1/***                           VSX extension                               ***/
2
3static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
4{
5    tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, true));
6}
7
8static inline void get_cpu_vsrl(TCGv_i64 dst, int n)
9{
10    tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, false));
11}
12
13static inline void set_cpu_vsrh(int n, TCGv_i64 src)
14{
15    tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, true));
16}
17
18static inline void set_cpu_vsrl(int n, TCGv_i64 src)
19{
20    tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, false));
21}
22
23static inline TCGv_ptr gen_vsr_ptr(int reg)
24{
25    TCGv_ptr r = tcg_temp_new_ptr();
26    tcg_gen_addi_ptr(r, cpu_env, vsr_full_offset(reg));
27    return r;
28}
29
30#define VSX_LOAD_SCALAR(name, operation)                      \
31static void gen_##name(DisasContext *ctx)                     \
32{                                                             \
33    TCGv EA;                                                  \
34    TCGv_i64 t0;                                              \
35    if (unlikely(!ctx->vsx_enabled)) {                        \
36        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
37        return;                                               \
38    }                                                         \
39    t0 = tcg_temp_new_i64();                                  \
40    gen_set_access_type(ctx, ACCESS_INT);                     \
41    EA = tcg_temp_new();                                      \
42    gen_addr_reg_index(ctx, EA);                              \
43    gen_qemu_##operation(ctx, t0, EA);                        \
44    set_cpu_vsrh(xT(ctx->opcode), t0);                        \
45    /* NOTE: cpu_vsrl is undefined */                         \
46    tcg_temp_free(EA);                                        \
47    tcg_temp_free_i64(t0);                                    \
48}
49
50VSX_LOAD_SCALAR(lxsdx, ld64_i64)
51VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
52VSX_LOAD_SCALAR(lxsibzx, ld8u_i64)
53VSX_LOAD_SCALAR(lxsihzx, ld16u_i64)
54VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
55VSX_LOAD_SCALAR(lxsspx, ld32fs)
56
57static void gen_lxvd2x(DisasContext *ctx)
58{
59    TCGv EA;
60    TCGv_i64 t0;
61    if (unlikely(!ctx->vsx_enabled)) {
62        gen_exception(ctx, POWERPC_EXCP_VSXU);
63        return;
64    }
65    t0 = tcg_temp_new_i64();
66    gen_set_access_type(ctx, ACCESS_INT);
67    EA = tcg_temp_new();
68    gen_addr_reg_index(ctx, EA);
69    gen_qemu_ld64_i64(ctx, t0, EA);
70    set_cpu_vsrh(xT(ctx->opcode), t0);
71    tcg_gen_addi_tl(EA, EA, 8);
72    gen_qemu_ld64_i64(ctx, t0, EA);
73    set_cpu_vsrl(xT(ctx->opcode), t0);
74    tcg_temp_free(EA);
75    tcg_temp_free_i64(t0);
76}
77
78static void gen_lxvw4x(DisasContext *ctx)
79{
80    TCGv EA;
81    TCGv_i64 xth;
82    TCGv_i64 xtl;
83    if (unlikely(!ctx->vsx_enabled)) {
84        gen_exception(ctx, POWERPC_EXCP_VSXU);
85        return;
86    }
87    xth = tcg_temp_new_i64();
88    xtl = tcg_temp_new_i64();
89
90    gen_set_access_type(ctx, ACCESS_INT);
91    EA = tcg_temp_new();
92
93    gen_addr_reg_index(ctx, EA);
94    if (ctx->le_mode) {
95        TCGv_i64 t0 = tcg_temp_new_i64();
96        TCGv_i64 t1 = tcg_temp_new_i64();
97
98        tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
99        tcg_gen_shri_i64(t1, t0, 32);
100        tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
101        tcg_gen_addi_tl(EA, EA, 8);
102        tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
103        tcg_gen_shri_i64(t1, t0, 32);
104        tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
105        tcg_temp_free_i64(t0);
106        tcg_temp_free_i64(t1);
107    } else {
108        tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
109        tcg_gen_addi_tl(EA, EA, 8);
110        tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
111    }
112    set_cpu_vsrh(xT(ctx->opcode), xth);
113    set_cpu_vsrl(xT(ctx->opcode), xtl);
114    tcg_temp_free(EA);
115    tcg_temp_free_i64(xth);
116    tcg_temp_free_i64(xtl);
117}
118
119static void gen_lxvwsx(DisasContext *ctx)
120{
121    TCGv EA;
122    TCGv_i32 data;
123
124    if (xT(ctx->opcode) < 32) {
125        if (unlikely(!ctx->vsx_enabled)) {
126            gen_exception(ctx, POWERPC_EXCP_VSXU);
127            return;
128        }
129    } else {
130        if (unlikely(!ctx->altivec_enabled)) {
131            gen_exception(ctx, POWERPC_EXCP_VPU);
132            return;
133        }
134    }
135
136    gen_set_access_type(ctx, ACCESS_INT);
137    EA = tcg_temp_new();
138
139    gen_addr_reg_index(ctx, EA);
140
141    data = tcg_temp_new_i32();
142    tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, MO_TEUL);
143    tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
144
145    tcg_temp_free(EA);
146    tcg_temp_free_i32(data);
147}
148
149static void gen_lxvdsx(DisasContext *ctx)
150{
151    TCGv EA;
152    TCGv_i64 data;
153
154    if (unlikely(!ctx->vsx_enabled)) {
155        gen_exception(ctx, POWERPC_EXCP_VSXU);
156        return;
157    }
158
159    gen_set_access_type(ctx, ACCESS_INT);
160    EA = tcg_temp_new();
161
162    gen_addr_reg_index(ctx, EA);
163
164    data = tcg_temp_new_i64();
165    tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, MO_TEQ);
166    tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
167
168    tcg_temp_free(EA);
169    tcg_temp_free_i64(data);
170}
171
172static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
173                          TCGv_i64 inh, TCGv_i64 inl)
174{
175    TCGv_i64 mask = tcg_const_i64(0x00FF00FF00FF00FF);
176    TCGv_i64 t0 = tcg_temp_new_i64();
177    TCGv_i64 t1 = tcg_temp_new_i64();
178
179    /* outh = ((inh & mask) << 8) | ((inh >> 8) & mask) */
180    tcg_gen_and_i64(t0, inh, mask);
181    tcg_gen_shli_i64(t0, t0, 8);
182    tcg_gen_shri_i64(t1, inh, 8);
183    tcg_gen_and_i64(t1, t1, mask);
184    tcg_gen_or_i64(outh, t0, t1);
185
186    /* outl = ((inl & mask) << 8) | ((inl >> 8) & mask) */
187    tcg_gen_and_i64(t0, inl, mask);
188    tcg_gen_shli_i64(t0, t0, 8);
189    tcg_gen_shri_i64(t1, inl, 8);
190    tcg_gen_and_i64(t1, t1, mask);
191    tcg_gen_or_i64(outl, t0, t1);
192
193    tcg_temp_free_i64(t0);
194    tcg_temp_free_i64(t1);
195    tcg_temp_free_i64(mask);
196}
197
198static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
199                          TCGv_i64 inh, TCGv_i64 inl)
200{
201    TCGv_i64 hi = tcg_temp_new_i64();
202    TCGv_i64 lo = tcg_temp_new_i64();
203
204    tcg_gen_bswap64_i64(hi, inh);
205    tcg_gen_bswap64_i64(lo, inl);
206    tcg_gen_shri_i64(outh, hi, 32);
207    tcg_gen_deposit_i64(outh, outh, hi, 32, 32);
208    tcg_gen_shri_i64(outl, lo, 32);
209    tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
210
211    tcg_temp_free_i64(hi);
212    tcg_temp_free_i64(lo);
213}
214static void gen_lxvh8x(DisasContext *ctx)
215{
216    TCGv EA;
217    TCGv_i64 xth;
218    TCGv_i64 xtl;
219
220    if (unlikely(!ctx->vsx_enabled)) {
221        gen_exception(ctx, POWERPC_EXCP_VSXU);
222        return;
223    }
224    xth = tcg_temp_new_i64();
225    xtl = tcg_temp_new_i64();
226    gen_set_access_type(ctx, ACCESS_INT);
227
228    EA = tcg_temp_new();
229    gen_addr_reg_index(ctx, EA);
230    tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
231    tcg_gen_addi_tl(EA, EA, 8);
232    tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
233    if (ctx->le_mode) {
234        gen_bswap16x8(xth, xtl, xth, xtl);
235    }
236    set_cpu_vsrh(xT(ctx->opcode), xth);
237    set_cpu_vsrl(xT(ctx->opcode), xtl);
238    tcg_temp_free(EA);
239    tcg_temp_free_i64(xth);
240    tcg_temp_free_i64(xtl);
241}
242
243static void gen_lxvb16x(DisasContext *ctx)
244{
245    TCGv EA;
246    TCGv_i64 xth;
247    TCGv_i64 xtl;
248
249    if (unlikely(!ctx->vsx_enabled)) {
250        gen_exception(ctx, POWERPC_EXCP_VSXU);
251        return;
252    }
253    xth = tcg_temp_new_i64();
254    xtl = tcg_temp_new_i64();
255    gen_set_access_type(ctx, ACCESS_INT);
256    EA = tcg_temp_new();
257    gen_addr_reg_index(ctx, EA);
258    tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
259    tcg_gen_addi_tl(EA, EA, 8);
260    tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
261    set_cpu_vsrh(xT(ctx->opcode), xth);
262    set_cpu_vsrl(xT(ctx->opcode), xtl);
263    tcg_temp_free(EA);
264    tcg_temp_free_i64(xth);
265    tcg_temp_free_i64(xtl);
266}
267
268#define VSX_VECTOR_LOAD(name, op, indexed)                  \
269static void gen_##name(DisasContext *ctx)                   \
270{                                                           \
271    int xt;                                                 \
272    TCGv EA;                                                \
273    TCGv_i64 xth;                                           \
274    TCGv_i64 xtl;                                           \
275                                                            \
276    if (indexed) {                                          \
277        xt = xT(ctx->opcode);                               \
278    } else {                                                \
279        xt = DQxT(ctx->opcode);                             \
280    }                                                       \
281                                                            \
282    if (xt < 32) {                                          \
283        if (unlikely(!ctx->vsx_enabled)) {                  \
284            gen_exception(ctx, POWERPC_EXCP_VSXU);          \
285            return;                                         \
286        }                                                   \
287    } else {                                                \
288        if (unlikely(!ctx->altivec_enabled)) {              \
289            gen_exception(ctx, POWERPC_EXCP_VPU);           \
290            return;                                         \
291        }                                                   \
292    }                                                       \
293    xth = tcg_temp_new_i64();                               \
294    xtl = tcg_temp_new_i64();                               \
295    gen_set_access_type(ctx, ACCESS_INT);                   \
296    EA = tcg_temp_new();                                    \
297    if (indexed) {                                          \
298        gen_addr_reg_index(ctx, EA);                        \
299    } else {                                                \
300        gen_addr_imm_index(ctx, EA, 0x0F);                  \
301    }                                                       \
302    if (ctx->le_mode) {                                     \
303        tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ);   \
304        set_cpu_vsrl(xt, xtl);                              \
305        tcg_gen_addi_tl(EA, EA, 8);                         \
306        tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ);   \
307        set_cpu_vsrh(xt, xth);                              \
308    } else {                                                \
309        tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ);   \
310        set_cpu_vsrh(xt, xth);                              \
311        tcg_gen_addi_tl(EA, EA, 8);                         \
312        tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ);   \
313        set_cpu_vsrl(xt, xtl);                              \
314    }                                                       \
315    tcg_temp_free(EA);                                      \
316    tcg_temp_free_i64(xth);                                 \
317    tcg_temp_free_i64(xtl);                                 \
318}
319
320VSX_VECTOR_LOAD(lxv, ld_i64, 0)
321VSX_VECTOR_LOAD(lxvx, ld_i64, 1)
322
323#define VSX_VECTOR_STORE(name, op, indexed)                 \
324static void gen_##name(DisasContext *ctx)                   \
325{                                                           \
326    int xt;                                                 \
327    TCGv EA;                                                \
328    TCGv_i64 xth;                                           \
329    TCGv_i64 xtl;                                           \
330                                                            \
331    if (indexed) {                                          \
332        xt = xT(ctx->opcode);                               \
333    } else {                                                \
334        xt = DQxT(ctx->opcode);                             \
335    }                                                       \
336                                                            \
337    if (xt < 32) {                                          \
338        if (unlikely(!ctx->vsx_enabled)) {                  \
339            gen_exception(ctx, POWERPC_EXCP_VSXU);          \
340            return;                                         \
341        }                                                   \
342    } else {                                                \
343        if (unlikely(!ctx->altivec_enabled)) {              \
344            gen_exception(ctx, POWERPC_EXCP_VPU);           \
345            return;                                         \
346        }                                                   \
347    }                                                       \
348    xth = tcg_temp_new_i64();                               \
349    xtl = tcg_temp_new_i64();                               \
350    get_cpu_vsrh(xth, xt);                                  \
351    get_cpu_vsrl(xtl, xt);                                  \
352    gen_set_access_type(ctx, ACCESS_INT);                   \
353    EA = tcg_temp_new();                                    \
354    if (indexed) {                                          \
355        gen_addr_reg_index(ctx, EA);                        \
356    } else {                                                \
357        gen_addr_imm_index(ctx, EA, 0x0F);                  \
358    }                                                       \
359    if (ctx->le_mode) {                                     \
360        tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ);   \
361        tcg_gen_addi_tl(EA, EA, 8);                         \
362        tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ);   \
363    } else {                                                \
364        tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ);   \
365        tcg_gen_addi_tl(EA, EA, 8);                         \
366        tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ);   \
367    }                                                       \
368    tcg_temp_free(EA);                                      \
369    tcg_temp_free_i64(xth);                                 \
370    tcg_temp_free_i64(xtl);                                 \
371}
372
373VSX_VECTOR_STORE(stxv, st_i64, 0)
374VSX_VECTOR_STORE(stxvx, st_i64, 1)
375
376#ifdef TARGET_PPC64
377#define VSX_VECTOR_LOAD_STORE_LENGTH(name)                         \
378static void gen_##name(DisasContext *ctx)                          \
379{                                                                  \
380    TCGv EA;                                                       \
381    TCGv_ptr xt;                                                   \
382                                                                   \
383    if (xT(ctx->opcode) < 32) {                                    \
384        if (unlikely(!ctx->vsx_enabled)) {                         \
385            gen_exception(ctx, POWERPC_EXCP_VSXU);                 \
386            return;                                                \
387        }                                                          \
388    } else {                                                       \
389        if (unlikely(!ctx->altivec_enabled)) {                     \
390            gen_exception(ctx, POWERPC_EXCP_VPU);                  \
391            return;                                                \
392        }                                                          \
393    }                                                              \
394    EA = tcg_temp_new();                                           \
395    xt = gen_vsr_ptr(xT(ctx->opcode));                             \
396    gen_set_access_type(ctx, ACCESS_INT);                          \
397    gen_addr_register(ctx, EA);                                    \
398    gen_helper_##name(cpu_env, EA, xt, cpu_gpr[rB(ctx->opcode)]);  \
399    tcg_temp_free(EA);                                             \
400    tcg_temp_free_ptr(xt);                                         \
401}
402
403VSX_VECTOR_LOAD_STORE_LENGTH(lxvl)
404VSX_VECTOR_LOAD_STORE_LENGTH(lxvll)
405VSX_VECTOR_LOAD_STORE_LENGTH(stxvl)
406VSX_VECTOR_LOAD_STORE_LENGTH(stxvll)
407#endif
408
409#define VSX_LOAD_SCALAR_DS(name, operation)                       \
410static void gen_##name(DisasContext *ctx)                         \
411{                                                                 \
412    TCGv EA;                                                      \
413    TCGv_i64 xth;                                                 \
414                                                                  \
415    if (unlikely(!ctx->altivec_enabled)) {                        \
416        gen_exception(ctx, POWERPC_EXCP_VPU);                     \
417        return;                                                   \
418    }                                                             \
419    xth = tcg_temp_new_i64();                                     \
420    gen_set_access_type(ctx, ACCESS_INT);                         \
421    EA = tcg_temp_new();                                          \
422    gen_addr_imm_index(ctx, EA, 0x03);                            \
423    gen_qemu_##operation(ctx, xth, EA);                           \
424    set_cpu_vsrh(rD(ctx->opcode) + 32, xth);                      \
425    /* NOTE: cpu_vsrl is undefined */                             \
426    tcg_temp_free(EA);                                            \
427    tcg_temp_free_i64(xth);                                       \
428}
429
430VSX_LOAD_SCALAR_DS(lxsd, ld64_i64)
431VSX_LOAD_SCALAR_DS(lxssp, ld32fs)
432
433#define VSX_STORE_SCALAR(name, operation)                     \
434static void gen_##name(DisasContext *ctx)                     \
435{                                                             \
436    TCGv EA;                                                  \
437    TCGv_i64 t0;                                              \
438    if (unlikely(!ctx->vsx_enabled)) {                        \
439        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
440        return;                                               \
441    }                                                         \
442    t0 = tcg_temp_new_i64();                                  \
443    gen_set_access_type(ctx, ACCESS_INT);                     \
444    EA = tcg_temp_new();                                      \
445    gen_addr_reg_index(ctx, EA);                              \
446    get_cpu_vsrh(t0, xS(ctx->opcode));                        \
447    gen_qemu_##operation(ctx, t0, EA);                        \
448    tcg_temp_free(EA);                                        \
449    tcg_temp_free_i64(t0);                                    \
450}
451
452VSX_STORE_SCALAR(stxsdx, st64_i64)
453
454VSX_STORE_SCALAR(stxsibx, st8_i64)
455VSX_STORE_SCALAR(stxsihx, st16_i64)
456VSX_STORE_SCALAR(stxsiwx, st32_i64)
457VSX_STORE_SCALAR(stxsspx, st32fs)
458
459static void gen_stxvd2x(DisasContext *ctx)
460{
461    TCGv EA;
462    TCGv_i64 t0;
463    if (unlikely(!ctx->vsx_enabled)) {
464        gen_exception(ctx, POWERPC_EXCP_VSXU);
465        return;
466    }
467    t0 = tcg_temp_new_i64();
468    gen_set_access_type(ctx, ACCESS_INT);
469    EA = tcg_temp_new();
470    gen_addr_reg_index(ctx, EA);
471    get_cpu_vsrh(t0, xS(ctx->opcode));
472    gen_qemu_st64_i64(ctx, t0, EA);
473    tcg_gen_addi_tl(EA, EA, 8);
474    get_cpu_vsrl(t0, xS(ctx->opcode));
475    gen_qemu_st64_i64(ctx, t0, EA);
476    tcg_temp_free(EA);
477    tcg_temp_free_i64(t0);
478}
479
480static void gen_stxvw4x(DisasContext *ctx)
481{
482    TCGv EA;
483    TCGv_i64 xsh;
484    TCGv_i64 xsl;
485
486    if (unlikely(!ctx->vsx_enabled)) {
487        gen_exception(ctx, POWERPC_EXCP_VSXU);
488        return;
489    }
490    xsh = tcg_temp_new_i64();
491    xsl = tcg_temp_new_i64();
492    get_cpu_vsrh(xsh, xS(ctx->opcode));
493    get_cpu_vsrl(xsl, xS(ctx->opcode));
494    gen_set_access_type(ctx, ACCESS_INT);
495    EA = tcg_temp_new();
496    gen_addr_reg_index(ctx, EA);
497    if (ctx->le_mode) {
498        TCGv_i64 t0 = tcg_temp_new_i64();
499        TCGv_i64 t1 = tcg_temp_new_i64();
500
501        tcg_gen_shri_i64(t0, xsh, 32);
502        tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
503        tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
504        tcg_gen_addi_tl(EA, EA, 8);
505        tcg_gen_shri_i64(t0, xsl, 32);
506        tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
507        tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
508        tcg_temp_free_i64(t0);
509        tcg_temp_free_i64(t1);
510    } else {
511        tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
512        tcg_gen_addi_tl(EA, EA, 8);
513        tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
514    }
515    tcg_temp_free(EA);
516    tcg_temp_free_i64(xsh);
517    tcg_temp_free_i64(xsl);
518}
519
520static void gen_stxvh8x(DisasContext *ctx)
521{
522    TCGv EA;
523    TCGv_i64 xsh;
524    TCGv_i64 xsl;
525
526    if (unlikely(!ctx->vsx_enabled)) {
527        gen_exception(ctx, POWERPC_EXCP_VSXU);
528        return;
529    }
530    xsh = tcg_temp_new_i64();
531    xsl = tcg_temp_new_i64();
532    get_cpu_vsrh(xsh, xS(ctx->opcode));
533    get_cpu_vsrl(xsl, xS(ctx->opcode));
534    gen_set_access_type(ctx, ACCESS_INT);
535    EA = tcg_temp_new();
536    gen_addr_reg_index(ctx, EA);
537    if (ctx->le_mode) {
538        TCGv_i64 outh = tcg_temp_new_i64();
539        TCGv_i64 outl = tcg_temp_new_i64();
540
541        gen_bswap16x8(outh, outl, xsh, xsl);
542        tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ);
543        tcg_gen_addi_tl(EA, EA, 8);
544        tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ);
545        tcg_temp_free_i64(outh);
546        tcg_temp_free_i64(outl);
547    } else {
548        tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
549        tcg_gen_addi_tl(EA, EA, 8);
550        tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
551    }
552    tcg_temp_free(EA);
553    tcg_temp_free_i64(xsh);
554    tcg_temp_free_i64(xsl);
555}
556
557static void gen_stxvb16x(DisasContext *ctx)
558{
559    TCGv EA;
560    TCGv_i64 xsh;
561    TCGv_i64 xsl;
562
563    if (unlikely(!ctx->vsx_enabled)) {
564        gen_exception(ctx, POWERPC_EXCP_VSXU);
565        return;
566    }
567    xsh = tcg_temp_new_i64();
568    xsl = tcg_temp_new_i64();
569    get_cpu_vsrh(xsh, xS(ctx->opcode));
570    get_cpu_vsrl(xsl, xS(ctx->opcode));
571    gen_set_access_type(ctx, ACCESS_INT);
572    EA = tcg_temp_new();
573    gen_addr_reg_index(ctx, EA);
574    tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
575    tcg_gen_addi_tl(EA, EA, 8);
576    tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
577    tcg_temp_free(EA);
578    tcg_temp_free_i64(xsh);
579    tcg_temp_free_i64(xsl);
580}
581
582#define VSX_STORE_SCALAR_DS(name, operation)                      \
583static void gen_##name(DisasContext *ctx)                         \
584{                                                                 \
585    TCGv EA;                                                      \
586    TCGv_i64 xth;                                                 \
587                                                                  \
588    if (unlikely(!ctx->altivec_enabled)) {                        \
589        gen_exception(ctx, POWERPC_EXCP_VPU);                     \
590        return;                                                   \
591    }                                                             \
592    xth = tcg_temp_new_i64();                                     \
593    get_cpu_vsrh(xth, rD(ctx->opcode) + 32);                      \
594    gen_set_access_type(ctx, ACCESS_INT);                         \
595    EA = tcg_temp_new();                                          \
596    gen_addr_imm_index(ctx, EA, 0x03);                            \
597    gen_qemu_##operation(ctx, xth, EA);                           \
598    /* NOTE: cpu_vsrl is undefined */                             \
599    tcg_temp_free(EA);                                            \
600    tcg_temp_free_i64(xth);                                       \
601}
602
603VSX_STORE_SCALAR_DS(stxsd, st64_i64)
604VSX_STORE_SCALAR_DS(stxssp, st32fs)
605
606static void gen_mfvsrwz(DisasContext *ctx)
607{
608    if (xS(ctx->opcode) < 32) {
609        if (unlikely(!ctx->fpu_enabled)) {
610            gen_exception(ctx, POWERPC_EXCP_FPU);
611            return;
612        }
613    } else {
614        if (unlikely(!ctx->altivec_enabled)) {
615            gen_exception(ctx, POWERPC_EXCP_VPU);
616            return;
617        }
618    }
619    TCGv_i64 tmp = tcg_temp_new_i64();
620    TCGv_i64 xsh = tcg_temp_new_i64();
621    get_cpu_vsrh(xsh, xS(ctx->opcode));
622    tcg_gen_ext32u_i64(tmp, xsh);
623    tcg_gen_trunc_i64_tl(cpu_gpr[rA(ctx->opcode)], tmp);
624    tcg_temp_free_i64(tmp);
625    tcg_temp_free_i64(xsh);
626}
627
628static void gen_mtvsrwa(DisasContext *ctx)
629{
630    if (xS(ctx->opcode) < 32) {
631        if (unlikely(!ctx->fpu_enabled)) {
632            gen_exception(ctx, POWERPC_EXCP_FPU);
633            return;
634        }
635    } else {
636        if (unlikely(!ctx->altivec_enabled)) {
637            gen_exception(ctx, POWERPC_EXCP_VPU);
638            return;
639        }
640    }
641    TCGv_i64 tmp = tcg_temp_new_i64();
642    TCGv_i64 xsh = tcg_temp_new_i64();
643    tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
644    tcg_gen_ext32s_i64(xsh, tmp);
645    set_cpu_vsrh(xT(ctx->opcode), xsh);
646    tcg_temp_free_i64(tmp);
647    tcg_temp_free_i64(xsh);
648}
649
650static void gen_mtvsrwz(DisasContext *ctx)
651{
652    if (xS(ctx->opcode) < 32) {
653        if (unlikely(!ctx->fpu_enabled)) {
654            gen_exception(ctx, POWERPC_EXCP_FPU);
655            return;
656        }
657    } else {
658        if (unlikely(!ctx->altivec_enabled)) {
659            gen_exception(ctx, POWERPC_EXCP_VPU);
660            return;
661        }
662    }
663    TCGv_i64 tmp = tcg_temp_new_i64();
664    TCGv_i64 xsh = tcg_temp_new_i64();
665    tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
666    tcg_gen_ext32u_i64(xsh, tmp);
667    set_cpu_vsrh(xT(ctx->opcode), xsh);
668    tcg_temp_free_i64(tmp);
669    tcg_temp_free_i64(xsh);
670}
671
672#if defined(TARGET_PPC64)
673static void gen_mfvsrd(DisasContext *ctx)
674{
675    TCGv_i64 t0;
676    if (xS(ctx->opcode) < 32) {
677        if (unlikely(!ctx->fpu_enabled)) {
678            gen_exception(ctx, POWERPC_EXCP_FPU);
679            return;
680        }
681    } else {
682        if (unlikely(!ctx->altivec_enabled)) {
683            gen_exception(ctx, POWERPC_EXCP_VPU);
684            return;
685        }
686    }
687    t0 = tcg_temp_new_i64();
688    get_cpu_vsrh(t0, xS(ctx->opcode));
689    tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
690    tcg_temp_free_i64(t0);
691}
692
693static void gen_mtvsrd(DisasContext *ctx)
694{
695    TCGv_i64 t0;
696    if (xS(ctx->opcode) < 32) {
697        if (unlikely(!ctx->fpu_enabled)) {
698            gen_exception(ctx, POWERPC_EXCP_FPU);
699            return;
700        }
701    } else {
702        if (unlikely(!ctx->altivec_enabled)) {
703            gen_exception(ctx, POWERPC_EXCP_VPU);
704            return;
705        }
706    }
707    t0 = tcg_temp_new_i64();
708    tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
709    set_cpu_vsrh(xT(ctx->opcode), t0);
710    tcg_temp_free_i64(t0);
711}
712
713static void gen_mfvsrld(DisasContext *ctx)
714{
715    TCGv_i64 t0;
716    if (xS(ctx->opcode) < 32) {
717        if (unlikely(!ctx->vsx_enabled)) {
718            gen_exception(ctx, POWERPC_EXCP_VSXU);
719            return;
720        }
721    } else {
722        if (unlikely(!ctx->altivec_enabled)) {
723            gen_exception(ctx, POWERPC_EXCP_VPU);
724            return;
725        }
726    }
727    t0 = tcg_temp_new_i64();
728    get_cpu_vsrl(t0, xS(ctx->opcode));
729    tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
730    tcg_temp_free_i64(t0);
731}
732
733static void gen_mtvsrdd(DisasContext *ctx)
734{
735    TCGv_i64 t0;
736    if (xT(ctx->opcode) < 32) {
737        if (unlikely(!ctx->vsx_enabled)) {
738            gen_exception(ctx, POWERPC_EXCP_VSXU);
739            return;
740        }
741    } else {
742        if (unlikely(!ctx->altivec_enabled)) {
743            gen_exception(ctx, POWERPC_EXCP_VPU);
744            return;
745        }
746    }
747
748    t0 = tcg_temp_new_i64();
749    if (!rA(ctx->opcode)) {
750        tcg_gen_movi_i64(t0, 0);
751    } else {
752        tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
753    }
754    set_cpu_vsrh(xT(ctx->opcode), t0);
755
756    tcg_gen_mov_i64(t0, cpu_gpr[rB(ctx->opcode)]);
757    set_cpu_vsrl(xT(ctx->opcode), t0);
758    tcg_temp_free_i64(t0);
759}
760
761static void gen_mtvsrws(DisasContext *ctx)
762{
763    TCGv_i64 t0;
764    if (xT(ctx->opcode) < 32) {
765        if (unlikely(!ctx->vsx_enabled)) {
766            gen_exception(ctx, POWERPC_EXCP_VSXU);
767            return;
768        }
769    } else {
770        if (unlikely(!ctx->altivec_enabled)) {
771            gen_exception(ctx, POWERPC_EXCP_VPU);
772            return;
773        }
774    }
775
776    t0 = tcg_temp_new_i64();
777    tcg_gen_deposit_i64(t0, cpu_gpr[rA(ctx->opcode)],
778                        cpu_gpr[rA(ctx->opcode)], 32, 32);
779    set_cpu_vsrl(xT(ctx->opcode), t0);
780    set_cpu_vsrh(xT(ctx->opcode), t0);
781    tcg_temp_free_i64(t0);
782}
783
784#endif
785
786static void gen_xxpermdi(DisasContext *ctx)
787{
788    TCGv_i64 xh, xl;
789
790    if (unlikely(!ctx->vsx_enabled)) {
791        gen_exception(ctx, POWERPC_EXCP_VSXU);
792        return;
793    }
794
795    xh = tcg_temp_new_i64();
796    xl = tcg_temp_new_i64();
797
798    if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
799                 (xT(ctx->opcode) == xB(ctx->opcode)))) {
800        if ((DM(ctx->opcode) & 2) == 0) {
801            get_cpu_vsrh(xh, xA(ctx->opcode));
802        } else {
803            get_cpu_vsrl(xh, xA(ctx->opcode));
804        }
805        if ((DM(ctx->opcode) & 1) == 0) {
806            get_cpu_vsrh(xl, xB(ctx->opcode));
807        } else {
808            get_cpu_vsrl(xl, xB(ctx->opcode));
809        }
810
811        set_cpu_vsrh(xT(ctx->opcode), xh);
812        set_cpu_vsrl(xT(ctx->opcode), xl);
813    } else {
814        if ((DM(ctx->opcode) & 2) == 0) {
815            get_cpu_vsrh(xh, xA(ctx->opcode));
816            set_cpu_vsrh(xT(ctx->opcode), xh);
817        } else {
818            get_cpu_vsrl(xh, xA(ctx->opcode));
819            set_cpu_vsrh(xT(ctx->opcode), xh);
820        }
821        if ((DM(ctx->opcode) & 1) == 0) {
822            get_cpu_vsrh(xl, xB(ctx->opcode));
823            set_cpu_vsrl(xT(ctx->opcode), xl);
824        } else {
825            get_cpu_vsrl(xl, xB(ctx->opcode));
826            set_cpu_vsrl(xT(ctx->opcode), xl);
827        }
828    }
829    tcg_temp_free_i64(xh);
830    tcg_temp_free_i64(xl);
831}
832
833#define OP_ABS 1
834#define OP_NABS 2
835#define OP_NEG 3
836#define OP_CPSGN 4
837#define SGN_MASK_DP  0x8000000000000000ull
838#define SGN_MASK_SP 0x8000000080000000ull
839
840#define VSX_SCALAR_MOVE(name, op, sgn_mask)                       \
841static void glue(gen_, name)(DisasContext *ctx)                   \
842    {                                                             \
843        TCGv_i64 xb, sgm;                                         \
844        if (unlikely(!ctx->vsx_enabled)) {                        \
845            gen_exception(ctx, POWERPC_EXCP_VSXU);                \
846            return;                                               \
847        }                                                         \
848        xb = tcg_temp_new_i64();                                  \
849        sgm = tcg_temp_new_i64();                                 \
850        get_cpu_vsrh(xb, xB(ctx->opcode));                        \
851        tcg_gen_movi_i64(sgm, sgn_mask);                          \
852        switch (op) {                                             \
853            case OP_ABS: {                                        \
854                tcg_gen_andc_i64(xb, xb, sgm);                    \
855                break;                                            \
856            }                                                     \
857            case OP_NABS: {                                       \
858                tcg_gen_or_i64(xb, xb, sgm);                      \
859                break;                                            \
860            }                                                     \
861            case OP_NEG: {                                        \
862                tcg_gen_xor_i64(xb, xb, sgm);                     \
863                break;                                            \
864            }                                                     \
865            case OP_CPSGN: {                                      \
866                TCGv_i64 xa = tcg_temp_new_i64();                 \
867                get_cpu_vsrh(xa, xA(ctx->opcode));                \
868                tcg_gen_and_i64(xa, xa, sgm);                     \
869                tcg_gen_andc_i64(xb, xb, sgm);                    \
870                tcg_gen_or_i64(xb, xb, xa);                       \
871                tcg_temp_free_i64(xa);                            \
872                break;                                            \
873            }                                                     \
874        }                                                         \
875        set_cpu_vsrh(xT(ctx->opcode), xb);                        \
876        tcg_temp_free_i64(xb);                                    \
877        tcg_temp_free_i64(sgm);                                   \
878    }
879
880VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
881VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
882VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
883VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
884
885#define VSX_SCALAR_MOVE_QP(name, op, sgn_mask)                    \
886static void glue(gen_, name)(DisasContext *ctx)                   \
887{                                                                 \
888    int xa;                                                       \
889    int xt = rD(ctx->opcode) + 32;                                \
890    int xb = rB(ctx->opcode) + 32;                                \
891    TCGv_i64 xah, xbh, xbl, sgm, tmp;                             \
892                                                                  \
893    if (unlikely(!ctx->vsx_enabled)) {                            \
894        gen_exception(ctx, POWERPC_EXCP_VSXU);                    \
895        return;                                                   \
896    }                                                             \
897    xbh = tcg_temp_new_i64();                                     \
898    xbl = tcg_temp_new_i64();                                     \
899    sgm = tcg_temp_new_i64();                                     \
900    tmp = tcg_temp_new_i64();                                     \
901    get_cpu_vsrh(xbh, xb);                                        \
902    get_cpu_vsrl(xbl, xb);                                        \
903    tcg_gen_movi_i64(sgm, sgn_mask);                              \
904    switch (op) {                                                 \
905    case OP_ABS:                                                  \
906        tcg_gen_andc_i64(xbh, xbh, sgm);                          \
907        break;                                                    \
908    case OP_NABS:                                                 \
909        tcg_gen_or_i64(xbh, xbh, sgm);                            \
910        break;                                                    \
911    case OP_NEG:                                                  \
912        tcg_gen_xor_i64(xbh, xbh, sgm);                           \
913        break;                                                    \
914    case OP_CPSGN:                                                \
915        xah = tcg_temp_new_i64();                                 \
916        xa = rA(ctx->opcode) + 32;                                \
917        get_cpu_vsrh(tmp, xa);                                    \
918        tcg_gen_and_i64(xah, tmp, sgm);                           \
919        tcg_gen_andc_i64(xbh, xbh, sgm);                          \
920        tcg_gen_or_i64(xbh, xbh, xah);                            \
921        tcg_temp_free_i64(xah);                                   \
922        break;                                                    \
923    }                                                             \
924    set_cpu_vsrh(xt, xbh);                                        \
925    set_cpu_vsrl(xt, xbl);                                        \
926    tcg_temp_free_i64(xbl);                                       \
927    tcg_temp_free_i64(xbh);                                       \
928    tcg_temp_free_i64(sgm);                                       \
929    tcg_temp_free_i64(tmp);                                       \
930}
931
932VSX_SCALAR_MOVE_QP(xsabsqp, OP_ABS, SGN_MASK_DP)
933VSX_SCALAR_MOVE_QP(xsnabsqp, OP_NABS, SGN_MASK_DP)
934VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP)
935VSX_SCALAR_MOVE_QP(xscpsgnqp, OP_CPSGN, SGN_MASK_DP)
936
937#define VSX_VECTOR_MOVE(name, op, sgn_mask)                      \
938static void glue(gen_, name)(DisasContext *ctx)                  \
939    {                                                            \
940        TCGv_i64 xbh, xbl, sgm;                                  \
941        if (unlikely(!ctx->vsx_enabled)) {                       \
942            gen_exception(ctx, POWERPC_EXCP_VSXU);               \
943            return;                                              \
944        }                                                        \
945        xbh = tcg_temp_new_i64();                                \
946        xbl = tcg_temp_new_i64();                                \
947        sgm = tcg_temp_new_i64();                                \
948        get_cpu_vsrh(xbh, xB(ctx->opcode));                      \
949        get_cpu_vsrl(xbl, xB(ctx->opcode));                      \
950        tcg_gen_movi_i64(sgm, sgn_mask);                         \
951        switch (op) {                                            \
952            case OP_ABS: {                                       \
953                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
954                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
955                break;                                           \
956            }                                                    \
957            case OP_NABS: {                                      \
958                tcg_gen_or_i64(xbh, xbh, sgm);                   \
959                tcg_gen_or_i64(xbl, xbl, sgm);                   \
960                break;                                           \
961            }                                                    \
962            case OP_NEG: {                                       \
963                tcg_gen_xor_i64(xbh, xbh, sgm);                  \
964                tcg_gen_xor_i64(xbl, xbl, sgm);                  \
965                break;                                           \
966            }                                                    \
967            case OP_CPSGN: {                                     \
968                TCGv_i64 xah = tcg_temp_new_i64();               \
969                TCGv_i64 xal = tcg_temp_new_i64();               \
970                get_cpu_vsrh(xah, xA(ctx->opcode));              \
971                get_cpu_vsrl(xal, xA(ctx->opcode));              \
972                tcg_gen_and_i64(xah, xah, sgm);                  \
973                tcg_gen_and_i64(xal, xal, sgm);                  \
974                tcg_gen_andc_i64(xbh, xbh, sgm);                 \
975                tcg_gen_andc_i64(xbl, xbl, sgm);                 \
976                tcg_gen_or_i64(xbh, xbh, xah);                   \
977                tcg_gen_or_i64(xbl, xbl, xal);                   \
978                tcg_temp_free_i64(xah);                          \
979                tcg_temp_free_i64(xal);                          \
980                break;                                           \
981            }                                                    \
982        }                                                        \
983        set_cpu_vsrh(xT(ctx->opcode), xbh);                      \
984        set_cpu_vsrl(xT(ctx->opcode), xbl);                      \
985        tcg_temp_free_i64(xbh);                                  \
986        tcg_temp_free_i64(xbl);                                  \
987        tcg_temp_free_i64(sgm);                                  \
988    }
989
990VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
991VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
992VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
993VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
994VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
995VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
996VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
997VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
998
999#define VSX_CMP(name, op1, op2, inval, type)                                  \
1000static void gen_##name(DisasContext *ctx)                                     \
1001{                                                                             \
1002    TCGv_i32 ignored;                                                         \
1003    TCGv_ptr xt, xa, xb;                                                      \
1004    if (unlikely(!ctx->vsx_enabled)) {                                        \
1005        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1006        return;                                                               \
1007    }                                                                         \
1008    xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
1009    xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
1010    xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
1011    if ((ctx->opcode >> (31 - 21)) & 1) {                                     \
1012        gen_helper_##name(cpu_crf[6], cpu_env, xt, xa, xb);                   \
1013    } else {                                                                  \
1014        ignored = tcg_temp_new_i32();                                         \
1015        gen_helper_##name(ignored, cpu_env, xt, xa, xb);                      \
1016        tcg_temp_free_i32(ignored);                                           \
1017    }                                                                         \
1018    gen_helper_float_check_status(cpu_env);                                   \
1019    tcg_temp_free_ptr(xt);                                                    \
1020    tcg_temp_free_ptr(xa);                                                    \
1021    tcg_temp_free_ptr(xb);                                                    \
1022}
1023
1024VSX_CMP(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
1025VSX_CMP(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
1026VSX_CMP(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
1027VSX_CMP(xvcmpnedp, 0x0C, 0x0F, 0, PPC2_ISA300)
1028VSX_CMP(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
1029VSX_CMP(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
1030VSX_CMP(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
1031VSX_CMP(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX)
1032
1033static void gen_xscvqpdp(DisasContext *ctx)
1034{
1035    TCGv_i32 opc;
1036    TCGv_ptr xt, xb;
1037    if (unlikely(!ctx->vsx_enabled)) {
1038        gen_exception(ctx, POWERPC_EXCP_VSXU);
1039        return;
1040    }
1041    opc = tcg_const_i32(ctx->opcode);
1042    xt = gen_vsr_ptr(xT(ctx->opcode));
1043    xb = gen_vsr_ptr(xB(ctx->opcode));
1044    gen_helper_xscvqpdp(cpu_env, opc, xt, xb);
1045    tcg_temp_free_i32(opc);
1046    tcg_temp_free_ptr(xt);
1047    tcg_temp_free_ptr(xb);
1048}
1049
1050#define GEN_VSX_HELPER_2(name, op1, op2, inval, type)                         \
1051static void gen_##name(DisasContext *ctx)                                     \
1052{                                                                             \
1053    TCGv_i32 opc;                                                             \
1054    if (unlikely(!ctx->vsx_enabled)) {                                        \
1055        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1056        return;                                                               \
1057    }                                                                         \
1058    opc = tcg_const_i32(ctx->opcode);                                         \
1059    gen_helper_##name(cpu_env, opc);                                          \
1060    tcg_temp_free_i32(opc);                                                   \
1061}
1062
1063#define GEN_VSX_HELPER_X3(name, op1, op2, inval, type)                        \
1064static void gen_##name(DisasContext *ctx)                                     \
1065{                                                                             \
1066    TCGv_ptr xt, xa, xb;                                                      \
1067    if (unlikely(!ctx->vsx_enabled)) {                                        \
1068        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1069        return;                                                               \
1070    }                                                                         \
1071    xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
1072    xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
1073    xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
1074    gen_helper_##name(cpu_env, xt, xa, xb);                                   \
1075    tcg_temp_free_ptr(xt);                                                    \
1076    tcg_temp_free_ptr(xa);                                                    \
1077    tcg_temp_free_ptr(xb);                                                    \
1078}
1079
1080#define GEN_VSX_HELPER_X2(name, op1, op2, inval, type)                        \
1081static void gen_##name(DisasContext *ctx)                                     \
1082{                                                                             \
1083    TCGv_ptr xt, xb;                                                          \
1084    if (unlikely(!ctx->vsx_enabled)) {                                        \
1085        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1086        return;                                                               \
1087    }                                                                         \
1088    xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
1089    xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
1090    gen_helper_##name(cpu_env, xt, xb);                                       \
1091    tcg_temp_free_ptr(xt);                                                    \
1092    tcg_temp_free_ptr(xb);                                                    \
1093}
1094
1095#define GEN_VSX_HELPER_X2_AB(name, op1, op2, inval, type)                     \
1096static void gen_##name(DisasContext *ctx)                                     \
1097{                                                                             \
1098    TCGv_i32 opc;                                                             \
1099    TCGv_ptr xa, xb;                                                          \
1100    if (unlikely(!ctx->vsx_enabled)) {                                        \
1101        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1102        return;                                                               \
1103    }                                                                         \
1104    opc = tcg_const_i32(ctx->opcode);                                         \
1105    xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
1106    xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
1107    gen_helper_##name(cpu_env, opc, xa, xb);                                  \
1108    tcg_temp_free_i32(opc);                                                   \
1109    tcg_temp_free_ptr(xa);                                                    \
1110    tcg_temp_free_ptr(xb);                                                    \
1111}
1112
1113#define GEN_VSX_HELPER_X1(name, op1, op2, inval, type)                        \
1114static void gen_##name(DisasContext *ctx)                                     \
1115{                                                                             \
1116    TCGv_i32 opc;                                                             \
1117    TCGv_ptr xb;                                                              \
1118    if (unlikely(!ctx->vsx_enabled)) {                                        \
1119        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1120        return;                                                               \
1121    }                                                                         \
1122    opc = tcg_const_i32(ctx->opcode);                                         \
1123    xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
1124    gen_helper_##name(cpu_env, opc, xb);                                      \
1125    tcg_temp_free_i32(opc);                                                   \
1126    tcg_temp_free_ptr(xb);                                                    \
1127}
1128
1129#define GEN_VSX_HELPER_R3(name, op1, op2, inval, type)                        \
1130static void gen_##name(DisasContext *ctx)                                     \
1131{                                                                             \
1132    TCGv_i32 opc;                                                             \
1133    TCGv_ptr xt, xa, xb;                                                      \
1134    if (unlikely(!ctx->vsx_enabled)) {                                        \
1135        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1136        return;                                                               \
1137    }                                                                         \
1138    opc = tcg_const_i32(ctx->opcode);                                         \
1139    xt = gen_vsr_ptr(rD(ctx->opcode) + 32);                                   \
1140    xa = gen_vsr_ptr(rA(ctx->opcode) + 32);                                   \
1141    xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
1142    gen_helper_##name(cpu_env, opc, xt, xa, xb);                              \
1143    tcg_temp_free_i32(opc);                                                   \
1144    tcg_temp_free_ptr(xt);                                                    \
1145    tcg_temp_free_ptr(xa);                                                    \
1146    tcg_temp_free_ptr(xb);                                                    \
1147}
1148
1149#define GEN_VSX_HELPER_R2(name, op1, op2, inval, type)                        \
1150static void gen_##name(DisasContext *ctx)                                     \
1151{                                                                             \
1152    TCGv_i32 opc;                                                             \
1153    TCGv_ptr xt, xb;                                                          \
1154    if (unlikely(!ctx->vsx_enabled)) {                                        \
1155        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1156        return;                                                               \
1157    }                                                                         \
1158    opc = tcg_const_i32(ctx->opcode);                                         \
1159    xt = gen_vsr_ptr(rD(ctx->opcode) + 32);                                   \
1160    xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
1161    gen_helper_##name(cpu_env, opc, xt, xb);                                  \
1162    tcg_temp_free_i32(opc);                                                   \
1163    tcg_temp_free_ptr(xt);                                                    \
1164    tcg_temp_free_ptr(xb);                                                    \
1165}
1166
1167#define GEN_VSX_HELPER_R2_AB(name, op1, op2, inval, type)                     \
1168static void gen_##name(DisasContext *ctx)                                     \
1169{                                                                             \
1170    TCGv_i32 opc;                                                             \
1171    TCGv_ptr xa, xb;                                                          \
1172    if (unlikely(!ctx->vsx_enabled)) {                                        \
1173        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1174        return;                                                               \
1175    }                                                                         \
1176    opc = tcg_const_i32(ctx->opcode);                                         \
1177    xa = gen_vsr_ptr(rA(ctx->opcode) + 32);                                   \
1178    xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
1179    gen_helper_##name(cpu_env, opc, xa, xb);                                  \
1180    tcg_temp_free_i32(opc);                                                   \
1181    tcg_temp_free_ptr(xa);                                                    \
1182    tcg_temp_free_ptr(xb);                                                    \
1183}
1184
1185#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
1186static void gen_##name(DisasContext *ctx)                     \
1187{                                                             \
1188    TCGv_i64 t0;                                              \
1189    TCGv_i64 t1;                                              \
1190    if (unlikely(!ctx->vsx_enabled)) {                        \
1191        gen_exception(ctx, POWERPC_EXCP_VSXU);                \
1192        return;                                               \
1193    }                                                         \
1194    t0 = tcg_temp_new_i64();                                  \
1195    t1 = tcg_temp_new_i64();                                  \
1196    get_cpu_vsrh(t0, xB(ctx->opcode));                        \
1197    gen_helper_##name(t1, cpu_env, t0);                       \
1198    set_cpu_vsrh(xT(ctx->opcode), t1);                        \
1199    tcg_temp_free_i64(t0);                                    \
1200    tcg_temp_free_i64(t1);                                    \
1201}
1202
1203GEN_VSX_HELPER_X3(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
1204GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300)
1205GEN_VSX_HELPER_X3(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
1206GEN_VSX_HELPER_X3(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
1207GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300)
1208GEN_VSX_HELPER_X3(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
1209GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300)
1210GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
1211GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
1212GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
1213GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
1214GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
1215GEN_VSX_HELPER_X3(xscmpeqdp, 0x0C, 0x00, 0, PPC2_ISA300)
1216GEN_VSX_HELPER_X3(xscmpgtdp, 0x0C, 0x01, 0, PPC2_ISA300)
1217GEN_VSX_HELPER_X3(xscmpgedp, 0x0C, 0x02, 0, PPC2_ISA300)
1218GEN_VSX_HELPER_X3(xscmpnedp, 0x0C, 0x03, 0, PPC2_ISA300)
1219GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300)
1220GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300)
1221GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
1222GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
1223GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX)
1224GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX)
1225GEN_VSX_HELPER_X3(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
1226GEN_VSX_HELPER_X3(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
1227GEN_VSX_HELPER_R3(xsmaxcdp, 0x00, 0x10, 0, PPC2_ISA300)
1228GEN_VSX_HELPER_R3(xsmincdp, 0x00, 0x11, 0, PPC2_ISA300)
1229GEN_VSX_HELPER_R3(xsmaxjdp, 0x00, 0x12, 0, PPC2_ISA300)
1230GEN_VSX_HELPER_R3(xsminjdp, 0x00, 0x12, 0, PPC2_ISA300)
1231GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300)
1232GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
1233GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
1234GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207)
1235GEN_VSX_HELPER_R2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300)
1236GEN_VSX_HELPER_R2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300)
1237GEN_VSX_HELPER_R2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300)
1238GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300)
1239GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
1240GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
1241GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
1242GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
1243GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
1244GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
1245GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
1246GEN_VSX_HELPER_X2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
1247GEN_VSX_HELPER_X2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
1248GEN_VSX_HELPER_R2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300)
1249GEN_VSX_HELPER_X2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
1250GEN_VSX_HELPER_X2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
1251GEN_VSX_HELPER_X2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
1252GEN_VSX_HELPER_X2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
1253GEN_VSX_HELPER_X2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
1254GEN_VSX_HELPER_X2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
1255GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207)
1256GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300)
1257GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300)
1258GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300)
1259GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300)
1260GEN_VSX_HELPER_X3(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
1261GEN_VSX_HELPER_X3(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
1262GEN_VSX_HELPER_X3(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
1263GEN_VSX_HELPER_X3(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
1264GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
1265GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
1266GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
1267GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
1268GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
1269GEN_VSX_HELPER_X1(xststdcsp, 0x14, 0x12, 0, PPC2_ISA300)
1270GEN_VSX_HELPER_2(xststdcdp, 0x14, 0x16, 0, PPC2_ISA300)
1271GEN_VSX_HELPER_2(xststdcqp, 0x04, 0x16, 0, PPC2_ISA300)
1272
1273GEN_VSX_HELPER_X3(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
1274GEN_VSX_HELPER_X3(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
1275GEN_VSX_HELPER_X3(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
1276GEN_VSX_HELPER_X3(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
1277GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
1278GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
1279GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
1280GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
1281GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
1282GEN_VSX_HELPER_X3(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
1283GEN_VSX_HELPER_X3(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
1284GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
1285GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
1286GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
1287GEN_VSX_HELPER_X2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
1288GEN_VSX_HELPER_X2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
1289GEN_VSX_HELPER_X2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
1290GEN_VSX_HELPER_X2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
1291GEN_VSX_HELPER_X2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
1292GEN_VSX_HELPER_X2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
1293GEN_VSX_HELPER_X2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
1294GEN_VSX_HELPER_X2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
1295GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
1296GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
1297GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
1298
1299GEN_VSX_HELPER_X3(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
1300GEN_VSX_HELPER_X3(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
1301GEN_VSX_HELPER_X3(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
1302GEN_VSX_HELPER_X3(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
1303GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
1304GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
1305GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
1306GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
1307GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
1308GEN_VSX_HELPER_X3(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
1309GEN_VSX_HELPER_X3(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
1310GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
1311GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300)
1312GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300)
1313GEN_VSX_HELPER_X2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
1314GEN_VSX_HELPER_X2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
1315GEN_VSX_HELPER_X2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
1316GEN_VSX_HELPER_X2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
1317GEN_VSX_HELPER_X2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
1318GEN_VSX_HELPER_X2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
1319GEN_VSX_HELPER_X2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
1320GEN_VSX_HELPER_X2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
1321GEN_VSX_HELPER_X2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
1322GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
1323GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
1324GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
1325GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
1326GEN_VSX_HELPER_2(xvtstdcsp, 0x14, 0x1A, 0, PPC2_VSX)
1327GEN_VSX_HELPER_2(xvtstdcdp, 0x14, 0x1E, 0, PPC2_VSX)
1328GEN_VSX_HELPER_X3(xxperm, 0x08, 0x03, 0, PPC2_ISA300)
1329GEN_VSX_HELPER_X3(xxpermr, 0x08, 0x07, 0, PPC2_ISA300)
1330
1331#define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type)             \
1332static void gen_##name(DisasContext *ctx)                                     \
1333{                                                                             \
1334    TCGv_ptr xt, xa, b, c;                                                    \
1335    if (unlikely(!ctx->vsx_enabled)) {                                        \
1336        gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
1337        return;                                                               \
1338    }                                                                         \
1339    xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
1340    xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
1341    if (ctx->opcode & PPC_BIT32(25)) {                                        \
1342        /*                                                                    \
1343         * AxT + B                                                            \
1344         */                                                                   \
1345        b = gen_vsr_ptr(xT(ctx->opcode));                                     \
1346        c = gen_vsr_ptr(xB(ctx->opcode));                                     \
1347    } else {                                                                  \
1348        /*                                                                    \
1349         * AxB + T                                                            \
1350         */                                                                   \
1351        b = gen_vsr_ptr(xB(ctx->opcode));                                     \
1352        c = gen_vsr_ptr(xT(ctx->opcode));                                     \
1353    }                                                                         \
1354    gen_helper_##name(cpu_env, xt, xa, b, c);                                 \
1355    tcg_temp_free_ptr(xt);                                                    \
1356    tcg_temp_free_ptr(xa);                                                    \
1357    tcg_temp_free_ptr(b);                                                     \
1358    tcg_temp_free_ptr(c);                                                     \
1359}
1360
1361GEN_VSX_HELPER_VSX_MADD(xsmadddp, 0x04, 0x04, 0x05, 0, PPC2_VSX)
1362GEN_VSX_HELPER_VSX_MADD(xsmsubdp, 0x04, 0x06, 0x07, 0, PPC2_VSX)
1363GEN_VSX_HELPER_VSX_MADD(xsnmadddp, 0x04, 0x14, 0x15, 0, PPC2_VSX)
1364GEN_VSX_HELPER_VSX_MADD(xsnmsubdp, 0x04, 0x16, 0x17, 0, PPC2_VSX)
1365GEN_VSX_HELPER_VSX_MADD(xsmaddsp, 0x04, 0x00, 0x01, 0, PPC2_VSX207)
1366GEN_VSX_HELPER_VSX_MADD(xsmsubsp, 0x04, 0x02, 0x03, 0, PPC2_VSX207)
1367GEN_VSX_HELPER_VSX_MADD(xsnmaddsp, 0x04, 0x10, 0x11, 0, PPC2_VSX207)
1368GEN_VSX_HELPER_VSX_MADD(xsnmsubsp, 0x04, 0x12, 0x13, 0, PPC2_VSX207)
1369GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX)
1370GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX)
1371GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX)
1372GEN_VSX_HELPER_VSX_MADD(xvnmsubdp, 0x04, 0x1E, 0x1F, 0, PPC2_VSX)
1373GEN_VSX_HELPER_VSX_MADD(xvmaddsp, 0x04, 0x08, 0x09, 0, PPC2_VSX)
1374GEN_VSX_HELPER_VSX_MADD(xvmsubsp, 0x04, 0x0A, 0x0B, 0, PPC2_VSX)
1375GEN_VSX_HELPER_VSX_MADD(xvnmaddsp, 0x04, 0x18, 0x19, 0, PPC2_VSX)
1376GEN_VSX_HELPER_VSX_MADD(xvnmsubsp, 0x04, 0x1A, 0x1B, 0, PPC2_VSX)
1377
1378static void gen_xxbrd(DisasContext *ctx)
1379{
1380    TCGv_i64 xth;
1381    TCGv_i64 xtl;
1382    TCGv_i64 xbh;
1383    TCGv_i64 xbl;
1384
1385    if (unlikely(!ctx->vsx_enabled)) {
1386        gen_exception(ctx, POWERPC_EXCP_VSXU);
1387        return;
1388    }
1389    xth = tcg_temp_new_i64();
1390    xtl = tcg_temp_new_i64();
1391    xbh = tcg_temp_new_i64();
1392    xbl = tcg_temp_new_i64();
1393    get_cpu_vsrh(xbh, xB(ctx->opcode));
1394    get_cpu_vsrl(xbl, xB(ctx->opcode));
1395
1396    tcg_gen_bswap64_i64(xth, xbh);
1397    tcg_gen_bswap64_i64(xtl, xbl);
1398    set_cpu_vsrh(xT(ctx->opcode), xth);
1399    set_cpu_vsrl(xT(ctx->opcode), xtl);
1400
1401    tcg_temp_free_i64(xth);
1402    tcg_temp_free_i64(xtl);
1403    tcg_temp_free_i64(xbh);
1404    tcg_temp_free_i64(xbl);
1405}
1406
1407static void gen_xxbrh(DisasContext *ctx)
1408{
1409    TCGv_i64 xth;
1410    TCGv_i64 xtl;
1411    TCGv_i64 xbh;
1412    TCGv_i64 xbl;
1413
1414    if (unlikely(!ctx->vsx_enabled)) {
1415        gen_exception(ctx, POWERPC_EXCP_VSXU);
1416        return;
1417    }
1418    xth = tcg_temp_new_i64();
1419    xtl = tcg_temp_new_i64();
1420    xbh = tcg_temp_new_i64();
1421    xbl = tcg_temp_new_i64();
1422    get_cpu_vsrh(xbh, xB(ctx->opcode));
1423    get_cpu_vsrl(xbl, xB(ctx->opcode));
1424
1425    gen_bswap16x8(xth, xtl, xbh, xbl);
1426    set_cpu_vsrh(xT(ctx->opcode), xth);
1427    set_cpu_vsrl(xT(ctx->opcode), xtl);
1428
1429    tcg_temp_free_i64(xth);
1430    tcg_temp_free_i64(xtl);
1431    tcg_temp_free_i64(xbh);
1432    tcg_temp_free_i64(xbl);
1433}
1434
1435static void gen_xxbrq(DisasContext *ctx)
1436{
1437    TCGv_i64 xth;
1438    TCGv_i64 xtl;
1439    TCGv_i64 xbh;
1440    TCGv_i64 xbl;
1441    TCGv_i64 t0;
1442
1443    if (unlikely(!ctx->vsx_enabled)) {
1444        gen_exception(ctx, POWERPC_EXCP_VSXU);
1445        return;
1446    }
1447    xth = tcg_temp_new_i64();
1448    xtl = tcg_temp_new_i64();
1449    xbh = tcg_temp_new_i64();
1450    xbl = tcg_temp_new_i64();
1451    get_cpu_vsrh(xbh, xB(ctx->opcode));
1452    get_cpu_vsrl(xbl, xB(ctx->opcode));
1453    t0 = tcg_temp_new_i64();
1454
1455    tcg_gen_bswap64_i64(t0, xbl);
1456    tcg_gen_bswap64_i64(xtl, xbh);
1457    set_cpu_vsrl(xT(ctx->opcode), xtl);
1458    tcg_gen_mov_i64(xth, t0);
1459    set_cpu_vsrh(xT(ctx->opcode), xth);
1460
1461    tcg_temp_free_i64(t0);
1462    tcg_temp_free_i64(xth);
1463    tcg_temp_free_i64(xtl);
1464    tcg_temp_free_i64(xbh);
1465    tcg_temp_free_i64(xbl);
1466}
1467
1468static void gen_xxbrw(DisasContext *ctx)
1469{
1470    TCGv_i64 xth;
1471    TCGv_i64 xtl;
1472    TCGv_i64 xbh;
1473    TCGv_i64 xbl;
1474
1475    if (unlikely(!ctx->vsx_enabled)) {
1476        gen_exception(ctx, POWERPC_EXCP_VSXU);
1477        return;
1478    }
1479    xth = tcg_temp_new_i64();
1480    xtl = tcg_temp_new_i64();
1481    xbh = tcg_temp_new_i64();
1482    xbl = tcg_temp_new_i64();
1483    get_cpu_vsrh(xbh, xB(ctx->opcode));
1484    get_cpu_vsrl(xbl, xB(ctx->opcode));
1485
1486    gen_bswap32x4(xth, xtl, xbh, xbl);
1487    set_cpu_vsrh(xT(ctx->opcode), xth);
1488    set_cpu_vsrl(xT(ctx->opcode), xtl);
1489
1490    tcg_temp_free_i64(xth);
1491    tcg_temp_free_i64(xtl);
1492    tcg_temp_free_i64(xbh);
1493    tcg_temp_free_i64(xbl);
1494}
1495
1496#define VSX_LOGICAL(name, vece, tcg_op)                              \
1497static void glue(gen_, name)(DisasContext *ctx)                      \
1498    {                                                                \
1499        if (unlikely(!ctx->vsx_enabled)) {                           \
1500            gen_exception(ctx, POWERPC_EXCP_VSXU);                   \
1501            return;                                                  \
1502        }                                                            \
1503        tcg_op(vece, vsr_full_offset(xT(ctx->opcode)),               \
1504               vsr_full_offset(xA(ctx->opcode)),                     \
1505               vsr_full_offset(xB(ctx->opcode)), 16, 16);            \
1506    }
1507
1508VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
1509VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
1510VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
1511VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
1512VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
1513VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
1514VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
1515VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
1516
1517#define VSX_XXMRG(name, high)                               \
1518static void glue(gen_, name)(DisasContext *ctx)             \
1519    {                                                       \
1520        TCGv_i64 a0, a1, b0, b1, tmp;                       \
1521        if (unlikely(!ctx->vsx_enabled)) {                  \
1522            gen_exception(ctx, POWERPC_EXCP_VSXU);          \
1523            return;                                         \
1524        }                                                   \
1525        a0 = tcg_temp_new_i64();                            \
1526        a1 = tcg_temp_new_i64();                            \
1527        b0 = tcg_temp_new_i64();                            \
1528        b1 = tcg_temp_new_i64();                            \
1529        tmp = tcg_temp_new_i64();                           \
1530        if (high) {                                         \
1531            get_cpu_vsrh(a0, xA(ctx->opcode));              \
1532            get_cpu_vsrh(a1, xA(ctx->opcode));              \
1533            get_cpu_vsrh(b0, xB(ctx->opcode));              \
1534            get_cpu_vsrh(b1, xB(ctx->opcode));              \
1535        } else {                                            \
1536            get_cpu_vsrl(a0, xA(ctx->opcode));              \
1537            get_cpu_vsrl(a1, xA(ctx->opcode));              \
1538            get_cpu_vsrl(b0, xB(ctx->opcode));              \
1539            get_cpu_vsrl(b1, xB(ctx->opcode));              \
1540        }                                                   \
1541        tcg_gen_shri_i64(a0, a0, 32);                       \
1542        tcg_gen_shri_i64(b0, b0, 32);                       \
1543        tcg_gen_deposit_i64(tmp, b0, a0, 32, 32);           \
1544        set_cpu_vsrh(xT(ctx->opcode), tmp);                 \
1545        tcg_gen_deposit_i64(tmp, b1, a1, 32, 32);           \
1546        set_cpu_vsrl(xT(ctx->opcode), tmp);                 \
1547        tcg_temp_free_i64(a0);                              \
1548        tcg_temp_free_i64(a1);                              \
1549        tcg_temp_free_i64(b0);                              \
1550        tcg_temp_free_i64(b1);                              \
1551        tcg_temp_free_i64(tmp);                             \
1552    }
1553
1554VSX_XXMRG(xxmrghw, 1)
1555VSX_XXMRG(xxmrglw, 0)
1556
1557static void gen_xxsel(DisasContext *ctx)
1558{
1559    int rt = xT(ctx->opcode);
1560    int ra = xA(ctx->opcode);
1561    int rb = xB(ctx->opcode);
1562    int rc = xC(ctx->opcode);
1563
1564    if (unlikely(!ctx->vsx_enabled)) {
1565        gen_exception(ctx, POWERPC_EXCP_VSXU);
1566        return;
1567    }
1568    tcg_gen_gvec_bitsel(MO_64, vsr_full_offset(rt), vsr_full_offset(rc),
1569                        vsr_full_offset(rb), vsr_full_offset(ra), 16, 16);
1570}
1571
1572static void gen_xxspltw(DisasContext *ctx)
1573{
1574    int rt = xT(ctx->opcode);
1575    int rb = xB(ctx->opcode);
1576    int uim = UIM(ctx->opcode);
1577    int tofs, bofs;
1578
1579    if (unlikely(!ctx->vsx_enabled)) {
1580        gen_exception(ctx, POWERPC_EXCP_VSXU);
1581        return;
1582    }
1583
1584    tofs = vsr_full_offset(rt);
1585    bofs = vsr_full_offset(rb);
1586    bofs += uim << MO_32;
1587#ifndef HOST_WORDS_BIG_ENDIAN
1588    bofs ^= 8 | 4;
1589#endif
1590
1591    tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
1592}
1593
1594#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
1595
1596static void gen_xxspltib(DisasContext *ctx)
1597{
1598    uint8_t uim8 = IMM8(ctx->opcode);
1599    int rt = xT(ctx->opcode);
1600
1601    if (rt < 32) {
1602        if (unlikely(!ctx->vsx_enabled)) {
1603            gen_exception(ctx, POWERPC_EXCP_VSXU);
1604            return;
1605        }
1606    } else {
1607        if (unlikely(!ctx->altivec_enabled)) {
1608            gen_exception(ctx, POWERPC_EXCP_VPU);
1609            return;
1610        }
1611    }
1612    tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(rt), 16, 16, uim8);
1613}
1614
1615static void gen_xxsldwi(DisasContext *ctx)
1616{
1617    TCGv_i64 xth, xtl;
1618    if (unlikely(!ctx->vsx_enabled)) {
1619        gen_exception(ctx, POWERPC_EXCP_VSXU);
1620        return;
1621    }
1622    xth = tcg_temp_new_i64();
1623    xtl = tcg_temp_new_i64();
1624
1625    switch (SHW(ctx->opcode)) {
1626        case 0: {
1627            get_cpu_vsrh(xth, xA(ctx->opcode));
1628            get_cpu_vsrl(xtl, xA(ctx->opcode));
1629            break;
1630        }
1631        case 1: {
1632            TCGv_i64 t0 = tcg_temp_new_i64();
1633            get_cpu_vsrh(xth, xA(ctx->opcode));
1634            tcg_gen_shli_i64(xth, xth, 32);
1635            get_cpu_vsrl(t0, xA(ctx->opcode));
1636            tcg_gen_shri_i64(t0, t0, 32);
1637            tcg_gen_or_i64(xth, xth, t0);
1638            get_cpu_vsrl(xtl, xA(ctx->opcode));
1639            tcg_gen_shli_i64(xtl, xtl, 32);
1640            get_cpu_vsrh(t0, xB(ctx->opcode));
1641            tcg_gen_shri_i64(t0, t0, 32);
1642            tcg_gen_or_i64(xtl, xtl, t0);
1643            tcg_temp_free_i64(t0);
1644            break;
1645        }
1646        case 2: {
1647            get_cpu_vsrl(xth, xA(ctx->opcode));
1648            get_cpu_vsrh(xtl, xB(ctx->opcode));
1649            break;
1650        }
1651        case 3: {
1652            TCGv_i64 t0 = tcg_temp_new_i64();
1653            get_cpu_vsrl(xth, xA(ctx->opcode));
1654            tcg_gen_shli_i64(xth, xth, 32);
1655            get_cpu_vsrh(t0, xB(ctx->opcode));
1656            tcg_gen_shri_i64(t0, t0, 32);
1657            tcg_gen_or_i64(xth, xth, t0);
1658            get_cpu_vsrh(xtl, xB(ctx->opcode));
1659            tcg_gen_shli_i64(xtl, xtl, 32);
1660            get_cpu_vsrl(t0, xB(ctx->opcode));
1661            tcg_gen_shri_i64(t0, t0, 32);
1662            tcg_gen_or_i64(xtl, xtl, t0);
1663            tcg_temp_free_i64(t0);
1664            break;
1665        }
1666    }
1667
1668    set_cpu_vsrh(xT(ctx->opcode), xth);
1669    set_cpu_vsrl(xT(ctx->opcode), xtl);
1670
1671    tcg_temp_free_i64(xth);
1672    tcg_temp_free_i64(xtl);
1673}
1674
1675#define VSX_EXTRACT_INSERT(name)                                \
1676static void gen_##name(DisasContext *ctx)                       \
1677{                                                               \
1678    TCGv_ptr xt, xb;                                            \
1679    TCGv_i32 t0;                                                \
1680    TCGv_i64 t1;                                                \
1681    uint8_t uimm = UIMM4(ctx->opcode);                          \
1682                                                                \
1683    if (unlikely(!ctx->vsx_enabled)) {                          \
1684        gen_exception(ctx, POWERPC_EXCP_VSXU);                  \
1685        return;                                                 \
1686    }                                                           \
1687    xt = gen_vsr_ptr(xT(ctx->opcode));                          \
1688    xb = gen_vsr_ptr(xB(ctx->opcode));                          \
1689    t0 = tcg_temp_new_i32();                                    \
1690    t1 = tcg_temp_new_i64();                                    \
1691    /*                                                          \
1692     * uimm > 15 out of bound and for                           \
1693     * uimm > 12 handle as per hardware in helper               \
1694     */                                                         \
1695    if (uimm > 15) {                                            \
1696        tcg_gen_movi_i64(t1, 0);                                \
1697        set_cpu_vsrh(xT(ctx->opcode), t1);                      \
1698        set_cpu_vsrl(xT(ctx->opcode), t1);                      \
1699        return;                                                 \
1700    }                                                           \
1701    tcg_gen_movi_i32(t0, uimm);                                 \
1702    gen_helper_##name(cpu_env, xt, xb, t0);                     \
1703    tcg_temp_free_ptr(xb);                                      \
1704    tcg_temp_free_ptr(xt);                                      \
1705    tcg_temp_free_i32(t0);                                      \
1706    tcg_temp_free_i64(t1);                                      \
1707}
1708
1709VSX_EXTRACT_INSERT(xxextractuw)
1710VSX_EXTRACT_INSERT(xxinsertw)
1711
1712#ifdef TARGET_PPC64
1713static void gen_xsxexpdp(DisasContext *ctx)
1714{
1715    TCGv rt = cpu_gpr[rD(ctx->opcode)];
1716    TCGv_i64 t0;
1717    if (unlikely(!ctx->vsx_enabled)) {
1718        gen_exception(ctx, POWERPC_EXCP_VSXU);
1719        return;
1720    }
1721    t0 = tcg_temp_new_i64();
1722    get_cpu_vsrh(t0, xB(ctx->opcode));
1723    tcg_gen_extract_i64(rt, t0, 52, 11);
1724    tcg_temp_free_i64(t0);
1725}
1726
1727static void gen_xsxexpqp(DisasContext *ctx)
1728{
1729    TCGv_i64 xth;
1730    TCGv_i64 xtl;
1731    TCGv_i64 xbh;
1732
1733    if (unlikely(!ctx->vsx_enabled)) {
1734        gen_exception(ctx, POWERPC_EXCP_VSXU);
1735        return;
1736    }
1737    xth = tcg_temp_new_i64();
1738    xtl = tcg_temp_new_i64();
1739    xbh = tcg_temp_new_i64();
1740    get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
1741
1742    tcg_gen_extract_i64(xth, xbh, 48, 15);
1743    set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
1744    tcg_gen_movi_i64(xtl, 0);
1745    set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
1746
1747    tcg_temp_free_i64(xbh);
1748    tcg_temp_free_i64(xth);
1749    tcg_temp_free_i64(xtl);
1750}
1751
1752static void gen_xsiexpdp(DisasContext *ctx)
1753{
1754    TCGv_i64 xth;
1755    TCGv ra = cpu_gpr[rA(ctx->opcode)];
1756    TCGv rb = cpu_gpr[rB(ctx->opcode)];
1757    TCGv_i64 t0;
1758
1759    if (unlikely(!ctx->vsx_enabled)) {
1760        gen_exception(ctx, POWERPC_EXCP_VSXU);
1761        return;
1762    }
1763    t0 = tcg_temp_new_i64();
1764    xth = tcg_temp_new_i64();
1765    tcg_gen_andi_i64(xth, ra, 0x800FFFFFFFFFFFFF);
1766    tcg_gen_andi_i64(t0, rb, 0x7FF);
1767    tcg_gen_shli_i64(t0, t0, 52);
1768    tcg_gen_or_i64(xth, xth, t0);
1769    set_cpu_vsrh(xT(ctx->opcode), xth);
1770    /* dword[1] is undefined */
1771    tcg_temp_free_i64(t0);
1772    tcg_temp_free_i64(xth);
1773}
1774
1775static void gen_xsiexpqp(DisasContext *ctx)
1776{
1777    TCGv_i64 xth;
1778    TCGv_i64 xtl;
1779    TCGv_i64 xah;
1780    TCGv_i64 xal;
1781    TCGv_i64 xbh;
1782    TCGv_i64 t0;
1783
1784    if (unlikely(!ctx->vsx_enabled)) {
1785        gen_exception(ctx, POWERPC_EXCP_VSXU);
1786        return;
1787    }
1788    xth = tcg_temp_new_i64();
1789    xtl = tcg_temp_new_i64();
1790    xah = tcg_temp_new_i64();
1791    xal = tcg_temp_new_i64();
1792    get_cpu_vsrh(xah, rA(ctx->opcode) + 32);
1793    get_cpu_vsrl(xal, rA(ctx->opcode) + 32);
1794    xbh = tcg_temp_new_i64();
1795    get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
1796    t0 = tcg_temp_new_i64();
1797
1798    tcg_gen_andi_i64(xth, xah, 0x8000FFFFFFFFFFFF);
1799    tcg_gen_andi_i64(t0, xbh, 0x7FFF);
1800    tcg_gen_shli_i64(t0, t0, 48);
1801    tcg_gen_or_i64(xth, xth, t0);
1802    set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
1803    tcg_gen_mov_i64(xtl, xal);
1804    set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
1805
1806    tcg_temp_free_i64(t0);
1807    tcg_temp_free_i64(xth);
1808    tcg_temp_free_i64(xtl);
1809    tcg_temp_free_i64(xah);
1810    tcg_temp_free_i64(xal);
1811    tcg_temp_free_i64(xbh);
1812}
1813
1814static void gen_xsxsigdp(DisasContext *ctx)
1815{
1816    TCGv rt = cpu_gpr[rD(ctx->opcode)];
1817    TCGv_i64 t0, t1, zr, nan, exp;
1818
1819    if (unlikely(!ctx->vsx_enabled)) {
1820        gen_exception(ctx, POWERPC_EXCP_VSXU);
1821        return;
1822    }
1823    exp = tcg_temp_new_i64();
1824    t0 = tcg_temp_new_i64();
1825    t1 = tcg_temp_new_i64();
1826    zr = tcg_const_i64(0);
1827    nan = tcg_const_i64(2047);
1828
1829    get_cpu_vsrh(t1, xB(ctx->opcode));
1830    tcg_gen_extract_i64(exp, t1, 52, 11);
1831    tcg_gen_movi_i64(t0, 0x0010000000000000);
1832    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
1833    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
1834    get_cpu_vsrh(t1, xB(ctx->opcode));
1835    tcg_gen_deposit_i64(rt, t0, t1, 0, 52);
1836
1837    tcg_temp_free_i64(t0);
1838    tcg_temp_free_i64(t1);
1839    tcg_temp_free_i64(exp);
1840    tcg_temp_free_i64(zr);
1841    tcg_temp_free_i64(nan);
1842}
1843
1844static void gen_xsxsigqp(DisasContext *ctx)
1845{
1846    TCGv_i64 t0, zr, nan, exp;
1847    TCGv_i64 xth;
1848    TCGv_i64 xtl;
1849    TCGv_i64 xbh;
1850    TCGv_i64 xbl;
1851
1852    if (unlikely(!ctx->vsx_enabled)) {
1853        gen_exception(ctx, POWERPC_EXCP_VSXU);
1854        return;
1855    }
1856    xth = tcg_temp_new_i64();
1857    xtl = tcg_temp_new_i64();
1858    xbh = tcg_temp_new_i64();
1859    xbl = tcg_temp_new_i64();
1860    get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
1861    get_cpu_vsrl(xbl, rB(ctx->opcode) + 32);
1862    exp = tcg_temp_new_i64();
1863    t0 = tcg_temp_new_i64();
1864    zr = tcg_const_i64(0);
1865    nan = tcg_const_i64(32767);
1866
1867    tcg_gen_extract_i64(exp, xbh, 48, 15);
1868    tcg_gen_movi_i64(t0, 0x0001000000000000);
1869    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
1870    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
1871    tcg_gen_deposit_i64(xth, t0, xbh, 0, 48);
1872    set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
1873    tcg_gen_mov_i64(xtl, xbl);
1874    set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
1875
1876    tcg_temp_free_i64(t0);
1877    tcg_temp_free_i64(exp);
1878    tcg_temp_free_i64(zr);
1879    tcg_temp_free_i64(nan);
1880    tcg_temp_free_i64(xth);
1881    tcg_temp_free_i64(xtl);
1882    tcg_temp_free_i64(xbh);
1883    tcg_temp_free_i64(xbl);
1884}
1885#endif
1886
1887static void gen_xviexpsp(DisasContext *ctx)
1888{
1889    TCGv_i64 xth;
1890    TCGv_i64 xtl;
1891    TCGv_i64 xah;
1892    TCGv_i64 xal;
1893    TCGv_i64 xbh;
1894    TCGv_i64 xbl;
1895    TCGv_i64 t0;
1896
1897    if (unlikely(!ctx->vsx_enabled)) {
1898        gen_exception(ctx, POWERPC_EXCP_VSXU);
1899        return;
1900    }
1901    xth = tcg_temp_new_i64();
1902    xtl = tcg_temp_new_i64();
1903    xah = tcg_temp_new_i64();
1904    xal = tcg_temp_new_i64();
1905    xbh = tcg_temp_new_i64();
1906    xbl = tcg_temp_new_i64();
1907    get_cpu_vsrh(xah, xA(ctx->opcode));
1908    get_cpu_vsrl(xal, xA(ctx->opcode));
1909    get_cpu_vsrh(xbh, xB(ctx->opcode));
1910    get_cpu_vsrl(xbl, xB(ctx->opcode));
1911    t0 = tcg_temp_new_i64();
1912
1913    tcg_gen_andi_i64(xth, xah, 0x807FFFFF807FFFFF);
1914    tcg_gen_andi_i64(t0, xbh, 0xFF000000FF);
1915    tcg_gen_shli_i64(t0, t0, 23);
1916    tcg_gen_or_i64(xth, xth, t0);
1917    set_cpu_vsrh(xT(ctx->opcode), xth);
1918    tcg_gen_andi_i64(xtl, xal, 0x807FFFFF807FFFFF);
1919    tcg_gen_andi_i64(t0, xbl, 0xFF000000FF);
1920    tcg_gen_shli_i64(t0, t0, 23);
1921    tcg_gen_or_i64(xtl, xtl, t0);
1922    set_cpu_vsrl(xT(ctx->opcode), xtl);
1923
1924    tcg_temp_free_i64(t0);
1925    tcg_temp_free_i64(xth);
1926    tcg_temp_free_i64(xtl);
1927    tcg_temp_free_i64(xah);
1928    tcg_temp_free_i64(xal);
1929    tcg_temp_free_i64(xbh);
1930    tcg_temp_free_i64(xbl);
1931}
1932
1933static void gen_xviexpdp(DisasContext *ctx)
1934{
1935    TCGv_i64 xth;
1936    TCGv_i64 xtl;
1937    TCGv_i64 xah;
1938    TCGv_i64 xal;
1939    TCGv_i64 xbh;
1940    TCGv_i64 xbl;
1941
1942    if (unlikely(!ctx->vsx_enabled)) {
1943        gen_exception(ctx, POWERPC_EXCP_VSXU);
1944        return;
1945    }
1946    xth = tcg_temp_new_i64();
1947    xtl = tcg_temp_new_i64();
1948    xah = tcg_temp_new_i64();
1949    xal = tcg_temp_new_i64();
1950    xbh = tcg_temp_new_i64();
1951    xbl = tcg_temp_new_i64();
1952    get_cpu_vsrh(xah, xA(ctx->opcode));
1953    get_cpu_vsrl(xal, xA(ctx->opcode));
1954    get_cpu_vsrh(xbh, xB(ctx->opcode));
1955    get_cpu_vsrl(xbl, xB(ctx->opcode));
1956
1957    tcg_gen_deposit_i64(xth, xah, xbh, 52, 11);
1958    set_cpu_vsrh(xT(ctx->opcode), xth);
1959
1960    tcg_gen_deposit_i64(xtl, xal, xbl, 52, 11);
1961    set_cpu_vsrl(xT(ctx->opcode), xtl);
1962
1963    tcg_temp_free_i64(xth);
1964    tcg_temp_free_i64(xtl);
1965    tcg_temp_free_i64(xah);
1966    tcg_temp_free_i64(xal);
1967    tcg_temp_free_i64(xbh);
1968    tcg_temp_free_i64(xbl);
1969}
1970
1971static void gen_xvxexpsp(DisasContext *ctx)
1972{
1973    TCGv_i64 xth;
1974    TCGv_i64 xtl;
1975    TCGv_i64 xbh;
1976    TCGv_i64 xbl;
1977
1978    if (unlikely(!ctx->vsx_enabled)) {
1979        gen_exception(ctx, POWERPC_EXCP_VSXU);
1980        return;
1981    }
1982    xth = tcg_temp_new_i64();
1983    xtl = tcg_temp_new_i64();
1984    xbh = tcg_temp_new_i64();
1985    xbl = tcg_temp_new_i64();
1986    get_cpu_vsrh(xbh, xB(ctx->opcode));
1987    get_cpu_vsrl(xbl, xB(ctx->opcode));
1988
1989    tcg_gen_shri_i64(xth, xbh, 23);
1990    tcg_gen_andi_i64(xth, xth, 0xFF000000FF);
1991    set_cpu_vsrh(xT(ctx->opcode), xth);
1992    tcg_gen_shri_i64(xtl, xbl, 23);
1993    tcg_gen_andi_i64(xtl, xtl, 0xFF000000FF);
1994    set_cpu_vsrl(xT(ctx->opcode), xtl);
1995
1996    tcg_temp_free_i64(xth);
1997    tcg_temp_free_i64(xtl);
1998    tcg_temp_free_i64(xbh);
1999    tcg_temp_free_i64(xbl);
2000}
2001
2002static void gen_xvxexpdp(DisasContext *ctx)
2003{
2004    TCGv_i64 xth;
2005    TCGv_i64 xtl;
2006    TCGv_i64 xbh;
2007    TCGv_i64 xbl;
2008
2009    if (unlikely(!ctx->vsx_enabled)) {
2010        gen_exception(ctx, POWERPC_EXCP_VSXU);
2011        return;
2012    }
2013    xth = tcg_temp_new_i64();
2014    xtl = tcg_temp_new_i64();
2015    xbh = tcg_temp_new_i64();
2016    xbl = tcg_temp_new_i64();
2017    get_cpu_vsrh(xbh, xB(ctx->opcode));
2018    get_cpu_vsrl(xbl, xB(ctx->opcode));
2019
2020    tcg_gen_extract_i64(xth, xbh, 52, 11);
2021    set_cpu_vsrh(xT(ctx->opcode), xth);
2022    tcg_gen_extract_i64(xtl, xbl, 52, 11);
2023    set_cpu_vsrl(xT(ctx->opcode), xtl);
2024
2025    tcg_temp_free_i64(xth);
2026    tcg_temp_free_i64(xtl);
2027    tcg_temp_free_i64(xbh);
2028    tcg_temp_free_i64(xbl);
2029}
2030
2031GEN_VSX_HELPER_X2(xvxsigsp, 0x00, 0x04, 0, PPC2_ISA300)
2032
2033static void gen_xvxsigdp(DisasContext *ctx)
2034{
2035    TCGv_i64 xth;
2036    TCGv_i64 xtl;
2037    TCGv_i64 xbh;
2038    TCGv_i64 xbl;
2039    TCGv_i64 t0, zr, nan, exp;
2040
2041    if (unlikely(!ctx->vsx_enabled)) {
2042        gen_exception(ctx, POWERPC_EXCP_VSXU);
2043        return;
2044    }
2045    xth = tcg_temp_new_i64();
2046    xtl = tcg_temp_new_i64();
2047    xbh = tcg_temp_new_i64();
2048    xbl = tcg_temp_new_i64();
2049    get_cpu_vsrh(xbh, xB(ctx->opcode));
2050    get_cpu_vsrl(xbl, xB(ctx->opcode));
2051    exp = tcg_temp_new_i64();
2052    t0 = tcg_temp_new_i64();
2053    zr = tcg_const_i64(0);
2054    nan = tcg_const_i64(2047);
2055
2056    tcg_gen_extract_i64(exp, xbh, 52, 11);
2057    tcg_gen_movi_i64(t0, 0x0010000000000000);
2058    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
2059    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
2060    tcg_gen_deposit_i64(xth, t0, xbh, 0, 52);
2061    set_cpu_vsrh(xT(ctx->opcode), xth);
2062
2063    tcg_gen_extract_i64(exp, xbl, 52, 11);
2064    tcg_gen_movi_i64(t0, 0x0010000000000000);
2065    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
2066    tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
2067    tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52);
2068    set_cpu_vsrl(xT(ctx->opcode), xtl);
2069
2070    tcg_temp_free_i64(t0);
2071    tcg_temp_free_i64(exp);
2072    tcg_temp_free_i64(zr);
2073    tcg_temp_free_i64(nan);
2074    tcg_temp_free_i64(xth);
2075    tcg_temp_free_i64(xtl);
2076    tcg_temp_free_i64(xbh);
2077    tcg_temp_free_i64(xbl);
2078}
2079
2080#undef GEN_XX2FORM
2081#undef GEN_XX3FORM
2082#undef GEN_XX2IFORM
2083#undef GEN_XX3_RC_FORM
2084#undef GEN_XX3FORM_DM
2085#undef VSX_LOGICAL
2086