xref: /qemu/target/ppc/translate/vmx-impl.c.inc (revision 4ce7a08d)
1/*
2 * translate/vmx-impl.c
3 *
4 * Altivec/VMX translation
5 */
6
7/***                      Altivec vector extension                         ***/
8/* Altivec registers moves */
9
10static inline TCGv_ptr gen_avr_ptr(int reg)
11{
12    TCGv_ptr r = tcg_temp_new_ptr();
13    tcg_gen_addi_ptr(r, cpu_env, avr_full_offset(reg));
14    return r;
15}
16
17#define GEN_VR_LDX(name, opc2, opc3)                                          \
18static void glue(gen_, name)(DisasContext *ctx)                               \
19{                                                                             \
20    TCGv EA;                                                                  \
21    TCGv_i64 avr;                                                             \
22    if (unlikely(!ctx->altivec_enabled)) {                                    \
23        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
24        return;                                                               \
25    }                                                                         \
26    gen_set_access_type(ctx, ACCESS_INT);                                     \
27    avr = tcg_temp_new_i64();                                                 \
28    EA = tcg_temp_new();                                                      \
29    gen_addr_reg_index(ctx, EA);                                              \
30    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
31    /*                                                                        \
32     * We only need to swap high and low halves. gen_qemu_ld64_i64            \
33     * does necessary 64-bit byteswap already.                                \
34     */                                                                       \
35    if (ctx->le_mode) {                                                       \
36        gen_qemu_ld64_i64(ctx, avr, EA);                                      \
37        set_avr64(rD(ctx->opcode), avr, false);                               \
38        tcg_gen_addi_tl(EA, EA, 8);                                           \
39        gen_qemu_ld64_i64(ctx, avr, EA);                                      \
40        set_avr64(rD(ctx->opcode), avr, true);                                \
41    } else {                                                                  \
42        gen_qemu_ld64_i64(ctx, avr, EA);                                      \
43        set_avr64(rD(ctx->opcode), avr, true);                                \
44        tcg_gen_addi_tl(EA, EA, 8);                                           \
45        gen_qemu_ld64_i64(ctx, avr, EA);                                      \
46        set_avr64(rD(ctx->opcode), avr, false);                               \
47    }                                                                         \
48    tcg_temp_free(EA);                                                        \
49    tcg_temp_free_i64(avr);                                                   \
50}
51
52#define GEN_VR_STX(name, opc2, opc3)                                          \
53static void gen_st##name(DisasContext *ctx)                                   \
54{                                                                             \
55    TCGv EA;                                                                  \
56    TCGv_i64 avr;                                                             \
57    if (unlikely(!ctx->altivec_enabled)) {                                    \
58        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
59        return;                                                               \
60    }                                                                         \
61    gen_set_access_type(ctx, ACCESS_INT);                                     \
62    avr = tcg_temp_new_i64();                                                 \
63    EA = tcg_temp_new();                                                      \
64    gen_addr_reg_index(ctx, EA);                                              \
65    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
66    /*                                                                        \
67     * We only need to swap high and low halves. gen_qemu_st64_i64            \
68     * does necessary 64-bit byteswap already.                                \
69     */                                                                       \
70    if (ctx->le_mode) {                                                       \
71        get_avr64(avr, rD(ctx->opcode), false);                               \
72        gen_qemu_st64_i64(ctx, avr, EA);                                      \
73        tcg_gen_addi_tl(EA, EA, 8);                                           \
74        get_avr64(avr, rD(ctx->opcode), true);                                \
75        gen_qemu_st64_i64(ctx, avr, EA);                                      \
76    } else {                                                                  \
77        get_avr64(avr, rD(ctx->opcode), true);                                \
78        gen_qemu_st64_i64(ctx, avr, EA);                                      \
79        tcg_gen_addi_tl(EA, EA, 8);                                           \
80        get_avr64(avr, rD(ctx->opcode), false);                               \
81        gen_qemu_st64_i64(ctx, avr, EA);                                      \
82    }                                                                         \
83    tcg_temp_free(EA);                                                        \
84    tcg_temp_free_i64(avr);                                                   \
85}
86
87#define GEN_VR_LVE(name, opc2, opc3, size)                              \
88static void gen_lve##name(DisasContext *ctx)                            \
89    {                                                                   \
90        TCGv EA;                                                        \
91        TCGv_ptr rs;                                                    \
92        if (unlikely(!ctx->altivec_enabled)) {                          \
93            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
94            return;                                                     \
95        }                                                               \
96        gen_set_access_type(ctx, ACCESS_INT);                           \
97        EA = tcg_temp_new();                                            \
98        gen_addr_reg_index(ctx, EA);                                    \
99        if (size > 1) {                                                 \
100            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
101        }                                                               \
102        rs = gen_avr_ptr(rS(ctx->opcode));                              \
103        gen_helper_lve##name(cpu_env, rs, EA);                          \
104        tcg_temp_free(EA);                                              \
105        tcg_temp_free_ptr(rs);                                          \
106    }
107
108#define GEN_VR_STVE(name, opc2, opc3, size)                             \
109static void gen_stve##name(DisasContext *ctx)                           \
110    {                                                                   \
111        TCGv EA;                                                        \
112        TCGv_ptr rs;                                                    \
113        if (unlikely(!ctx->altivec_enabled)) {                          \
114            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
115            return;                                                     \
116        }                                                               \
117        gen_set_access_type(ctx, ACCESS_INT);                           \
118        EA = tcg_temp_new();                                            \
119        gen_addr_reg_index(ctx, EA);                                    \
120        if (size > 1) {                                                 \
121            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
122        }                                                               \
123        rs = gen_avr_ptr(rS(ctx->opcode));                              \
124        gen_helper_stve##name(cpu_env, rs, EA);                         \
125        tcg_temp_free(EA);                                              \
126        tcg_temp_free_ptr(rs);                                          \
127    }
128
129GEN_VR_LDX(lvx, 0x07, 0x03);
130/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
131GEN_VR_LDX(lvxl, 0x07, 0x0B);
132
133GEN_VR_LVE(bx, 0x07, 0x00, 1);
134GEN_VR_LVE(hx, 0x07, 0x01, 2);
135GEN_VR_LVE(wx, 0x07, 0x02, 4);
136
137GEN_VR_STX(svx, 0x07, 0x07);
138/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
139GEN_VR_STX(svxl, 0x07, 0x0F);
140
141GEN_VR_STVE(bx, 0x07, 0x04, 1);
142GEN_VR_STVE(hx, 0x07, 0x05, 2);
143GEN_VR_STVE(wx, 0x07, 0x06, 4);
144
145static void gen_mfvscr(DisasContext *ctx)
146{
147    TCGv_i32 t;
148    TCGv_i64 avr;
149    if (unlikely(!ctx->altivec_enabled)) {
150        gen_exception(ctx, POWERPC_EXCP_VPU);
151        return;
152    }
153    avr = tcg_temp_new_i64();
154    tcg_gen_movi_i64(avr, 0);
155    set_avr64(rD(ctx->opcode), avr, true);
156    t = tcg_temp_new_i32();
157    gen_helper_mfvscr(t, cpu_env);
158    tcg_gen_extu_i32_i64(avr, t);
159    set_avr64(rD(ctx->opcode), avr, false);
160    tcg_temp_free_i32(t);
161    tcg_temp_free_i64(avr);
162}
163
164static void gen_mtvscr(DisasContext *ctx)
165{
166    TCGv_i32 val;
167    int bofs;
168
169    if (unlikely(!ctx->altivec_enabled)) {
170        gen_exception(ctx, POWERPC_EXCP_VPU);
171        return;
172    }
173
174    val = tcg_temp_new_i32();
175    bofs = avr_full_offset(rB(ctx->opcode));
176#ifdef HOST_WORDS_BIGENDIAN
177    bofs += 3 * 4;
178#endif
179
180    tcg_gen_ld_i32(val, cpu_env, bofs);
181    gen_helper_mtvscr(cpu_env, val);
182    tcg_temp_free_i32(val);
183}
184
185#define GEN_VX_VMUL10(name, add_cin, ret_carry)                         \
186static void glue(gen_, name)(DisasContext *ctx)                         \
187{                                                                       \
188    TCGv_i64 t0;                                                        \
189    TCGv_i64 t1;                                                        \
190    TCGv_i64 t2;                                                        \
191    TCGv_i64 avr;                                                       \
192    TCGv_i64 ten, z;                                                    \
193                                                                        \
194    if (unlikely(!ctx->altivec_enabled)) {                              \
195        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
196        return;                                                         \
197    }                                                                   \
198                                                                        \
199    t0 = tcg_temp_new_i64();                                            \
200    t1 = tcg_temp_new_i64();                                            \
201    t2 = tcg_temp_new_i64();                                            \
202    avr = tcg_temp_new_i64();                                           \
203    ten = tcg_const_i64(10);                                            \
204    z = tcg_const_i64(0);                                               \
205                                                                        \
206    if (add_cin) {                                                      \
207        get_avr64(avr, rA(ctx->opcode), false);                         \
208        tcg_gen_mulu2_i64(t0, t1, avr, ten);                            \
209        get_avr64(avr, rB(ctx->opcode), false);                         \
210        tcg_gen_andi_i64(t2, avr, 0xF);                                 \
211        tcg_gen_add2_i64(avr, t2, t0, t1, t2, z);                       \
212        set_avr64(rD(ctx->opcode), avr, false);                         \
213    } else {                                                            \
214        get_avr64(avr, rA(ctx->opcode), false);                         \
215        tcg_gen_mulu2_i64(avr, t2, avr, ten);                           \
216        set_avr64(rD(ctx->opcode), avr, false);                         \
217    }                                                                   \
218                                                                        \
219    if (ret_carry) {                                                    \
220        get_avr64(avr, rA(ctx->opcode), true);                          \
221        tcg_gen_mulu2_i64(t0, t1, avr, ten);                            \
222        tcg_gen_add2_i64(t0, avr, t0, t1, t2, z);                       \
223        set_avr64(rD(ctx->opcode), avr, false);                         \
224        set_avr64(rD(ctx->opcode), z, true);                            \
225    } else {                                                            \
226        get_avr64(avr, rA(ctx->opcode), true);                          \
227        tcg_gen_mul_i64(t0, avr, ten);                                  \
228        tcg_gen_add_i64(avr, t0, t2);                                   \
229        set_avr64(rD(ctx->opcode), avr, true);                          \
230    }                                                                   \
231                                                                        \
232    tcg_temp_free_i64(t0);                                              \
233    tcg_temp_free_i64(t1);                                              \
234    tcg_temp_free_i64(t2);                                              \
235    tcg_temp_free_i64(avr);                                             \
236    tcg_temp_free_i64(ten);                                             \
237    tcg_temp_free_i64(z);                                               \
238}                                                                       \
239
240GEN_VX_VMUL10(vmul10uq, 0, 0);
241GEN_VX_VMUL10(vmul10euq, 1, 0);
242GEN_VX_VMUL10(vmul10cuq, 0, 1);
243GEN_VX_VMUL10(vmul10ecuq, 1, 1);
244
245#define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3)                    \
246static void glue(gen_, name)(DisasContext *ctx)                         \
247{                                                                       \
248    if (unlikely(!ctx->altivec_enabled)) {                              \
249        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
250        return;                                                         \
251    }                                                                   \
252                                                                        \
253    tcg_op(vece,                                                        \
254           avr_full_offset(rD(ctx->opcode)),                            \
255           avr_full_offset(rA(ctx->opcode)),                            \
256           avr_full_offset(rB(ctx->opcode)),                            \
257           16, 16);                                                     \
258}
259
260/* Logical operations */
261GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16);
262GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17);
263GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18);
264GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19);
265GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20);
266GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26);
267GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
268GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
269
270#define GEN_VXFORM(name, opc2, opc3)                                    \
271static void glue(gen_, name)(DisasContext *ctx)                         \
272{                                                                       \
273    TCGv_ptr ra, rb, rd;                                                \
274    if (unlikely(!ctx->altivec_enabled)) {                              \
275        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
276        return;                                                         \
277    }                                                                   \
278    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
279    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
280    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
281    gen_helper_##name(rd, ra, rb);                                      \
282    tcg_temp_free_ptr(ra);                                              \
283    tcg_temp_free_ptr(rb);                                              \
284    tcg_temp_free_ptr(rd);                                              \
285}
286
287#define GEN_VXFORM_TRANS(name, opc2, opc3)                              \
288static void glue(gen_, name)(DisasContext *ctx)                         \
289{                                                                       \
290    if (unlikely(!ctx->altivec_enabled)) {                              \
291        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
292        return;                                                         \
293    }                                                                   \
294    trans_##name(ctx);                                                  \
295}
296
297#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
298static void glue(gen_, name)(DisasContext *ctx)                         \
299{                                                                       \
300    TCGv_ptr ra, rb, rd;                                                \
301    if (unlikely(!ctx->altivec_enabled)) {                              \
302        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
303        return;                                                         \
304    }                                                                   \
305    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
306    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
307    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
308    gen_helper_##name(cpu_env, rd, ra, rb);                             \
309    tcg_temp_free_ptr(ra);                                              \
310    tcg_temp_free_ptr(rb);                                              \
311    tcg_temp_free_ptr(rd);                                              \
312}
313
314#define GEN_VXFORM3(name, opc2, opc3)                                   \
315static void glue(gen_, name)(DisasContext *ctx)                         \
316{                                                                       \
317    TCGv_ptr ra, rb, rc, rd;                                            \
318    if (unlikely(!ctx->altivec_enabled)) {                              \
319        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
320        return;                                                         \
321    }                                                                   \
322    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
323    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
324    rc = gen_avr_ptr(rC(ctx->opcode));                                  \
325    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
326    gen_helper_##name(rd, ra, rb, rc);                                  \
327    tcg_temp_free_ptr(ra);                                              \
328    tcg_temp_free_ptr(rb);                                              \
329    tcg_temp_free_ptr(rc);                                              \
330    tcg_temp_free_ptr(rd);                                              \
331}
332
333/*
334 * Support for Altivec instruction pairs that use bit 31 (Rc) as
335 * an opcode bit.  In general, these pairs come from different
336 * versions of the ISA, so we must also support a pair of flags for
337 * each instruction.
338 */
339#define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)          \
340static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
341{                                                                      \
342    if ((Rc(ctx->opcode) == 0) &&                                      \
343        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
344        gen_##name0(ctx);                                              \
345    } else if ((Rc(ctx->opcode) == 1) &&                               \
346        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
347        gen_##name1(ctx);                                              \
348    } else {                                                           \
349        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
350    }                                                                  \
351}
352
353/*
354 * We use this macro if one instruction is realized with direct
355 * translation, and second one with helper.
356 */
357#define GEN_VXFORM_TRANS_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)\
358static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
359{                                                                      \
360    if ((Rc(ctx->opcode) == 0) &&                                      \
361        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
362        if (unlikely(!ctx->altivec_enabled)) {                         \
363            gen_exception(ctx, POWERPC_EXCP_VPU);                      \
364            return;                                                    \
365        }                                                              \
366        trans_##name0(ctx);                                            \
367    } else if ((Rc(ctx->opcode) == 1) &&                               \
368        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
369        gen_##name1(ctx);                                              \
370    } else {                                                           \
371        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
372    }                                                                  \
373}
374
375/* Adds support to provide invalid mask */
376#define GEN_VXFORM_DUAL_EXT(name0, flg0, flg2_0, inval0,                \
377                            name1, flg1, flg2_1, inval1)                \
378static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
379{                                                                       \
380    if ((Rc(ctx->opcode) == 0) &&                                       \
381        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0)) &&  \
382        !(ctx->opcode & inval0)) {                                      \
383        gen_##name0(ctx);                                               \
384    } else if ((Rc(ctx->opcode) == 1) &&                                \
385               ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1)) && \
386               !(ctx->opcode & inval1)) {                               \
387        gen_##name1(ctx);                                               \
388    } else {                                                            \
389        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);             \
390    }                                                                   \
391}
392
393#define GEN_VXFORM_HETRO(name, opc2, opc3)                              \
394static void glue(gen_, name)(DisasContext *ctx)                         \
395{                                                                       \
396    TCGv_ptr rb;                                                        \
397    if (unlikely(!ctx->altivec_enabled)) {                              \
398        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
399        return;                                                         \
400    }                                                                   \
401    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
402    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], rb); \
403    tcg_temp_free_ptr(rb);                                              \
404}
405
406GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
407GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0,       \
408                    vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
409GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1);
410GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE,  \
411                vmul10ecuq, PPC_NONE, PPC2_ISA300)
412GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2);
413GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3);
414GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16);
415GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17);
416GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18);
417GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19);
418GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0);
419GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1);
420GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2);
421GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3);
422GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4);
423GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5);
424GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6);
425GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7);
426GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8);
427GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9);
428GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10);
429GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11);
430GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
431GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
432GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
433GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
434GEN_VXFORM(vavgub, 1, 16);
435GEN_VXFORM(vabsdub, 1, 16);
436GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
437                vabsdub, PPC_NONE, PPC2_ISA300)
438GEN_VXFORM(vavguh, 1, 17);
439GEN_VXFORM(vabsduh, 1, 17);
440GEN_VXFORM_DUAL(vavguh, PPC_ALTIVEC, PPC_NONE, \
441                vabsduh, PPC_NONE, PPC2_ISA300)
442GEN_VXFORM(vavguw, 1, 18);
443GEN_VXFORM(vabsduw, 1, 18);
444GEN_VXFORM_DUAL(vavguw, PPC_ALTIVEC, PPC_NONE, \
445                vabsduw, PPC_NONE, PPC2_ISA300)
446GEN_VXFORM(vavgsb, 1, 20);
447GEN_VXFORM(vavgsh, 1, 21);
448GEN_VXFORM(vavgsw, 1, 22);
449GEN_VXFORM(vmrghb, 6, 0);
450GEN_VXFORM(vmrghh, 6, 1);
451GEN_VXFORM(vmrghw, 6, 2);
452GEN_VXFORM(vmrglb, 6, 4);
453GEN_VXFORM(vmrglh, 6, 5);
454GEN_VXFORM(vmrglw, 6, 6);
455
456static void trans_vmrgew(DisasContext *ctx)
457{
458    int VT = rD(ctx->opcode);
459    int VA = rA(ctx->opcode);
460    int VB = rB(ctx->opcode);
461    TCGv_i64 tmp = tcg_temp_new_i64();
462    TCGv_i64 avr = tcg_temp_new_i64();
463
464    get_avr64(avr, VB, true);
465    tcg_gen_shri_i64(tmp, avr, 32);
466    get_avr64(avr, VA, true);
467    tcg_gen_deposit_i64(avr, avr, tmp, 0, 32);
468    set_avr64(VT, avr, true);
469
470    get_avr64(avr, VB, false);
471    tcg_gen_shri_i64(tmp, avr, 32);
472    get_avr64(avr, VA, false);
473    tcg_gen_deposit_i64(avr, avr, tmp, 0, 32);
474    set_avr64(VT, avr, false);
475
476    tcg_temp_free_i64(tmp);
477    tcg_temp_free_i64(avr);
478}
479
480static void trans_vmrgow(DisasContext *ctx)
481{
482    int VT = rD(ctx->opcode);
483    int VA = rA(ctx->opcode);
484    int VB = rB(ctx->opcode);
485    TCGv_i64 t0 = tcg_temp_new_i64();
486    TCGv_i64 t1 = tcg_temp_new_i64();
487    TCGv_i64 avr = tcg_temp_new_i64();
488
489    get_avr64(t0, VB, true);
490    get_avr64(t1, VA, true);
491    tcg_gen_deposit_i64(avr, t0, t1, 32, 32);
492    set_avr64(VT, avr, true);
493
494    get_avr64(t0, VB, false);
495    get_avr64(t1, VA, false);
496    tcg_gen_deposit_i64(avr, t0, t1, 32, 32);
497    set_avr64(VT, avr, false);
498
499    tcg_temp_free_i64(t0);
500    tcg_temp_free_i64(t1);
501    tcg_temp_free_i64(avr);
502}
503
504/*
505 * lvsl VRT,RA,RB - Load Vector for Shift Left
506 *
507 * Let the EA be the sum (rA|0)+(rB). Let sh=EA[28–31].
508 * Let X be the 32-byte value 0x00 || 0x01 || 0x02 || ... || 0x1E || 0x1F.
509 * Bytes sh:sh+15 of X are placed into vD.
510 */
511static void trans_lvsl(DisasContext *ctx)
512{
513    int VT = rD(ctx->opcode);
514    TCGv_i64 result = tcg_temp_new_i64();
515    TCGv_i64 sh = tcg_temp_new_i64();
516    TCGv EA = tcg_temp_new();
517
518    /* Get sh(from description) by anding EA with 0xf. */
519    gen_addr_reg_index(ctx, EA);
520    tcg_gen_extu_tl_i64(sh, EA);
521    tcg_gen_andi_i64(sh, sh, 0xfULL);
522
523    /*
524     * Create bytes sh:sh+7 of X(from description) and place them in
525     * higher doubleword of vD.
526     */
527    tcg_gen_muli_i64(sh, sh, 0x0101010101010101ULL);
528    tcg_gen_addi_i64(result, sh, 0x0001020304050607ull);
529    set_avr64(VT, result, true);
530    /*
531     * Create bytes sh+8:sh+15 of X(from description) and place them in
532     * lower doubleword of vD.
533     */
534    tcg_gen_addi_i64(result, sh, 0x08090a0b0c0d0e0fULL);
535    set_avr64(VT, result, false);
536
537    tcg_temp_free_i64(result);
538    tcg_temp_free_i64(sh);
539    tcg_temp_free(EA);
540}
541
542/*
543 * lvsr VRT,RA,RB - Load Vector for Shift Right
544 *
545 * Let the EA be the sum (rA|0)+(rB). Let sh=EA[28–31].
546 * Let X be the 32-byte value 0x00 || 0x01 || 0x02 || ... || 0x1E || 0x1F.
547 * Bytes (16-sh):(31-sh) of X are placed into vD.
548 */
549static void trans_lvsr(DisasContext *ctx)
550{
551    int VT = rD(ctx->opcode);
552    TCGv_i64 result = tcg_temp_new_i64();
553    TCGv_i64 sh = tcg_temp_new_i64();
554    TCGv EA = tcg_temp_new();
555
556
557    /* Get sh(from description) by anding EA with 0xf. */
558    gen_addr_reg_index(ctx, EA);
559    tcg_gen_extu_tl_i64(sh, EA);
560    tcg_gen_andi_i64(sh, sh, 0xfULL);
561
562    /*
563     * Create bytes (16-sh):(23-sh) of X(from description) and place them in
564     * higher doubleword of vD.
565     */
566    tcg_gen_muli_i64(sh, sh, 0x0101010101010101ULL);
567    tcg_gen_subfi_i64(result, 0x1011121314151617ULL, sh);
568    set_avr64(VT, result, true);
569    /*
570     * Create bytes (24-sh):(32-sh) of X(from description) and place them in
571     * lower doubleword of vD.
572     */
573    tcg_gen_subfi_i64(result, 0x18191a1b1c1d1e1fULL, sh);
574    set_avr64(VT, result, false);
575
576    tcg_temp_free_i64(result);
577    tcg_temp_free_i64(sh);
578    tcg_temp_free(EA);
579}
580
581/*
582 * vsl VRT,VRA,VRB - Vector Shift Left
583 *
584 * Shifting left 128 bit value of vA by value specified in bits 125-127 of vB.
585 * Lowest 3 bits in each byte element of register vB must be identical or
586 * result is undefined.
587 */
588static void trans_vsl(DisasContext *ctx)
589{
590    int VT = rD(ctx->opcode);
591    int VA = rA(ctx->opcode);
592    int VB = rB(ctx->opcode);
593    TCGv_i64 avr = tcg_temp_new_i64();
594    TCGv_i64 sh = tcg_temp_new_i64();
595    TCGv_i64 carry = tcg_temp_new_i64();
596    TCGv_i64 tmp = tcg_temp_new_i64();
597
598    /* Place bits 125-127 of vB in 'sh'. */
599    get_avr64(avr, VB, false);
600    tcg_gen_andi_i64(sh, avr, 0x07ULL);
601
602    /*
603     * Save highest 'sh' bits of lower doubleword element of vA in variable
604     * 'carry' and perform shift on lower doubleword.
605     */
606    get_avr64(avr, VA, false);
607    tcg_gen_subfi_i64(tmp, 32, sh);
608    tcg_gen_shri_i64(carry, avr, 32);
609    tcg_gen_shr_i64(carry, carry, tmp);
610    tcg_gen_shl_i64(avr, avr, sh);
611    set_avr64(VT, avr, false);
612
613    /*
614     * Perform shift on higher doubleword element of vA and replace lowest
615     * 'sh' bits with 'carry'.
616     */
617    get_avr64(avr, VA, true);
618    tcg_gen_shl_i64(avr, avr, sh);
619    tcg_gen_or_i64(avr, avr, carry);
620    set_avr64(VT, avr, true);
621
622    tcg_temp_free_i64(avr);
623    tcg_temp_free_i64(sh);
624    tcg_temp_free_i64(carry);
625    tcg_temp_free_i64(tmp);
626}
627
628/*
629 * vsr VRT,VRA,VRB - Vector Shift Right
630 *
631 * Shifting right 128 bit value of vA by value specified in bits 125-127 of vB.
632 * Lowest 3 bits in each byte element of register vB must be identical or
633 * result is undefined.
634 */
635static void trans_vsr(DisasContext *ctx)
636{
637    int VT = rD(ctx->opcode);
638    int VA = rA(ctx->opcode);
639    int VB = rB(ctx->opcode);
640    TCGv_i64 avr = tcg_temp_new_i64();
641    TCGv_i64 sh = tcg_temp_new_i64();
642    TCGv_i64 carry = tcg_temp_new_i64();
643    TCGv_i64 tmp = tcg_temp_new_i64();
644
645    /* Place bits 125-127 of vB in 'sh'. */
646    get_avr64(avr, VB, false);
647    tcg_gen_andi_i64(sh, avr, 0x07ULL);
648
649    /*
650     * Save lowest 'sh' bits of higher doubleword element of vA in variable
651     * 'carry' and perform shift on higher doubleword.
652     */
653    get_avr64(avr, VA, true);
654    tcg_gen_subfi_i64(tmp, 32, sh);
655    tcg_gen_shli_i64(carry, avr, 32);
656    tcg_gen_shl_i64(carry, carry, tmp);
657    tcg_gen_shr_i64(avr, avr, sh);
658    set_avr64(VT, avr, true);
659    /*
660     * Perform shift on lower doubleword element of vA and replace highest
661     * 'sh' bits with 'carry'.
662     */
663    get_avr64(avr, VA, false);
664    tcg_gen_shr_i64(avr, avr, sh);
665    tcg_gen_or_i64(avr, avr, carry);
666    set_avr64(VT, avr, false);
667
668    tcg_temp_free_i64(avr);
669    tcg_temp_free_i64(sh);
670    tcg_temp_free_i64(carry);
671    tcg_temp_free_i64(tmp);
672}
673
674/*
675 * vgbbd VRT,VRB - Vector Gather Bits by Bytes by Doubleword
676 *
677 * All ith bits (i in range 1 to 8) of each byte of doubleword element in source
678 * register are concatenated and placed into ith byte of appropriate doubleword
679 * element in destination register.
680 *
681 * Following solution is done for both doubleword elements of source register
682 * in parallel, in order to reduce the number of instructions needed(that's why
683 * arrays are used):
684 * First, both doubleword elements of source register vB are placed in
685 * appropriate element of array avr. Bits are gathered in 2x8 iterations(2 for
686 * loops). In first iteration bit 1 of byte 1, bit 2 of byte 2,... bit 8 of
687 * byte 8 are in their final spots so avr[i], i={0,1} can be and-ed with
688 * tcg_mask. For every following iteration, both avr[i] and tcg_mask variables
689 * have to be shifted right for 7 and 8 places, respectively, in order to get
690 * bit 1 of byte 2, bit 2 of byte 3.. bit 7 of byte 8 in their final spots so
691 * shifted avr values(saved in tmp) can be and-ed with new value of tcg_mask...
692 * After first 8 iteration(first loop), all the first bits are in their final
693 * places, all second bits but second bit from eight byte are in their places...
694 * only 1 eight bit from eight byte is in it's place). In second loop we do all
695 * operations symmetrically, in order to get other half of bits in their final
696 * spots. Results for first and second doubleword elements are saved in
697 * result[0] and result[1] respectively. In the end those results are saved in
698 * appropriate doubleword element of destination register vD.
699 */
700static void trans_vgbbd(DisasContext *ctx)
701{
702    int VT = rD(ctx->opcode);
703    int VB = rB(ctx->opcode);
704    TCGv_i64 tmp = tcg_temp_new_i64();
705    uint64_t mask = 0x8040201008040201ULL;
706    int i, j;
707
708    TCGv_i64 result[2];
709    result[0] = tcg_temp_new_i64();
710    result[1] = tcg_temp_new_i64();
711    TCGv_i64 avr[2];
712    avr[0] = tcg_temp_new_i64();
713    avr[1] = tcg_temp_new_i64();
714    TCGv_i64 tcg_mask = tcg_temp_new_i64();
715
716    tcg_gen_movi_i64(tcg_mask, mask);
717    for (j = 0; j < 2; j++) {
718        get_avr64(avr[j], VB, j);
719        tcg_gen_and_i64(result[j], avr[j], tcg_mask);
720    }
721    for (i = 1; i < 8; i++) {
722        tcg_gen_movi_i64(tcg_mask, mask >> (i * 8));
723        for (j = 0; j < 2; j++) {
724            tcg_gen_shri_i64(tmp, avr[j], i * 7);
725            tcg_gen_and_i64(tmp, tmp, tcg_mask);
726            tcg_gen_or_i64(result[j], result[j], tmp);
727        }
728    }
729    for (i = 1; i < 8; i++) {
730        tcg_gen_movi_i64(tcg_mask, mask << (i * 8));
731        for (j = 0; j < 2; j++) {
732            tcg_gen_shli_i64(tmp, avr[j], i * 7);
733            tcg_gen_and_i64(tmp, tmp, tcg_mask);
734            tcg_gen_or_i64(result[j], result[j], tmp);
735        }
736    }
737    for (j = 0; j < 2; j++) {
738        set_avr64(VT, result[j], j);
739    }
740
741    tcg_temp_free_i64(tmp);
742    tcg_temp_free_i64(tcg_mask);
743    tcg_temp_free_i64(result[0]);
744    tcg_temp_free_i64(result[1]);
745    tcg_temp_free_i64(avr[0]);
746    tcg_temp_free_i64(avr[1]);
747}
748
749/*
750 * vclzw VRT,VRB - Vector Count Leading Zeros Word
751 *
752 * Counting the number of leading zero bits of each word element in source
753 * register and placing result in appropriate word element of destination
754 * register.
755 */
756static void trans_vclzw(DisasContext *ctx)
757{
758    int VT = rD(ctx->opcode);
759    int VB = rB(ctx->opcode);
760    TCGv_i32 tmp = tcg_temp_new_i32();
761    int i;
762
763    /* Perform count for every word element using tcg_gen_clzi_i32. */
764    for (i = 0; i < 4; i++) {
765        tcg_gen_ld_i32(tmp, cpu_env,
766            offsetof(CPUPPCState, vsr[32 + VB].u64[0]) + i * 4);
767        tcg_gen_clzi_i32(tmp, tmp, 32);
768        tcg_gen_st_i32(tmp, cpu_env,
769            offsetof(CPUPPCState, vsr[32 + VT].u64[0]) + i * 4);
770    }
771
772    tcg_temp_free_i32(tmp);
773}
774
775/*
776 * vclzd VRT,VRB - Vector Count Leading Zeros Doubleword
777 *
778 * Counting the number of leading zero bits of each doubleword element in source
779 * register and placing result in appropriate doubleword element of destination
780 * register.
781 */
782static void trans_vclzd(DisasContext *ctx)
783{
784    int VT = rD(ctx->opcode);
785    int VB = rB(ctx->opcode);
786    TCGv_i64 avr = tcg_temp_new_i64();
787
788    /* high doubleword */
789    get_avr64(avr, VB, true);
790    tcg_gen_clzi_i64(avr, avr, 64);
791    set_avr64(VT, avr, true);
792
793    /* low doubleword */
794    get_avr64(avr, VB, false);
795    tcg_gen_clzi_i64(avr, avr, 64);
796    set_avr64(VT, avr, false);
797
798    tcg_temp_free_i64(avr);
799}
800
801GEN_VXFORM_V(vmuluwm, MO_32, tcg_gen_gvec_mul, 4, 2);
802GEN_VXFORM(vsrv, 2, 28);
803GEN_VXFORM(vslv, 2, 29);
804GEN_VXFORM(vslo, 6, 16);
805GEN_VXFORM(vsro, 6, 17);
806GEN_VXFORM(vaddcuw, 0, 6);
807GEN_VXFORM(vsubcuw, 0, 22);
808
809static bool do_vector_gvec3_VX(DisasContext *ctx, arg_VX *a, int vece,
810                               void (*gen_gvec)(unsigned, uint32_t, uint32_t,
811                                                uint32_t, uint32_t, uint32_t))
812{
813    REQUIRE_VECTOR(ctx);
814
815    gen_gvec(vece, avr_full_offset(a->vrt), avr_full_offset(a->vra),
816             avr_full_offset(a->vrb), 16, 16);
817
818    return true;
819}
820
821TRANS_FLAGS(ALTIVEC, VSLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shlv);
822TRANS_FLAGS(ALTIVEC, VSLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shlv);
823TRANS_FLAGS(ALTIVEC, VSLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shlv);
824TRANS_FLAGS2(ALTIVEC_207, VSLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shlv);
825
826TRANS_FLAGS(ALTIVEC, VSRB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shrv);
827TRANS_FLAGS(ALTIVEC, VSRH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shrv);
828TRANS_FLAGS(ALTIVEC, VSRW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shrv);
829TRANS_FLAGS2(ALTIVEC_207, VSRD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shrv);
830
831TRANS_FLAGS(ALTIVEC, VSRAB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_sarv);
832TRANS_FLAGS(ALTIVEC, VSRAH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_sarv);
833TRANS_FLAGS(ALTIVEC, VSRAW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_sarv);
834TRANS_FLAGS2(ALTIVEC_207, VSRAD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_sarv);
835
836TRANS_FLAGS(ALTIVEC, VRLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_rotlv)
837TRANS_FLAGS(ALTIVEC, VRLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_rotlv)
838TRANS_FLAGS(ALTIVEC, VRLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_rotlv)
839TRANS_FLAGS2(ALTIVEC_207, VRLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_rotlv)
840
841static TCGv_vec do_vrl_mask_vec(unsigned vece, TCGv_vec vrb)
842{
843    TCGv_vec t0 = tcg_temp_new_vec_matching(vrb),
844             t1 = tcg_temp_new_vec_matching(vrb),
845             t2 = tcg_temp_new_vec_matching(vrb),
846             ones = tcg_constant_vec_matching(vrb, vece, -1);
847
848    /* Extract b and e */
849    tcg_gen_dupi_vec(vece, t2, (8 << vece) - 1);
850
851    tcg_gen_shri_vec(vece, t0, vrb, 16);
852    tcg_gen_and_vec(vece, t0, t0, t2);
853
854    tcg_gen_shri_vec(vece, t1, vrb, 8);
855    tcg_gen_and_vec(vece, t1, t1, t2);
856
857    /* Compare b and e to negate the mask where begin > end */
858    tcg_gen_cmp_vec(TCG_COND_GT, vece, t2, t0, t1);
859
860    /* Create the mask with (~0 >> b) ^ ((~0 >> e) >> 1) */
861    tcg_gen_shrv_vec(vece, t0, ones, t0);
862    tcg_gen_shrv_vec(vece, t1, ones, t1);
863    tcg_gen_shri_vec(vece, t1, t1, 1);
864    tcg_gen_xor_vec(vece, t0, t0, t1);
865
866    /* negate the mask */
867    tcg_gen_xor_vec(vece, t0, t0, t2);
868
869    tcg_temp_free_vec(t1);
870    tcg_temp_free_vec(t2);
871
872    return t0;
873}
874
875static void gen_vrlnm_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
876                          TCGv_vec vrb)
877{
878    TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt);
879
880    /* Create the mask */
881    mask = do_vrl_mask_vec(vece, vrb);
882
883    /* Extract n */
884    tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
885    tcg_gen_and_vec(vece, n, vrb, n);
886
887    /* Rotate and mask */
888    tcg_gen_rotlv_vec(vece, vrt, vra, n);
889    tcg_gen_and_vec(vece, vrt, vrt, mask);
890
891    tcg_temp_free_vec(n);
892    tcg_temp_free_vec(mask);
893}
894
895static bool do_vrlnm(DisasContext *ctx, arg_VX *a, int vece)
896{
897    static const TCGOpcode vecop_list[] = {
898        INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
899        INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
900    };
901    static const GVecGen3 ops[2] = {
902        {
903            .fniv = gen_vrlnm_vec,
904            .fno = gen_helper_VRLWNM,
905            .opt_opc = vecop_list,
906            .load_dest = true,
907            .vece = MO_32
908        },
909        {
910            .fniv = gen_vrlnm_vec,
911            .fno = gen_helper_VRLDNM,
912            .opt_opc = vecop_list,
913            .load_dest = true,
914            .vece = MO_64
915        }
916    };
917
918    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
919    REQUIRE_VSX(ctx);
920
921    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
922                   avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
923
924    return true;
925}
926
927TRANS(VRLWNM, do_vrlnm, MO_32)
928TRANS(VRLDNM, do_vrlnm, MO_64)
929
930static void gen_vrlmi_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
931                          TCGv_vec vrb)
932{
933    TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt),
934             tmp = tcg_temp_new_vec_matching(vrt);
935
936    /* Create the mask */
937    mask = do_vrl_mask_vec(vece, vrb);
938
939    /* Extract n */
940    tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
941    tcg_gen_and_vec(vece, n, vrb, n);
942
943    /* Rotate and insert */
944    tcg_gen_rotlv_vec(vece, tmp, vra, n);
945    tcg_gen_bitsel_vec(vece, vrt, mask, tmp, vrt);
946
947    tcg_temp_free_vec(n);
948    tcg_temp_free_vec(tmp);
949    tcg_temp_free_vec(mask);
950}
951
952static bool do_vrlmi(DisasContext *ctx, arg_VX *a, int vece)
953{
954    static const TCGOpcode vecop_list[] = {
955        INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
956        INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
957    };
958    static const GVecGen3 ops[2] = {
959        {
960            .fniv = gen_vrlmi_vec,
961            .fno = gen_helper_VRLWMI,
962            .opt_opc = vecop_list,
963            .load_dest = true,
964            .vece = MO_32
965        },
966        {
967            .fniv = gen_vrlnm_vec,
968            .fno = gen_helper_VRLDMI,
969            .opt_opc = vecop_list,
970            .load_dest = true,
971            .vece = MO_64
972        }
973    };
974
975    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
976    REQUIRE_VSX(ctx);
977
978    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
979                   avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
980
981    return true;
982}
983
984TRANS(VRLWMI, do_vrlmi, MO_32)
985TRANS(VRLDMI, do_vrlmi, MO_64)
986
987static bool do_vector_shift_quad(DisasContext *ctx, arg_VX *a, bool right,
988                                 bool alg)
989{
990    TCGv_i64 hi, lo, t0, t1, n, zero = tcg_constant_i64(0);
991
992    REQUIRE_VECTOR(ctx);
993
994    n = tcg_temp_new_i64();
995    hi = tcg_temp_new_i64();
996    lo = tcg_temp_new_i64();
997    t0 = tcg_temp_new_i64();
998    t1 = tcg_const_i64(0);
999
1000    get_avr64(lo, a->vra, false);
1001    get_avr64(hi, a->vra, true);
1002
1003    get_avr64(n, a->vrb, true);
1004
1005    tcg_gen_andi_i64(t0, n, 64);
1006    if (right) {
1007        tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, hi, lo);
1008        if (alg) {
1009            tcg_gen_sari_i64(t1, lo, 63);
1010        }
1011        tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, t1, hi);
1012    } else {
1013        tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, lo, hi);
1014        tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, zero, lo);
1015    }
1016    tcg_gen_andi_i64(n, n, 0x3F);
1017
1018    if (right) {
1019        if (alg) {
1020            tcg_gen_sar_i64(t0, hi, n);
1021        } else {
1022            tcg_gen_shr_i64(t0, hi, n);
1023        }
1024    } else {
1025        tcg_gen_shl_i64(t0, lo, n);
1026    }
1027    set_avr64(a->vrt, t0, right);
1028
1029    if (right) {
1030        tcg_gen_shr_i64(lo, lo, n);
1031    } else {
1032        tcg_gen_shl_i64(hi, hi, n);
1033    }
1034    tcg_gen_xori_i64(n, n, 63);
1035    if (right) {
1036        tcg_gen_shl_i64(hi, hi, n);
1037        tcg_gen_shli_i64(hi, hi, 1);
1038    } else {
1039        tcg_gen_shr_i64(lo, lo, n);
1040        tcg_gen_shri_i64(lo, lo, 1);
1041    }
1042    tcg_gen_or_i64(hi, hi, lo);
1043    set_avr64(a->vrt, hi, !right);
1044
1045    tcg_temp_free_i64(hi);
1046    tcg_temp_free_i64(lo);
1047    tcg_temp_free_i64(t0);
1048    tcg_temp_free_i64(t1);
1049    tcg_temp_free_i64(n);
1050
1051    return true;
1052}
1053
1054TRANS_FLAGS2(ISA310, VSLQ, do_vector_shift_quad, false, false);
1055TRANS_FLAGS2(ISA310, VSRQ, do_vector_shift_quad, true, false);
1056TRANS_FLAGS2(ISA310, VSRAQ, do_vector_shift_quad, true, true);
1057
1058static void do_vrlq_mask(TCGv_i64 mh, TCGv_i64 ml, TCGv_i64 b, TCGv_i64 e)
1059{
1060    TCGv_i64 th, tl, t0, t1, zero = tcg_constant_i64(0),
1061             ones = tcg_constant_i64(-1);
1062
1063    th = tcg_temp_new_i64();
1064    tl = tcg_temp_new_i64();
1065    t0 = tcg_temp_new_i64();
1066    t1 = tcg_temp_new_i64();
1067
1068    /* m = ~0 >> b */
1069    tcg_gen_andi_i64(t0, b, 64);
1070    tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
1071    tcg_gen_andi_i64(t0, b, 0x3F);
1072    tcg_gen_shr_i64(mh, t1, t0);
1073    tcg_gen_shr_i64(ml, ones, t0);
1074    tcg_gen_xori_i64(t0, t0, 63);
1075    tcg_gen_shl_i64(t1, t1, t0);
1076    tcg_gen_shli_i64(t1, t1, 1);
1077    tcg_gen_or_i64(ml, t1, ml);
1078
1079    /* t = ~0 >> e */
1080    tcg_gen_andi_i64(t0, e, 64);
1081    tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
1082    tcg_gen_andi_i64(t0, e, 0x3F);
1083    tcg_gen_shr_i64(th, t1, t0);
1084    tcg_gen_shr_i64(tl, ones, t0);
1085    tcg_gen_xori_i64(t0, t0, 63);
1086    tcg_gen_shl_i64(t1, t1, t0);
1087    tcg_gen_shli_i64(t1, t1, 1);
1088    tcg_gen_or_i64(tl, t1, tl);
1089
1090    /* t = t >> 1 */
1091    tcg_gen_shli_i64(t0, th, 63);
1092    tcg_gen_shri_i64(tl, tl, 1);
1093    tcg_gen_shri_i64(th, th, 1);
1094    tcg_gen_or_i64(tl, t0, tl);
1095
1096    /* m = m ^ t */
1097    tcg_gen_xor_i64(mh, mh, th);
1098    tcg_gen_xor_i64(ml, ml, tl);
1099
1100    /* Negate the mask if begin > end */
1101    tcg_gen_movcond_i64(TCG_COND_GT, t0, b, e, ones, zero);
1102
1103    tcg_gen_xor_i64(mh, mh, t0);
1104    tcg_gen_xor_i64(ml, ml, t0);
1105
1106    tcg_temp_free_i64(th);
1107    tcg_temp_free_i64(tl);
1108    tcg_temp_free_i64(t0);
1109    tcg_temp_free_i64(t1);
1110}
1111
1112static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask,
1113                                bool insert)
1114{
1115    TCGv_i64 ah, al, vrb, n, t0, t1, zero = tcg_constant_i64(0);
1116
1117    REQUIRE_VECTOR(ctx);
1118    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1119
1120    ah = tcg_temp_new_i64();
1121    al = tcg_temp_new_i64();
1122    vrb = tcg_temp_new_i64();
1123    n = tcg_temp_new_i64();
1124    t0 = tcg_temp_new_i64();
1125    t1 = tcg_temp_new_i64();
1126
1127    get_avr64(ah, a->vra, true);
1128    get_avr64(al, a->vra, false);
1129    get_avr64(vrb, a->vrb, true);
1130
1131    tcg_gen_mov_i64(t0, ah);
1132    tcg_gen_andi_i64(t1, vrb, 64);
1133    tcg_gen_movcond_i64(TCG_COND_NE, ah, t1, zero, al, ah);
1134    tcg_gen_movcond_i64(TCG_COND_NE, al, t1, zero, t0, al);
1135    tcg_gen_andi_i64(n, vrb, 0x3F);
1136
1137    tcg_gen_shl_i64(t0, ah, n);
1138    tcg_gen_shl_i64(t1, al, n);
1139
1140    tcg_gen_xori_i64(n, n, 63);
1141
1142    tcg_gen_shr_i64(al, al, n);
1143    tcg_gen_shri_i64(al, al, 1);
1144    tcg_gen_or_i64(t0, al, t0);
1145
1146    tcg_gen_shr_i64(ah, ah, n);
1147    tcg_gen_shri_i64(ah, ah, 1);
1148    tcg_gen_or_i64(t1, ah, t1);
1149
1150    if (mask || insert) {
1151        tcg_gen_shri_i64(n, vrb, 8);
1152        tcg_gen_shri_i64(vrb, vrb, 16);
1153        tcg_gen_andi_i64(n, n, 0x7f);
1154        tcg_gen_andi_i64(vrb, vrb, 0x7f);
1155
1156        do_vrlq_mask(ah, al, vrb, n);
1157
1158        tcg_gen_and_i64(t0, t0, ah);
1159        tcg_gen_and_i64(t1, t1, al);
1160
1161        if (insert) {
1162            get_avr64(n, a->vrt, true);
1163            get_avr64(vrb, a->vrt, false);
1164            tcg_gen_not_i64(ah, ah);
1165            tcg_gen_not_i64(al, al);
1166            tcg_gen_and_i64(n, n, ah);
1167            tcg_gen_and_i64(vrb, vrb, al);
1168            tcg_gen_or_i64(t0, t0, n);
1169            tcg_gen_or_i64(t1, t1, vrb);
1170        }
1171    }
1172
1173    set_avr64(a->vrt, t0, true);
1174    set_avr64(a->vrt, t1, false);
1175
1176    tcg_temp_free_i64(ah);
1177    tcg_temp_free_i64(al);
1178    tcg_temp_free_i64(vrb);
1179    tcg_temp_free_i64(n);
1180    tcg_temp_free_i64(t0);
1181    tcg_temp_free_i64(t1);
1182
1183    return true;
1184}
1185
1186TRANS(VRLQ, do_vector_rotl_quad, false, false)
1187TRANS(VRLQNM, do_vector_rotl_quad, true, false)
1188TRANS(VRLQMI, do_vector_rotl_quad, false, true)
1189
1190#define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3)               \
1191static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t,     \
1192                                         TCGv_vec sat, TCGv_vec a,      \
1193                                         TCGv_vec b)                    \
1194{                                                                       \
1195    TCGv_vec x = tcg_temp_new_vec_matching(t);                          \
1196    glue(glue(tcg_gen_, NORM), _vec)(VECE, x, a, b);                    \
1197    glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b);                     \
1198    tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t);                        \
1199    tcg_gen_or_vec(VECE, sat, sat, x);                                  \
1200    tcg_temp_free_vec(x);                                               \
1201}                                                                       \
1202static void glue(gen_, NAME)(DisasContext *ctx)                         \
1203{                                                                       \
1204    static const TCGOpcode vecop_list[] = {                             \
1205        glue(glue(INDEX_op_, NORM), _vec),                              \
1206        glue(glue(INDEX_op_, SAT), _vec),                               \
1207        INDEX_op_cmp_vec, 0                                             \
1208    };                                                                  \
1209    static const GVecGen4 g = {                                         \
1210        .fniv = glue(glue(gen_, NAME), _vec),                           \
1211        .fno = glue(gen_helper_, NAME),                                 \
1212        .opt_opc = vecop_list,                                          \
1213        .write_aofs = true,                                             \
1214        .vece = VECE,                                                   \
1215    };                                                                  \
1216    if (unlikely(!ctx->altivec_enabled)) {                              \
1217        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
1218        return;                                                         \
1219    }                                                                   \
1220    tcg_gen_gvec_4(avr_full_offset(rD(ctx->opcode)),                    \
1221                   offsetof(CPUPPCState, vscr_sat),                     \
1222                   avr_full_offset(rA(ctx->opcode)),                    \
1223                   avr_full_offset(rB(ctx->opcode)),                    \
1224                   16, 16, &g);                                         \
1225}
1226
1227GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8);
1228GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0,       \
1229                    vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
1230GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9);
1231GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
1232                vmul10euq, PPC_NONE, PPC2_ISA300)
1233GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10);
1234GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12);
1235GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13);
1236GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14);
1237GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24);
1238GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25);
1239GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
1240GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
1241GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
1242GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
1243GEN_VXFORM(vadduqm, 0, 4);
1244GEN_VXFORM(vaddcuq, 0, 5);
1245GEN_VXFORM3(vaddeuqm, 30, 0);
1246GEN_VXFORM3(vaddecuq, 30, 0);
1247GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
1248            vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
1249GEN_VXFORM(vsubuqm, 0, 20);
1250GEN_VXFORM(vsubcuq, 0, 21);
1251GEN_VXFORM3(vsubeuqm, 31, 0);
1252GEN_VXFORM3(vsubecuq, 31, 0);
1253GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
1254            vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
1255GEN_VXFORM_TRANS(vsl, 2, 7);
1256GEN_VXFORM_TRANS(vsr, 2, 11);
1257GEN_VXFORM_ENV(vpkuhum, 7, 0);
1258GEN_VXFORM_ENV(vpkuwum, 7, 1);
1259GEN_VXFORM_ENV(vpkudum, 7, 17);
1260GEN_VXFORM_ENV(vpkuhus, 7, 2);
1261GEN_VXFORM_ENV(vpkuwus, 7, 3);
1262GEN_VXFORM_ENV(vpkudus, 7, 19);
1263GEN_VXFORM_ENV(vpkshus, 7, 4);
1264GEN_VXFORM_ENV(vpkswus, 7, 5);
1265GEN_VXFORM_ENV(vpksdus, 7, 21);
1266GEN_VXFORM_ENV(vpkshss, 7, 6);
1267GEN_VXFORM_ENV(vpkswss, 7, 7);
1268GEN_VXFORM_ENV(vpksdss, 7, 23);
1269GEN_VXFORM(vpkpx, 7, 12);
1270GEN_VXFORM_ENV(vsum4ubs, 4, 24);
1271GEN_VXFORM_ENV(vsum4sbs, 4, 28);
1272GEN_VXFORM_ENV(vsum4shs, 4, 25);
1273GEN_VXFORM_ENV(vsum2sws, 4, 26);
1274GEN_VXFORM_ENV(vsumsws, 4, 30);
1275GEN_VXFORM_ENV(vaddfp, 5, 0);
1276GEN_VXFORM_ENV(vsubfp, 5, 1);
1277GEN_VXFORM_ENV(vmaxfp, 5, 16);
1278GEN_VXFORM_ENV(vminfp, 5, 17);
1279GEN_VXFORM_HETRO(vextublx, 6, 24)
1280GEN_VXFORM_HETRO(vextuhlx, 6, 25)
1281GEN_VXFORM_HETRO(vextuwlx, 6, 26)
1282GEN_VXFORM_TRANS_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207,
1283                vextuwlx, PPC_NONE, PPC2_ISA300)
1284GEN_VXFORM_HETRO(vextubrx, 6, 28)
1285GEN_VXFORM_HETRO(vextuhrx, 6, 29)
1286GEN_VXFORM_HETRO(vextuwrx, 6, 30)
1287GEN_VXFORM_TRANS(lvsl, 6, 31)
1288GEN_VXFORM_TRANS(lvsr, 6, 32)
1289GEN_VXFORM_TRANS_DUAL(vmrgew, PPC_NONE, PPC2_ALTIVEC_207,
1290                vextuwrx, PPC_NONE, PPC2_ISA300)
1291
1292#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
1293static void glue(gen_, name)(DisasContext *ctx)                         \
1294    {                                                                   \
1295        TCGv_ptr ra, rb, rd;                                            \
1296        if (unlikely(!ctx->altivec_enabled)) {                          \
1297            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1298            return;                                                     \
1299        }                                                               \
1300        ra = gen_avr_ptr(rA(ctx->opcode));                              \
1301        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1302        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1303        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
1304        tcg_temp_free_ptr(ra);                                          \
1305        tcg_temp_free_ptr(rb);                                          \
1306        tcg_temp_free_ptr(rd);                                          \
1307    }
1308
1309#define GEN_VXRFORM(name, opc2, opc3)                                \
1310    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
1311    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
1312
1313/*
1314 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
1315 * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
1316 * come from different versions of the ISA, so we must also support a
1317 * pair of flags for each instruction.
1318 */
1319#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
1320static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
1321{                                                                      \
1322    if ((Rc(ctx->opcode) == 0) &&                                      \
1323        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
1324        if (Rc21(ctx->opcode) == 0) {                                  \
1325            gen_##name0(ctx);                                          \
1326        } else {                                                       \
1327            gen_##name0##_(ctx);                                       \
1328        }                                                              \
1329    } else if ((Rc(ctx->opcode) == 1) &&                               \
1330        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
1331        if (Rc21(ctx->opcode) == 0) {                                  \
1332            gen_##name1(ctx);                                          \
1333        } else {                                                       \
1334            gen_##name1##_(ctx);                                       \
1335        }                                                              \
1336    } else {                                                           \
1337        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
1338    }                                                                  \
1339}
1340
1341static void do_vcmp_rc(int vrt)
1342{
1343    TCGv_i64 tmp, set, clr;
1344
1345    tmp = tcg_temp_new_i64();
1346    set = tcg_temp_new_i64();
1347    clr = tcg_temp_new_i64();
1348
1349    get_avr64(tmp, vrt, true);
1350    tcg_gen_mov_i64(set, tmp);
1351    get_avr64(tmp, vrt, false);
1352    tcg_gen_or_i64(clr, set, tmp);
1353    tcg_gen_and_i64(set, set, tmp);
1354
1355    tcg_gen_setcondi_i64(TCG_COND_EQ, clr, clr, 0);
1356    tcg_gen_shli_i64(clr, clr, 1);
1357
1358    tcg_gen_setcondi_i64(TCG_COND_EQ, set, set, -1);
1359    tcg_gen_shli_i64(set, set, 3);
1360
1361    tcg_gen_or_i64(tmp, set, clr);
1362    tcg_gen_extrl_i64_i32(cpu_crf[6], tmp);
1363
1364    tcg_temp_free_i64(tmp);
1365    tcg_temp_free_i64(set);
1366    tcg_temp_free_i64(clr);
1367}
1368
1369static bool do_vcmp(DisasContext *ctx, arg_VC *a, TCGCond cond, int vece)
1370{
1371    REQUIRE_VECTOR(ctx);
1372
1373    tcg_gen_gvec_cmp(cond, vece, avr_full_offset(a->vrt),
1374                     avr_full_offset(a->vra), avr_full_offset(a->vrb), 16, 16);
1375
1376    if (a->rc) {
1377        do_vcmp_rc(a->vrt);
1378    }
1379
1380    return true;
1381}
1382
1383TRANS_FLAGS(ALTIVEC, VCMPEQUB, do_vcmp, TCG_COND_EQ, MO_8)
1384TRANS_FLAGS(ALTIVEC, VCMPEQUH, do_vcmp, TCG_COND_EQ, MO_16)
1385TRANS_FLAGS(ALTIVEC, VCMPEQUW, do_vcmp, TCG_COND_EQ, MO_32)
1386TRANS_FLAGS2(ALTIVEC_207, VCMPEQUD, do_vcmp, TCG_COND_EQ, MO_64)
1387
1388TRANS_FLAGS(ALTIVEC, VCMPGTSB, do_vcmp, TCG_COND_GT, MO_8)
1389TRANS_FLAGS(ALTIVEC, VCMPGTSH, do_vcmp, TCG_COND_GT, MO_16)
1390TRANS_FLAGS(ALTIVEC, VCMPGTSW, do_vcmp, TCG_COND_GT, MO_32)
1391TRANS_FLAGS2(ALTIVEC_207, VCMPGTSD, do_vcmp, TCG_COND_GT, MO_64)
1392TRANS_FLAGS(ALTIVEC, VCMPGTUB, do_vcmp, TCG_COND_GTU, MO_8)
1393TRANS_FLAGS(ALTIVEC, VCMPGTUH, do_vcmp, TCG_COND_GTU, MO_16)
1394TRANS_FLAGS(ALTIVEC, VCMPGTUW, do_vcmp, TCG_COND_GTU, MO_32)
1395TRANS_FLAGS2(ALTIVEC_207, VCMPGTUD, do_vcmp, TCG_COND_GTU, MO_64)
1396
1397TRANS_FLAGS2(ISA300, VCMPNEB, do_vcmp, TCG_COND_NE, MO_8)
1398TRANS_FLAGS2(ISA300, VCMPNEH, do_vcmp, TCG_COND_NE, MO_16)
1399TRANS_FLAGS2(ISA300, VCMPNEW, do_vcmp, TCG_COND_NE, MO_32)
1400
1401static void gen_vcmpnez_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1402{
1403    TCGv_vec t0, t1, zero;
1404
1405    t0 = tcg_temp_new_vec_matching(t);
1406    t1 = tcg_temp_new_vec_matching(t);
1407    zero = tcg_constant_vec_matching(t, vece, 0);
1408
1409    tcg_gen_cmp_vec(TCG_COND_EQ, vece, t0, a, zero);
1410    tcg_gen_cmp_vec(TCG_COND_EQ, vece, t1, b, zero);
1411    tcg_gen_cmp_vec(TCG_COND_NE, vece, t, a, b);
1412
1413    tcg_gen_or_vec(vece, t, t, t0);
1414    tcg_gen_or_vec(vece, t, t, t1);
1415
1416    tcg_temp_free_vec(t0);
1417    tcg_temp_free_vec(t1);
1418}
1419
1420static bool do_vcmpnez(DisasContext *ctx, arg_VC *a, int vece)
1421{
1422    static const TCGOpcode vecop_list[] = {
1423        INDEX_op_cmp_vec, 0
1424    };
1425    static const GVecGen3 ops[3] = {
1426        {
1427            .fniv = gen_vcmpnez_vec,
1428            .fno = gen_helper_VCMPNEZB,
1429            .opt_opc = vecop_list,
1430            .vece = MO_8
1431        },
1432        {
1433            .fniv = gen_vcmpnez_vec,
1434            .fno = gen_helper_VCMPNEZH,
1435            .opt_opc = vecop_list,
1436            .vece = MO_16
1437        },
1438        {
1439            .fniv = gen_vcmpnez_vec,
1440            .fno = gen_helper_VCMPNEZW,
1441            .opt_opc = vecop_list,
1442            .vece = MO_32
1443        }
1444    };
1445
1446    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1447    REQUIRE_VECTOR(ctx);
1448
1449    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
1450                   avr_full_offset(a->vrb), 16, 16, &ops[vece]);
1451
1452    if (a->rc) {
1453        do_vcmp_rc(a->vrt);
1454    }
1455
1456    return true;
1457}
1458
1459TRANS(VCMPNEZB, do_vcmpnez, MO_8)
1460TRANS(VCMPNEZH, do_vcmpnez, MO_16)
1461TRANS(VCMPNEZW, do_vcmpnez, MO_32)
1462
1463static bool trans_VCMPEQUQ(DisasContext *ctx, arg_VC *a)
1464{
1465    TCGv_i64 t0, t1, t2;
1466
1467    t0 = tcg_temp_new_i64();
1468    t1 = tcg_temp_new_i64();
1469    t2 = tcg_temp_new_i64();
1470
1471    get_avr64(t0, a->vra, true);
1472    get_avr64(t1, a->vrb, true);
1473    tcg_gen_xor_i64(t2, t0, t1);
1474
1475    get_avr64(t0, a->vra, false);
1476    get_avr64(t1, a->vrb, false);
1477    tcg_gen_xor_i64(t1, t0, t1);
1478
1479    tcg_gen_or_i64(t1, t1, t2);
1480    tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t1, 0);
1481    tcg_gen_neg_i64(t1, t1);
1482
1483    set_avr64(a->vrt, t1, true);
1484    set_avr64(a->vrt, t1, false);
1485
1486    if (a->rc) {
1487        tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
1488        tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
1489        tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
1490    }
1491
1492    tcg_temp_free_i64(t0);
1493    tcg_temp_free_i64(t1);
1494    tcg_temp_free_i64(t2);
1495
1496    return true;
1497}
1498
1499static bool do_vcmpgtq(DisasContext *ctx, arg_VC *a, bool sign)
1500{
1501    TCGv_i64 t0, t1, t2;
1502
1503    t0 = tcg_temp_new_i64();
1504    t1 = tcg_temp_new_i64();
1505    t2 = tcg_temp_new_i64();
1506
1507    get_avr64(t0, a->vra, false);
1508    get_avr64(t1, a->vrb, false);
1509    tcg_gen_setcond_i64(TCG_COND_GTU, t2, t0, t1);
1510
1511    get_avr64(t0, a->vra, true);
1512    get_avr64(t1, a->vrb, true);
1513    tcg_gen_movcond_i64(TCG_COND_EQ, t2, t0, t1, t2, tcg_constant_i64(0));
1514    tcg_gen_setcond_i64(sign ? TCG_COND_GT : TCG_COND_GTU, t1, t0, t1);
1515
1516    tcg_gen_or_i64(t1, t1, t2);
1517    tcg_gen_neg_i64(t1, t1);
1518
1519    set_avr64(a->vrt, t1, true);
1520    set_avr64(a->vrt, t1, false);
1521
1522    if (a->rc) {
1523        tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
1524        tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
1525        tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
1526    }
1527
1528    tcg_temp_free_i64(t0);
1529    tcg_temp_free_i64(t1);
1530    tcg_temp_free_i64(t2);
1531
1532    return true;
1533}
1534
1535TRANS(VCMPGTSQ, do_vcmpgtq, true)
1536TRANS(VCMPGTUQ, do_vcmpgtq, false)
1537
1538static bool do_vcmpq(DisasContext *ctx, arg_VX_bf *a, bool sign)
1539{
1540    TCGv_i64 vra, vrb;
1541    TCGLabel *gt, *lt, *done;
1542
1543    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1544    REQUIRE_VECTOR(ctx);
1545
1546    vra = tcg_temp_local_new_i64();
1547    vrb = tcg_temp_local_new_i64();
1548    gt = gen_new_label();
1549    lt = gen_new_label();
1550    done = gen_new_label();
1551
1552    get_avr64(vra, a->vra, true);
1553    get_avr64(vrb, a->vrb, true);
1554    tcg_gen_brcond_i64((sign ? TCG_COND_GT : TCG_COND_GTU), vra, vrb, gt);
1555    tcg_gen_brcond_i64((sign ? TCG_COND_LT : TCG_COND_LTU), vra, vrb, lt);
1556
1557    get_avr64(vra, a->vra, false);
1558    get_avr64(vrb, a->vrb, false);
1559    tcg_gen_brcond_i64(TCG_COND_GTU, vra, vrb, gt);
1560    tcg_gen_brcond_i64(TCG_COND_LTU, vra, vrb, lt);
1561
1562    tcg_gen_movi_i32(cpu_crf[a->bf], CRF_EQ);
1563    tcg_gen_br(done);
1564
1565    gen_set_label(gt);
1566    tcg_gen_movi_i32(cpu_crf[a->bf], CRF_GT);
1567    tcg_gen_br(done);
1568
1569    gen_set_label(lt);
1570    tcg_gen_movi_i32(cpu_crf[a->bf], CRF_LT);
1571    tcg_gen_br(done);
1572
1573    gen_set_label(done);
1574    tcg_temp_free_i64(vra);
1575    tcg_temp_free_i64(vrb);
1576
1577    return true;
1578}
1579
1580TRANS(VCMPSQ, do_vcmpq, true)
1581TRANS(VCMPUQ, do_vcmpq, false)
1582
1583GEN_VXRFORM(vcmpeqfp, 3, 3)
1584GEN_VXRFORM(vcmpgefp, 3, 7)
1585GEN_VXRFORM(vcmpgtfp, 3, 11)
1586GEN_VXRFORM(vcmpbfp, 3, 15)
1587
1588static void gen_vsplti(DisasContext *ctx, int vece)
1589{
1590    int simm;
1591
1592    if (unlikely(!ctx->altivec_enabled)) {
1593        gen_exception(ctx, POWERPC_EXCP_VPU);
1594        return;
1595    }
1596
1597    simm = SIMM5(ctx->opcode);
1598    tcg_gen_gvec_dup_imm(vece, avr_full_offset(rD(ctx->opcode)), 16, 16, simm);
1599}
1600
1601#define GEN_VXFORM_VSPLTI(name, vece, opc2, opc3) \
1602static void glue(gen_, name)(DisasContext *ctx) { gen_vsplti(ctx, vece); }
1603
1604GEN_VXFORM_VSPLTI(vspltisb, MO_8, 6, 12);
1605GEN_VXFORM_VSPLTI(vspltish, MO_16, 6, 13);
1606GEN_VXFORM_VSPLTI(vspltisw, MO_32, 6, 14);
1607
1608#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
1609static void glue(gen_, name)(DisasContext *ctx)                         \
1610    {                                                                   \
1611        TCGv_ptr rb, rd;                                                \
1612        if (unlikely(!ctx->altivec_enabled)) {                          \
1613            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1614            return;                                                     \
1615        }                                                               \
1616        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1617        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1618        gen_helper_##name(rd, rb);                                      \
1619        tcg_temp_free_ptr(rb);                                          \
1620        tcg_temp_free_ptr(rd);                                          \
1621    }
1622
1623#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
1624static void glue(gen_, name)(DisasContext *ctx)                         \
1625    {                                                                   \
1626        TCGv_ptr rb, rd;                                                \
1627                                                                        \
1628        if (unlikely(!ctx->altivec_enabled)) {                          \
1629            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1630            return;                                                     \
1631        }                                                               \
1632        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1633        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1634        gen_helper_##name(cpu_env, rd, rb);                             \
1635        tcg_temp_free_ptr(rb);                                          \
1636        tcg_temp_free_ptr(rd);                                          \
1637    }
1638
1639#define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4)                        \
1640static void glue(gen_, name)(DisasContext *ctx)                         \
1641    {                                                                   \
1642        TCGv_ptr rb, rd;                                                \
1643        if (unlikely(!ctx->altivec_enabled)) {                          \
1644            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1645            return;                                                     \
1646        }                                                               \
1647        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1648        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1649        gen_helper_##name(rd, rb);                                      \
1650        tcg_temp_free_ptr(rb);                                          \
1651        tcg_temp_free_ptr(rd);                                          \
1652    }
1653
1654#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4)                        \
1655static void glue(gen_, name)(DisasContext *ctx)                         \
1656    {                                                                   \
1657        TCGv_ptr rb;                                                    \
1658        if (unlikely(!ctx->altivec_enabled)) {                          \
1659            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1660            return;                                                     \
1661        }                                                               \
1662        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1663        gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb);                \
1664        tcg_temp_free_ptr(rb);                                          \
1665    }
1666GEN_VXFORM_NOA(vupkhsb, 7, 8);
1667GEN_VXFORM_NOA(vupkhsh, 7, 9);
1668GEN_VXFORM_NOA(vupkhsw, 7, 25);
1669GEN_VXFORM_NOA(vupklsb, 7, 10);
1670GEN_VXFORM_NOA(vupklsh, 7, 11);
1671GEN_VXFORM_NOA(vupklsw, 7, 27);
1672GEN_VXFORM_NOA(vupkhpx, 7, 13);
1673GEN_VXFORM_NOA(vupklpx, 7, 15);
1674GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
1675GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
1676GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
1677GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
1678GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
1679GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
1680GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
1681GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
1682GEN_VXFORM_NOA(vprtybw, 1, 24);
1683GEN_VXFORM_NOA(vprtybd, 1, 24);
1684GEN_VXFORM_NOA(vprtybq, 1, 24);
1685
1686static void gen_vsplt(DisasContext *ctx, int vece)
1687{
1688    int uimm, dofs, bofs;
1689
1690    if (unlikely(!ctx->altivec_enabled)) {
1691        gen_exception(ctx, POWERPC_EXCP_VPU);
1692        return;
1693    }
1694
1695    uimm = UIMM5(ctx->opcode);
1696    bofs = avr_full_offset(rB(ctx->opcode));
1697    dofs = avr_full_offset(rD(ctx->opcode));
1698
1699    /* Experimental testing shows that hardware masks the immediate.  */
1700    bofs += (uimm << vece) & 15;
1701#ifndef HOST_WORDS_BIGENDIAN
1702    bofs ^= 15;
1703    bofs &= ~((1 << vece) - 1);
1704#endif
1705
1706    tcg_gen_gvec_dup_mem(vece, dofs, bofs, 16, 16);
1707}
1708
1709#define GEN_VXFORM_VSPLT(name, vece, opc2, opc3) \
1710static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); }
1711
1712#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
1713static void glue(gen_, name)(DisasContext *ctx)                         \
1714    {                                                                   \
1715        TCGv_ptr rb, rd;                                                \
1716        TCGv_i32 uimm;                                                  \
1717                                                                        \
1718        if (unlikely(!ctx->altivec_enabled)) {                          \
1719            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1720            return;                                                     \
1721        }                                                               \
1722        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
1723        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1724        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1725        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
1726        tcg_temp_free_i32(uimm);                                        \
1727        tcg_temp_free_ptr(rb);                                          \
1728        tcg_temp_free_ptr(rd);                                          \
1729    }
1730
1731#define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max)              \
1732static void glue(gen_, name)(DisasContext *ctx)                         \
1733    {                                                                   \
1734        TCGv_ptr rb, rd;                                                \
1735        uint8_t uimm = UIMM4(ctx->opcode);                              \
1736        TCGv_i32 t0;                                                    \
1737        if (unlikely(!ctx->altivec_enabled)) {                          \
1738            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
1739            return;                                                     \
1740        }                                                               \
1741        if (uimm > splat_max) {                                         \
1742            uimm = 0;                                                   \
1743        }                                                               \
1744        t0 = tcg_temp_new_i32();                                        \
1745        tcg_gen_movi_i32(t0, uimm);                                     \
1746        rb = gen_avr_ptr(rB(ctx->opcode));                              \
1747        rd = gen_avr_ptr(rD(ctx->opcode));                              \
1748        gen_helper_##name(rd, rb, t0);                                  \
1749        tcg_temp_free_i32(t0);                                          \
1750        tcg_temp_free_ptr(rb);                                          \
1751        tcg_temp_free_ptr(rd);                                          \
1752    }
1753
1754GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
1755GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9);
1756GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10);
1757GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
1758GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
1759GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
1760GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
1761GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
1762GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
1763GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
1764GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
1765GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
1766                vextractub, PPC_NONE, PPC2_ISA300);
1767GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
1768                vextractuh, PPC_NONE, PPC2_ISA300);
1769GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
1770                vextractuw, PPC_NONE, PPC2_ISA300);
1771
1772static bool trans_VGNB(DisasContext *ctx, arg_VX_n *a)
1773{
1774    /*
1775     * Similar to do_vextractm, we'll use a sequence of mask-shift-or operations
1776     * to gather the bits. The masks can be created with
1777     *
1778     * uint64_t mask(uint64_t n, uint64_t step)
1779     * {
1780     *     uint64_t p = ((1UL << (1UL << step)) - 1UL) << ((n - 1UL) << step),
1781     *                  plen = n << step, m = 0;
1782     *     for(int i = 0; i < 64/plen; i++) {
1783     *         m |= p;
1784     *         m = ror64(m, plen);
1785     *     }
1786     *     p >>= plen * DIV_ROUND_UP(64, plen) - 64;
1787     *     return m | p;
1788     * }
1789     *
1790     * But since there are few values of N, we'll use a lookup table to avoid
1791     * these calculations at runtime.
1792     */
1793    static const uint64_t mask[6][5] = {
1794        {
1795            0xAAAAAAAAAAAAAAAAULL, 0xccccccccccccccccULL, 0xf0f0f0f0f0f0f0f0ULL,
1796            0xff00ff00ff00ff00ULL, 0xffff0000ffff0000ULL
1797        },
1798        {
1799            0x9249249249249249ULL, 0xC30C30C30C30C30CULL, 0xF00F00F00F00F00FULL,
1800            0xFF0000FF0000FF00ULL, 0xFFFF00000000FFFFULL
1801        },
1802        {
1803            /* For N >= 4, some mask operations can be elided */
1804            0x8888888888888888ULL, 0, 0xf000f000f000f000ULL, 0,
1805            0xFFFF000000000000ULL
1806        },
1807        {
1808            0x8421084210842108ULL, 0, 0xF0000F0000F0000FULL, 0, 0
1809        },
1810        {
1811            0x8208208208208208ULL, 0, 0xF00000F00000F000ULL, 0, 0
1812        },
1813        {
1814            0x8102040810204081ULL, 0, 0xF000000F000000F0ULL, 0, 0
1815        }
1816    };
1817    uint64_t m;
1818    int i, sh, nbits = DIV_ROUND_UP(64, a->n);
1819    TCGv_i64 hi, lo, t0, t1;
1820
1821    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1822    REQUIRE_VECTOR(ctx);
1823
1824    if (a->n < 2) {
1825        /*
1826         * "N can be any value between 2 and 7, inclusive." Otherwise, the
1827         * result is undefined, so we don't need to change RT. Also, N > 7 is
1828         * impossible since the immediate field is 3 bits only.
1829         */
1830        return true;
1831    }
1832
1833    hi = tcg_temp_new_i64();
1834    lo = tcg_temp_new_i64();
1835    t0 = tcg_temp_new_i64();
1836    t1 = tcg_temp_new_i64();
1837
1838    get_avr64(hi, a->vrb, true);
1839    get_avr64(lo, a->vrb, false);
1840
1841    /* Align the lower doubleword so we can use the same mask */
1842    tcg_gen_shli_i64(lo, lo, a->n * nbits - 64);
1843
1844    /*
1845     * Starting from the most significant bit, gather every Nth bit with a
1846     * sequence of mask-shift-or operation. E.g.: for N=3
1847     * AxxBxxCxxDxxExxFxxGxxHxxIxxJxxKxxLxxMxxNxxOxxPxxQxxRxxSxxTxxUxxV
1848     *     & rep(0b100)
1849     * A..B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V
1850     *     << 2
1851     * .B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V..
1852     *     |
1853     * AB.BC.CD.DE.EF.FG.GH.HI.IJ.JK.KL.LM.MN.NO.OP.PQ.QR.RS.ST.TU.UV.V
1854     *  & rep(0b110000)
1855     * AB....CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV..
1856     *     << 4
1857     * ..CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV......
1858     *     |
1859     * ABCD..CDEF..EFGH..GHIJ..IJKL..KLMN..MNOP..OPQR..QRST..STUV..UV..
1860     *     & rep(0b111100000000)
1861     * ABCD........EFGH........IJKL........MNOP........QRST........UV..
1862     *     << 8
1863     * ....EFGH........IJKL........MNOP........QRST........UV..........
1864     *     |
1865     * ABCDEFGH....EFGHIJKL....IJKLMNOP....MNOPQRST....QRSTUV......UV..
1866     *  & rep(0b111111110000000000000000)
1867     * ABCDEFGH................IJKLMNOP................QRSTUV..........
1868     *     << 16
1869     * ........IJKLMNOP................QRSTUV..........................
1870     *     |
1871     * ABCDEFGHIJKLMNOP........IJKLMNOPQRSTUV..........QRSTUV..........
1872     *     & rep(0b111111111111111100000000000000000000000000000000)
1873     * ABCDEFGHIJKLMNOP................................QRSTUV..........
1874     *     << 32
1875     * ................QRSTUV..........................................
1876     *     |
1877     * ABCDEFGHIJKLMNOPQRSTUV..........................QRSTUV..........
1878     */
1879    for (i = 0, sh = a->n - 1; i < 5; i++, sh <<= 1) {
1880        m = mask[a->n - 2][i];
1881        if (m) {
1882            tcg_gen_andi_i64(hi, hi, m);
1883            tcg_gen_andi_i64(lo, lo, m);
1884        }
1885        if (sh < 64) {
1886            tcg_gen_shli_i64(t0, hi, sh);
1887            tcg_gen_shli_i64(t1, lo, sh);
1888            tcg_gen_or_i64(hi, t0, hi);
1889            tcg_gen_or_i64(lo, t1, lo);
1890        }
1891    }
1892
1893    tcg_gen_andi_i64(hi, hi, ~(~0ULL >> nbits));
1894    tcg_gen_andi_i64(lo, lo, ~(~0ULL >> nbits));
1895    tcg_gen_shri_i64(lo, lo, nbits);
1896    tcg_gen_or_i64(hi, hi, lo);
1897    tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], hi);
1898
1899    tcg_temp_free_i64(hi);
1900    tcg_temp_free_i64(lo);
1901    tcg_temp_free_i64(t0);
1902    tcg_temp_free_i64(t1);
1903
1904    return true;
1905}
1906
1907static bool do_vextdx(DisasContext *ctx, arg_VA *a, int size, bool right,
1908               void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv))
1909{
1910    TCGv_ptr vrt, vra, vrb;
1911    TCGv rc;
1912
1913    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1914    REQUIRE_VECTOR(ctx);
1915
1916    vrt = gen_avr_ptr(a->vrt);
1917    vra = gen_avr_ptr(a->vra);
1918    vrb = gen_avr_ptr(a->vrb);
1919    rc = tcg_temp_new();
1920
1921    tcg_gen_andi_tl(rc, cpu_gpr[a->rc], 0x1F);
1922    if (right) {
1923        tcg_gen_subfi_tl(rc, 32 - size, rc);
1924    }
1925    gen_helper(cpu_env, vrt, vra, vrb, rc);
1926
1927    tcg_temp_free_ptr(vrt);
1928    tcg_temp_free_ptr(vra);
1929    tcg_temp_free_ptr(vrb);
1930    tcg_temp_free(rc);
1931    return true;
1932}
1933
1934TRANS(VEXTDUBVLX, do_vextdx, 1, false, gen_helper_VEXTDUBVLX)
1935TRANS(VEXTDUHVLX, do_vextdx, 2, false, gen_helper_VEXTDUHVLX)
1936TRANS(VEXTDUWVLX, do_vextdx, 4, false, gen_helper_VEXTDUWVLX)
1937TRANS(VEXTDDVLX, do_vextdx, 8, false, gen_helper_VEXTDDVLX)
1938
1939TRANS(VEXTDUBVRX, do_vextdx, 1, true, gen_helper_VEXTDUBVLX)
1940TRANS(VEXTDUHVRX, do_vextdx, 2, true, gen_helper_VEXTDUHVLX)
1941TRANS(VEXTDUWVRX, do_vextdx, 4, true, gen_helper_VEXTDUWVLX)
1942TRANS(VEXTDDVRX, do_vextdx, 8, true, gen_helper_VEXTDDVLX)
1943
1944static bool do_vinsx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
1945            TCGv_i64 rb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
1946{
1947    TCGv_ptr t;
1948    TCGv idx;
1949
1950    t = gen_avr_ptr(vrt);
1951    idx = tcg_temp_new();
1952
1953    tcg_gen_andi_tl(idx, ra, 0xF);
1954    if (right) {
1955        tcg_gen_subfi_tl(idx, 16 - size, idx);
1956    }
1957
1958    gen_helper(cpu_env, t, rb, idx);
1959
1960    tcg_temp_free_ptr(t);
1961    tcg_temp_free(idx);
1962
1963    return true;
1964}
1965
1966static bool do_vinsvx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
1967                int vrb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
1968{
1969    bool ok;
1970    TCGv_i64 val;
1971
1972    val = tcg_temp_new_i64();
1973    get_avr64(val, vrb, true);
1974    ok = do_vinsx(ctx, vrt, size, right, ra, val, gen_helper);
1975
1976    tcg_temp_free_i64(val);
1977    return ok;
1978}
1979
1980static bool do_vinsx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
1981                        void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
1982{
1983    bool ok;
1984    TCGv_i64 val;
1985
1986    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1987    REQUIRE_VECTOR(ctx);
1988
1989    val = tcg_temp_new_i64();
1990    tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
1991
1992    ok = do_vinsx(ctx, a->vrt, size, right, cpu_gpr[a->vra], val, gen_helper);
1993
1994    tcg_temp_free_i64(val);
1995    return ok;
1996}
1997
1998static bool do_vinsvx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
1999                        void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
2000{
2001    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2002    REQUIRE_VECTOR(ctx);
2003
2004    return do_vinsvx(ctx, a->vrt, size, right, cpu_gpr[a->vra], a->vrb,
2005                     gen_helper);
2006}
2007
2008static bool do_vins_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
2009                        void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
2010{
2011    bool ok;
2012    TCGv_i64 val;
2013
2014    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2015    REQUIRE_VECTOR(ctx);
2016
2017    if (a->uim > (16 - size)) {
2018        /*
2019         * PowerISA v3.1 says that the resulting value is undefined in this
2020         * case, so just log a guest error and leave VRT unchanged. The
2021         * real hardware would do a partial insert, e.g. if VRT is zeroed and
2022         * RB is 0x12345678, executing "vinsw VRT,RB,14" results in
2023         * VRT = 0x0000...00001234, but we don't bother to reproduce this
2024         * behavior as software shouldn't rely on it.
2025         */
2026        qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINS* at"
2027            " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
2028            16 - size);
2029        return true;
2030    }
2031
2032    val = tcg_temp_new_i64();
2033    tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
2034
2035    ok = do_vinsx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), val,
2036                  gen_helper);
2037
2038    tcg_temp_free_i64(val);
2039    return ok;
2040}
2041
2042static bool do_vinsert_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
2043                        void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
2044{
2045    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2046    REQUIRE_VECTOR(ctx);
2047
2048    if (a->uim > (16 - size)) {
2049        qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINSERT* at"
2050            " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
2051            16 - size);
2052        return true;
2053    }
2054
2055    return do_vinsvx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), a->vrb,
2056                     gen_helper);
2057}
2058
2059TRANS(VINSBLX, do_vinsx_VX, 1, false, gen_helper_VINSBLX)
2060TRANS(VINSHLX, do_vinsx_VX, 2, false, gen_helper_VINSHLX)
2061TRANS(VINSWLX, do_vinsx_VX, 4, false, gen_helper_VINSWLX)
2062TRANS(VINSDLX, do_vinsx_VX, 8, false, gen_helper_VINSDLX)
2063
2064TRANS(VINSBRX, do_vinsx_VX, 1, true, gen_helper_VINSBLX)
2065TRANS(VINSHRX, do_vinsx_VX, 2, true, gen_helper_VINSHLX)
2066TRANS(VINSWRX, do_vinsx_VX, 4, true, gen_helper_VINSWLX)
2067TRANS(VINSDRX, do_vinsx_VX, 8, true, gen_helper_VINSDLX)
2068
2069TRANS(VINSW, do_vins_VX_uim4, 4, gen_helper_VINSWLX)
2070TRANS(VINSD, do_vins_VX_uim4, 8, gen_helper_VINSDLX)
2071
2072TRANS(VINSBVLX, do_vinsvx_VX, 1, false, gen_helper_VINSBLX)
2073TRANS(VINSHVLX, do_vinsvx_VX, 2, false, gen_helper_VINSHLX)
2074TRANS(VINSWVLX, do_vinsvx_VX, 4, false, gen_helper_VINSWLX)
2075
2076TRANS(VINSBVRX, do_vinsvx_VX, 1, true, gen_helper_VINSBLX)
2077TRANS(VINSHVRX, do_vinsvx_VX, 2, true, gen_helper_VINSHLX)
2078TRANS(VINSWVRX, do_vinsvx_VX, 4, true, gen_helper_VINSWLX)
2079
2080TRANS(VINSERTB, do_vinsert_VX_uim4, 1, gen_helper_VINSBLX)
2081TRANS(VINSERTH, do_vinsert_VX_uim4, 2, gen_helper_VINSHLX)
2082TRANS(VINSERTW, do_vinsert_VX_uim4, 4, gen_helper_VINSWLX)
2083TRANS(VINSERTD, do_vinsert_VX_uim4, 8, gen_helper_VINSDLX)
2084
2085static void gen_vsldoi(DisasContext *ctx)
2086{
2087    TCGv_ptr ra, rb, rd;
2088    TCGv_i32 sh;
2089    if (unlikely(!ctx->altivec_enabled)) {
2090        gen_exception(ctx, POWERPC_EXCP_VPU);
2091        return;
2092    }
2093    ra = gen_avr_ptr(rA(ctx->opcode));
2094    rb = gen_avr_ptr(rB(ctx->opcode));
2095    rd = gen_avr_ptr(rD(ctx->opcode));
2096    sh = tcg_const_i32(VSH(ctx->opcode));
2097    gen_helper_vsldoi(rd, ra, rb, sh);
2098    tcg_temp_free_ptr(ra);
2099    tcg_temp_free_ptr(rb);
2100    tcg_temp_free_ptr(rd);
2101    tcg_temp_free_i32(sh);
2102}
2103
2104static bool trans_VSLDBI(DisasContext *ctx, arg_VN *a)
2105{
2106    TCGv_i64 t0, t1, t2;
2107
2108    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2109    REQUIRE_VECTOR(ctx);
2110
2111    t0 = tcg_temp_new_i64();
2112    t1 = tcg_temp_new_i64();
2113
2114    get_avr64(t0, a->vra, true);
2115    get_avr64(t1, a->vra, false);
2116
2117    if (a->sh != 0) {
2118        t2 = tcg_temp_new_i64();
2119
2120        get_avr64(t2, a->vrb, true);
2121
2122        tcg_gen_extract2_i64(t0, t1, t0, 64 - a->sh);
2123        tcg_gen_extract2_i64(t1, t2, t1, 64 - a->sh);
2124
2125        tcg_temp_free_i64(t2);
2126    }
2127
2128    set_avr64(a->vrt, t0, true);
2129    set_avr64(a->vrt, t1, false);
2130
2131    tcg_temp_free_i64(t0);
2132    tcg_temp_free_i64(t1);
2133
2134    return true;
2135}
2136
2137static bool trans_VSRDBI(DisasContext *ctx, arg_VN *a)
2138{
2139    TCGv_i64 t2, t1, t0;
2140
2141    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2142    REQUIRE_VECTOR(ctx);
2143
2144    t0 = tcg_temp_new_i64();
2145    t1 = tcg_temp_new_i64();
2146
2147    get_avr64(t0, a->vrb, false);
2148    get_avr64(t1, a->vrb, true);
2149
2150    if (a->sh != 0) {
2151        t2 = tcg_temp_new_i64();
2152
2153        get_avr64(t2, a->vra, false);
2154
2155        tcg_gen_extract2_i64(t0, t0, t1, a->sh);
2156        tcg_gen_extract2_i64(t1, t1, t2, a->sh);
2157
2158        tcg_temp_free_i64(t2);
2159    }
2160
2161    set_avr64(a->vrt, t0, false);
2162    set_avr64(a->vrt, t1, true);
2163
2164    tcg_temp_free_i64(t0);
2165    tcg_temp_free_i64(t1);
2166
2167    return true;
2168}
2169
2170static bool do_vexpand(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
2171{
2172    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2173    REQUIRE_VECTOR(ctx);
2174
2175    tcg_gen_gvec_sari(vece, avr_full_offset(a->vrt), avr_full_offset(a->vrb),
2176                      (8 << vece) - 1, 16, 16);
2177
2178    return true;
2179}
2180
2181TRANS(VEXPANDBM, do_vexpand, MO_8)
2182TRANS(VEXPANDHM, do_vexpand, MO_16)
2183TRANS(VEXPANDWM, do_vexpand, MO_32)
2184TRANS(VEXPANDDM, do_vexpand, MO_64)
2185
2186static bool trans_VEXPANDQM(DisasContext *ctx, arg_VX_tb *a)
2187{
2188    TCGv_i64 tmp;
2189
2190    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2191    REQUIRE_VECTOR(ctx);
2192
2193    tmp = tcg_temp_new_i64();
2194
2195    get_avr64(tmp, a->vrb, true);
2196    tcg_gen_sari_i64(tmp, tmp, 63);
2197    set_avr64(a->vrt, tmp, false);
2198    set_avr64(a->vrt, tmp, true);
2199
2200    tcg_temp_free_i64(tmp);
2201    return true;
2202}
2203
2204static bool do_vextractm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
2205{
2206    const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece,
2207                   mask = dup_const(vece, 1 << (elem_width - 1));
2208    uint64_t i, j;
2209    TCGv_i64 lo, hi, t0, t1;
2210
2211    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2212    REQUIRE_VECTOR(ctx);
2213
2214    hi = tcg_temp_new_i64();
2215    lo = tcg_temp_new_i64();
2216    t0 = tcg_temp_new_i64();
2217    t1 = tcg_temp_new_i64();
2218
2219    get_avr64(lo, a->vrb, false);
2220    get_avr64(hi, a->vrb, true);
2221
2222    tcg_gen_andi_i64(lo, lo, mask);
2223    tcg_gen_andi_i64(hi, hi, mask);
2224
2225    /*
2226     * Gather the most significant bit of each element in the highest element
2227     * element. E.g. for bytes:
2228     * aXXXXXXXbXXXXXXXcXXXXXXXdXXXXXXXeXXXXXXXfXXXXXXXgXXXXXXXhXXXXXXX
2229     *     & dup(1 << (elem_width - 1))
2230     * a0000000b0000000c0000000d0000000e0000000f0000000g0000000h0000000
2231     *     << 32 - 4
2232     * 0000e0000000f0000000g0000000h00000000000000000000000000000000000
2233     *     |
2234     * a000e000b000f000c000g000d000h000e0000000f0000000g0000000h0000000
2235     *     << 16 - 2
2236     * 00c000g000d000h000e0000000f0000000g0000000h000000000000000000000
2237     *     |
2238     * a0c0e0g0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h0000000
2239     *     << 8 - 1
2240     * 0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h00000000000000
2241     *     |
2242     * abcdefghbcdefgh0cdefgh00defgh000efgh0000fgh00000gh000000h0000000
2243     */
2244    for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
2245        tcg_gen_shli_i64(t0, hi, j - i);
2246        tcg_gen_shli_i64(t1, lo, j - i);
2247        tcg_gen_or_i64(hi, hi, t0);
2248        tcg_gen_or_i64(lo, lo, t1);
2249    }
2250
2251    tcg_gen_shri_i64(hi, hi, 64 - elem_count_half);
2252    tcg_gen_extract2_i64(lo, lo, hi, 64 - elem_count_half);
2253    tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], lo);
2254
2255    tcg_temp_free_i64(hi);
2256    tcg_temp_free_i64(lo);
2257    tcg_temp_free_i64(t0);
2258    tcg_temp_free_i64(t1);
2259
2260    return true;
2261}
2262
2263TRANS(VEXTRACTBM, do_vextractm, MO_8)
2264TRANS(VEXTRACTHM, do_vextractm, MO_16)
2265TRANS(VEXTRACTWM, do_vextractm, MO_32)
2266TRANS(VEXTRACTDM, do_vextractm, MO_64)
2267
2268static bool trans_VEXTRACTQM(DisasContext *ctx, arg_VX_tb *a)
2269{
2270    TCGv_i64 tmp;
2271
2272    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2273    REQUIRE_VECTOR(ctx);
2274
2275    tmp = tcg_temp_new_i64();
2276
2277    get_avr64(tmp, a->vrb, true);
2278    tcg_gen_shri_i64(tmp, tmp, 63);
2279    tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], tmp);
2280
2281    tcg_temp_free_i64(tmp);
2282
2283    return true;
2284}
2285
2286static bool do_mtvsrm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
2287{
2288    const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece;
2289    uint64_t c;
2290    int i, j;
2291    TCGv_i64 hi, lo, t0, t1;
2292
2293    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2294    REQUIRE_VECTOR(ctx);
2295
2296    hi = tcg_temp_new_i64();
2297    lo = tcg_temp_new_i64();
2298    t0 = tcg_temp_new_i64();
2299    t1 = tcg_temp_new_i64();
2300
2301    tcg_gen_extu_tl_i64(t0, cpu_gpr[a->vrb]);
2302    tcg_gen_extract_i64(hi, t0, elem_count_half, elem_count_half);
2303    tcg_gen_extract_i64(lo, t0, 0, elem_count_half);
2304
2305    /*
2306     * Spread the bits into their respective elements.
2307     * E.g. for bytes:
2308     * 00000000000000000000000000000000000000000000000000000000abcdefgh
2309     *   << 32 - 4
2310     * 0000000000000000000000000000abcdefgh0000000000000000000000000000
2311     *   |
2312     * 0000000000000000000000000000abcdefgh00000000000000000000abcdefgh
2313     *   << 16 - 2
2314     * 00000000000000abcdefgh00000000000000000000abcdefgh00000000000000
2315     *   |
2316     * 00000000000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh
2317     *   << 8 - 1
2318     * 0000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh0000000
2319     *   |
2320     * 0000000abcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgh
2321     *   & dup(1)
2322     * 0000000a0000000b0000000c0000000d0000000e0000000f0000000g0000000h
2323     *   * 0xff
2324     * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
2325     */
2326    for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
2327        tcg_gen_shli_i64(t0, hi, j - i);
2328        tcg_gen_shli_i64(t1, lo, j - i);
2329        tcg_gen_or_i64(hi, hi, t0);
2330        tcg_gen_or_i64(lo, lo, t1);
2331    }
2332
2333    c = dup_const(vece, 1);
2334    tcg_gen_andi_i64(hi, hi, c);
2335    tcg_gen_andi_i64(lo, lo, c);
2336
2337    c = MAKE_64BIT_MASK(0, elem_width);
2338    tcg_gen_muli_i64(hi, hi, c);
2339    tcg_gen_muli_i64(lo, lo, c);
2340
2341    set_avr64(a->vrt, lo, false);
2342    set_avr64(a->vrt, hi, true);
2343
2344    tcg_temp_free_i64(hi);
2345    tcg_temp_free_i64(lo);
2346    tcg_temp_free_i64(t0);
2347    tcg_temp_free_i64(t1);
2348
2349    return true;
2350}
2351
2352TRANS(MTVSRBM, do_mtvsrm, MO_8)
2353TRANS(MTVSRHM, do_mtvsrm, MO_16)
2354TRANS(MTVSRWM, do_mtvsrm, MO_32)
2355TRANS(MTVSRDM, do_mtvsrm, MO_64)
2356
2357static bool trans_MTVSRQM(DisasContext *ctx, arg_VX_tb *a)
2358{
2359    TCGv_i64 tmp;
2360
2361    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2362    REQUIRE_VECTOR(ctx);
2363
2364    tmp = tcg_temp_new_i64();
2365
2366    tcg_gen_ext_tl_i64(tmp, cpu_gpr[a->vrb]);
2367    tcg_gen_sextract_i64(tmp, tmp, 0, 1);
2368    set_avr64(a->vrt, tmp, false);
2369    set_avr64(a->vrt, tmp, true);
2370
2371    tcg_temp_free_i64(tmp);
2372
2373    return true;
2374}
2375
2376static bool trans_MTVSRBMI(DisasContext *ctx, arg_DX_b *a)
2377{
2378    const uint64_t mask = dup_const(MO_8, 1);
2379    uint64_t hi, lo;
2380
2381    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2382    REQUIRE_VECTOR(ctx);
2383
2384    hi = extract16(a->b, 8, 8);
2385    lo = extract16(a->b, 0, 8);
2386
2387    for (int i = 4, j = 32; i > 0; i >>= 1, j >>= 1) {
2388        hi |= hi << (j - i);
2389        lo |= lo << (j - i);
2390    }
2391
2392    hi = (hi & mask) * 0xFF;
2393    lo = (lo & mask) * 0xFF;
2394
2395    set_avr64(a->vrt, tcg_constant_i64(hi), true);
2396    set_avr64(a->vrt, tcg_constant_i64(lo), false);
2397
2398    return true;
2399}
2400
2401static bool do_vcntmb(DisasContext *ctx, arg_VX_mp *a, int vece)
2402{
2403    TCGv_i64 rt, vrb, mask;
2404    rt = tcg_const_i64(0);
2405    vrb = tcg_temp_new_i64();
2406    mask = tcg_constant_i64(dup_const(vece, 1ULL << ((8 << vece) - 1)));
2407
2408    for (int i = 0; i < 2; i++) {
2409        get_avr64(vrb, a->vrb, i);
2410        if (a->mp) {
2411            tcg_gen_and_i64(vrb, mask, vrb);
2412        } else {
2413            tcg_gen_andc_i64(vrb, mask, vrb);
2414        }
2415        tcg_gen_ctpop_i64(vrb, vrb);
2416        tcg_gen_add_i64(rt, rt, vrb);
2417    }
2418
2419    tcg_gen_shli_i64(rt, rt, TARGET_LONG_BITS - 8 + vece);
2420    tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], rt);
2421
2422    tcg_temp_free_i64(vrb);
2423    tcg_temp_free_i64(rt);
2424
2425    return true;
2426}
2427
2428TRANS(VCNTMBB, do_vcntmb, MO_8)
2429TRANS(VCNTMBH, do_vcntmb, MO_16)
2430TRANS(VCNTMBW, do_vcntmb, MO_32)
2431TRANS(VCNTMBD, do_vcntmb, MO_64)
2432
2433static bool do_vstri(DisasContext *ctx, arg_VX_tb_rc *a,
2434                     void (*gen_helper)(TCGv_i32, TCGv_ptr, TCGv_ptr))
2435{
2436    TCGv_ptr vrt, vrb;
2437
2438    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2439    REQUIRE_VECTOR(ctx);
2440
2441    vrt = gen_avr_ptr(a->vrt);
2442    vrb = gen_avr_ptr(a->vrb);
2443
2444    if (a->rc) {
2445        gen_helper(cpu_crf[6], vrt, vrb);
2446    } else {
2447        TCGv_i32 discard = tcg_temp_new_i32();
2448        gen_helper(discard, vrt, vrb);
2449        tcg_temp_free_i32(discard);
2450    }
2451
2452    tcg_temp_free_ptr(vrt);
2453    tcg_temp_free_ptr(vrb);
2454
2455    return true;
2456}
2457
2458TRANS(VSTRIBL, do_vstri, gen_helper_VSTRIBL)
2459TRANS(VSTRIBR, do_vstri, gen_helper_VSTRIBR)
2460TRANS(VSTRIHL, do_vstri, gen_helper_VSTRIHL)
2461TRANS(VSTRIHR, do_vstri, gen_helper_VSTRIHR)
2462
2463static bool do_vclrb(DisasContext *ctx, arg_VX *a, bool right)
2464{
2465    TCGv_i64 rb, mh, ml, tmp,
2466             ones = tcg_constant_i64(-1),
2467             zero = tcg_constant_i64(0);
2468
2469    rb = tcg_temp_new_i64();
2470    mh = tcg_temp_new_i64();
2471    ml = tcg_temp_new_i64();
2472    tmp = tcg_temp_new_i64();
2473
2474    tcg_gen_extu_tl_i64(rb, cpu_gpr[a->vrb]);
2475    tcg_gen_andi_i64(tmp, rb, 7);
2476    tcg_gen_shli_i64(tmp, tmp, 3);
2477    if (right) {
2478        tcg_gen_shr_i64(tmp, ones, tmp);
2479    } else {
2480        tcg_gen_shl_i64(tmp, ones, tmp);
2481    }
2482    tcg_gen_not_i64(tmp, tmp);
2483
2484    if (right) {
2485        tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
2486                            tmp, ones);
2487        tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
2488                            zero, tmp);
2489        tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(16),
2490                            ml, ones);
2491    } else {
2492        tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
2493                            tmp, ones);
2494        tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
2495                            zero, tmp);
2496        tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(16),
2497                            mh, ones);
2498    }
2499
2500    get_avr64(tmp, a->vra, true);
2501    tcg_gen_and_i64(tmp, tmp, mh);
2502    set_avr64(a->vrt, tmp, true);
2503
2504    get_avr64(tmp, a->vra, false);
2505    tcg_gen_and_i64(tmp, tmp, ml);
2506    set_avr64(a->vrt, tmp, false);
2507
2508    tcg_temp_free_i64(rb);
2509    tcg_temp_free_i64(mh);
2510    tcg_temp_free_i64(ml);
2511    tcg_temp_free_i64(tmp);
2512
2513    return true;
2514}
2515
2516TRANS(VCLRLB, do_vclrb, false)
2517TRANS(VCLRRB, do_vclrb, true)
2518
2519#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
2520static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
2521    {                                                                   \
2522        TCGv_ptr ra, rb, rc, rd;                                        \
2523        if (unlikely(!ctx->altivec_enabled)) {                          \
2524            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
2525            return;                                                     \
2526        }                                                               \
2527        ra = gen_avr_ptr(rA(ctx->opcode));                              \
2528        rb = gen_avr_ptr(rB(ctx->opcode));                              \
2529        rc = gen_avr_ptr(rC(ctx->opcode));                              \
2530        rd = gen_avr_ptr(rD(ctx->opcode));                              \
2531        if (Rc(ctx->opcode)) {                                          \
2532            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
2533        } else {                                                        \
2534            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
2535        }                                                               \
2536        tcg_temp_free_ptr(ra);                                          \
2537        tcg_temp_free_ptr(rb);                                          \
2538        tcg_temp_free_ptr(rc);                                          \
2539        tcg_temp_free_ptr(rd);                                          \
2540    }
2541
2542GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
2543
2544static void gen_vmladduhm(DisasContext *ctx)
2545{
2546    TCGv_ptr ra, rb, rc, rd;
2547    if (unlikely(!ctx->altivec_enabled)) {
2548        gen_exception(ctx, POWERPC_EXCP_VPU);
2549        return;
2550    }
2551    ra = gen_avr_ptr(rA(ctx->opcode));
2552    rb = gen_avr_ptr(rB(ctx->opcode));
2553    rc = gen_avr_ptr(rC(ctx->opcode));
2554    rd = gen_avr_ptr(rD(ctx->opcode));
2555    gen_helper_vmladduhm(rd, ra, rb, rc);
2556    tcg_temp_free_ptr(ra);
2557    tcg_temp_free_ptr(rb);
2558    tcg_temp_free_ptr(rc);
2559    tcg_temp_free_ptr(rd);
2560}
2561
2562static bool trans_VPERM(DisasContext *ctx, arg_VA *a)
2563{
2564    TCGv_ptr vrt, vra, vrb, vrc;
2565
2566    REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
2567    REQUIRE_VECTOR(ctx);
2568
2569    vrt = gen_avr_ptr(a->vrt);
2570    vra = gen_avr_ptr(a->vra);
2571    vrb = gen_avr_ptr(a->vrb);
2572    vrc = gen_avr_ptr(a->rc);
2573
2574    gen_helper_VPERM(vrt, vra, vrb, vrc);
2575
2576    tcg_temp_free_ptr(vrt);
2577    tcg_temp_free_ptr(vra);
2578    tcg_temp_free_ptr(vrb);
2579    tcg_temp_free_ptr(vrc);
2580
2581    return true;
2582}
2583
2584static bool trans_VPERMR(DisasContext *ctx, arg_VA *a)
2585{
2586    TCGv_ptr vrt, vra, vrb, vrc;
2587
2588    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2589    REQUIRE_VECTOR(ctx);
2590
2591    vrt = gen_avr_ptr(a->vrt);
2592    vra = gen_avr_ptr(a->vra);
2593    vrb = gen_avr_ptr(a->vrb);
2594    vrc = gen_avr_ptr(a->rc);
2595
2596    gen_helper_VPERMR(vrt, vra, vrb, vrc);
2597
2598    tcg_temp_free_ptr(vrt);
2599    tcg_temp_free_ptr(vra);
2600    tcg_temp_free_ptr(vrb);
2601    tcg_temp_free_ptr(vrc);
2602
2603    return true;
2604}
2605
2606static bool trans_VSEL(DisasContext *ctx, arg_VA *a)
2607{
2608    REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
2609    REQUIRE_VECTOR(ctx);
2610
2611    tcg_gen_gvec_bitsel(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->rc),
2612                        avr_full_offset(a->vrb), avr_full_offset(a->vra),
2613                        16, 16);
2614
2615    return true;
2616}
2617
2618GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
2619GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
2620GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
2621GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
2622
2623GEN_VXFORM_NOA(vclzb, 1, 28)
2624GEN_VXFORM_NOA(vclzh, 1, 29)
2625GEN_VXFORM_TRANS(vclzw, 1, 30)
2626GEN_VXFORM_TRANS(vclzd, 1, 31)
2627GEN_VXFORM_NOA_2(vnegw, 1, 24, 6)
2628GEN_VXFORM_NOA_2(vnegd, 1, 24, 7)
2629
2630static void gen_vexts_i64(TCGv_i64 t, TCGv_i64 b, int64_t s)
2631{
2632    tcg_gen_sextract_i64(t, b, 0, 64 - s);
2633}
2634
2635static void gen_vexts_i32(TCGv_i32 t, TCGv_i32 b, int32_t s)
2636{
2637    tcg_gen_sextract_i32(t, b, 0, 32 - s);
2638}
2639
2640static void gen_vexts_vec(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t s)
2641{
2642    tcg_gen_shli_vec(vece, t, b, s);
2643    tcg_gen_sari_vec(vece, t, t, s);
2644}
2645
2646static bool do_vexts(DisasContext *ctx, arg_VX_tb *a, unsigned vece, int64_t s)
2647{
2648    static const TCGOpcode vecop_list[] = {
2649        INDEX_op_shli_vec, INDEX_op_sari_vec, 0
2650    };
2651
2652    static const GVecGen2i op[2] = {
2653        {
2654            .fni4 = gen_vexts_i32,
2655            .fniv = gen_vexts_vec,
2656            .opt_opc = vecop_list,
2657            .vece = MO_32
2658        },
2659        {
2660            .fni8 = gen_vexts_i64,
2661            .fniv = gen_vexts_vec,
2662            .opt_opc = vecop_list,
2663            .vece = MO_64
2664        },
2665    };
2666
2667    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2668    REQUIRE_VECTOR(ctx);
2669
2670    tcg_gen_gvec_2i(avr_full_offset(a->vrt), avr_full_offset(a->vrb),
2671                    16, 16, s, &op[vece - MO_32]);
2672
2673    return true;
2674}
2675
2676TRANS(VEXTSB2W, do_vexts, MO_32, 24);
2677TRANS(VEXTSH2W, do_vexts, MO_32, 16);
2678TRANS(VEXTSB2D, do_vexts, MO_64, 56);
2679TRANS(VEXTSH2D, do_vexts, MO_64, 48);
2680TRANS(VEXTSW2D, do_vexts, MO_64, 32);
2681
2682static bool trans_VEXTSD2Q(DisasContext *ctx, arg_VX_tb *a)
2683{
2684    TCGv_i64 tmp;
2685
2686    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2687    REQUIRE_VECTOR(ctx);
2688
2689    tmp = tcg_temp_new_i64();
2690
2691    get_avr64(tmp, a->vrb, false);
2692    set_avr64(a->vrt, tmp, false);
2693    tcg_gen_sari_i64(tmp, tmp, 63);
2694    set_avr64(a->vrt, tmp, true);
2695
2696    tcg_temp_free_i64(tmp);
2697    return true;
2698}
2699
2700GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
2701GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
2702GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
2703GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
2704GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
2705GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
2706GEN_VXFORM_NOA(vpopcntb, 1, 28)
2707GEN_VXFORM_NOA(vpopcnth, 1, 29)
2708GEN_VXFORM_NOA(vpopcntw, 1, 30)
2709GEN_VXFORM_NOA(vpopcntd, 1, 31)
2710GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
2711                vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
2712GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
2713                vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
2714GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
2715                vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
2716GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
2717                vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
2718GEN_VXFORM(vbpermd, 6, 23);
2719GEN_VXFORM(vbpermq, 6, 21);
2720GEN_VXFORM_TRANS(vgbbd, 6, 20);
2721GEN_VXFORM(vpmsumb, 4, 16)
2722GEN_VXFORM(vpmsumh, 4, 17)
2723GEN_VXFORM(vpmsumw, 4, 18)
2724GEN_VXFORM(vpmsumd, 4, 19)
2725
2726#define GEN_BCD(op)                                 \
2727static void gen_##op(DisasContext *ctx)             \
2728{                                                   \
2729    TCGv_ptr ra, rb, rd;                            \
2730    TCGv_i32 ps;                                    \
2731                                                    \
2732    if (unlikely(!ctx->altivec_enabled)) {          \
2733        gen_exception(ctx, POWERPC_EXCP_VPU);       \
2734        return;                                     \
2735    }                                               \
2736                                                    \
2737    ra = gen_avr_ptr(rA(ctx->opcode));              \
2738    rb = gen_avr_ptr(rB(ctx->opcode));              \
2739    rd = gen_avr_ptr(rD(ctx->opcode));              \
2740                                                    \
2741    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
2742                                                    \
2743    gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
2744                                                    \
2745    tcg_temp_free_ptr(ra);                          \
2746    tcg_temp_free_ptr(rb);                          \
2747    tcg_temp_free_ptr(rd);                          \
2748    tcg_temp_free_i32(ps);                          \
2749}
2750
2751#define GEN_BCD2(op)                                \
2752static void gen_##op(DisasContext *ctx)             \
2753{                                                   \
2754    TCGv_ptr rd, rb;                                \
2755    TCGv_i32 ps;                                    \
2756                                                    \
2757    if (unlikely(!ctx->altivec_enabled)) {          \
2758        gen_exception(ctx, POWERPC_EXCP_VPU);       \
2759        return;                                     \
2760    }                                               \
2761                                                    \
2762    rb = gen_avr_ptr(rB(ctx->opcode));              \
2763    rd = gen_avr_ptr(rD(ctx->opcode));              \
2764                                                    \
2765    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
2766                                                    \
2767    gen_helper_##op(cpu_crf[6], rd, rb, ps);        \
2768                                                    \
2769    tcg_temp_free_ptr(rb);                          \
2770    tcg_temp_free_ptr(rd);                          \
2771    tcg_temp_free_i32(ps);                          \
2772}
2773
2774GEN_BCD(bcdadd)
2775GEN_BCD(bcdsub)
2776GEN_BCD2(bcdcfn)
2777GEN_BCD2(bcdctn)
2778GEN_BCD2(bcdcfz)
2779GEN_BCD2(bcdctz)
2780GEN_BCD2(bcdcfsq)
2781GEN_BCD2(bcdctsq)
2782GEN_BCD2(bcdsetsgn)
2783GEN_BCD(bcdcpsgn);
2784GEN_BCD(bcds);
2785GEN_BCD(bcdus);
2786GEN_BCD(bcdsr);
2787GEN_BCD(bcdtrunc);
2788GEN_BCD(bcdutrunc);
2789
2790static void gen_xpnd04_1(DisasContext *ctx)
2791{
2792    switch (opc4(ctx->opcode)) {
2793    case 0:
2794        gen_bcdctsq(ctx);
2795        break;
2796    case 2:
2797        gen_bcdcfsq(ctx);
2798        break;
2799    case 4:
2800        gen_bcdctz(ctx);
2801        break;
2802    case 5:
2803        gen_bcdctn(ctx);
2804        break;
2805    case 6:
2806        gen_bcdcfz(ctx);
2807        break;
2808    case 7:
2809        gen_bcdcfn(ctx);
2810        break;
2811    case 31:
2812        gen_bcdsetsgn(ctx);
2813        break;
2814    default:
2815        gen_invalid(ctx);
2816        break;
2817    }
2818}
2819
2820static void gen_xpnd04_2(DisasContext *ctx)
2821{
2822    switch (opc4(ctx->opcode)) {
2823    case 0:
2824        gen_bcdctsq(ctx);
2825        break;
2826    case 2:
2827        gen_bcdcfsq(ctx);
2828        break;
2829    case 4:
2830        gen_bcdctz(ctx);
2831        break;
2832    case 6:
2833        gen_bcdcfz(ctx);
2834        break;
2835    case 7:
2836        gen_bcdcfn(ctx);
2837        break;
2838    case 31:
2839        gen_bcdsetsgn(ctx);
2840        break;
2841    default:
2842        gen_invalid(ctx);
2843        break;
2844    }
2845}
2846
2847
2848GEN_VXFORM_DUAL(vsubcuw, PPC_ALTIVEC, PPC_NONE, \
2849                xpnd04_1, PPC_NONE, PPC2_ISA300)
2850GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \
2851                xpnd04_2, PPC_NONE, PPC2_ISA300)
2852
2853GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
2854                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
2855GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
2856                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
2857GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
2858                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
2859GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
2860                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
2861GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \
2862                bcdcpsgn, PPC_NONE, PPC2_ISA300)
2863GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
2864                bcds, PPC_NONE, PPC2_ISA300)
2865GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
2866                bcdus, PPC_NONE, PPC2_ISA300)
2867GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
2868                bcdtrunc, PPC_NONE, PPC2_ISA300)
2869GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
2870                bcdtrunc, PPC_NONE, PPC2_ISA300)
2871GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
2872                bcdutrunc, PPC_NONE, PPC2_ISA300)
2873
2874
2875static void gen_vsbox(DisasContext *ctx)
2876{
2877    TCGv_ptr ra, rd;
2878    if (unlikely(!ctx->altivec_enabled)) {
2879        gen_exception(ctx, POWERPC_EXCP_VPU);
2880        return;
2881    }
2882    ra = gen_avr_ptr(rA(ctx->opcode));
2883    rd = gen_avr_ptr(rD(ctx->opcode));
2884    gen_helper_vsbox(rd, ra);
2885    tcg_temp_free_ptr(ra);
2886    tcg_temp_free_ptr(rd);
2887}
2888
2889GEN_VXFORM(vcipher, 4, 20)
2890GEN_VXFORM(vcipherlast, 4, 20)
2891GEN_VXFORM(vncipher, 4, 21)
2892GEN_VXFORM(vncipherlast, 4, 21)
2893
2894GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
2895                vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
2896GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
2897                vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
2898
2899#define VSHASIGMA(op)                         \
2900static void gen_##op(DisasContext *ctx)       \
2901{                                             \
2902    TCGv_ptr ra, rd;                          \
2903    TCGv_i32 st_six;                          \
2904    if (unlikely(!ctx->altivec_enabled)) {    \
2905        gen_exception(ctx, POWERPC_EXCP_VPU); \
2906        return;                               \
2907    }                                         \
2908    ra = gen_avr_ptr(rA(ctx->opcode));        \
2909    rd = gen_avr_ptr(rD(ctx->opcode));        \
2910    st_six = tcg_const_i32(rB(ctx->opcode));  \
2911    gen_helper_##op(rd, ra, st_six);          \
2912    tcg_temp_free_ptr(ra);                    \
2913    tcg_temp_free_ptr(rd);                    \
2914    tcg_temp_free_i32(st_six);                \
2915}
2916
2917VSHASIGMA(vshasigmaw)
2918VSHASIGMA(vshasigmad)
2919
2920GEN_VXFORM3(vpermxor, 22, 0xFF)
2921GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
2922                vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
2923
2924static bool trans_VCFUGED(DisasContext *ctx, arg_VX *a)
2925{
2926    static const GVecGen3 g = {
2927        .fni8 = gen_helper_CFUGED,
2928        .vece = MO_64,
2929    };
2930
2931    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2932    REQUIRE_VECTOR(ctx);
2933
2934    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
2935                   avr_full_offset(a->vrb), 16, 16, &g);
2936
2937    return true;
2938}
2939
2940static bool trans_VCLZDM(DisasContext *ctx, arg_VX *a)
2941{
2942    static const GVecGen3i g = {
2943        .fni8 = do_cntzdm,
2944        .vece = MO_64,
2945    };
2946
2947    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2948    REQUIRE_VECTOR(ctx);
2949
2950    tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
2951                    avr_full_offset(a->vrb), 16, 16, false, &g);
2952
2953    return true;
2954}
2955
2956static bool trans_VCTZDM(DisasContext *ctx, arg_VX *a)
2957{
2958    static const GVecGen3i g = {
2959        .fni8 = do_cntzdm,
2960        .vece = MO_64,
2961    };
2962
2963    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2964    REQUIRE_VECTOR(ctx);
2965
2966    tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
2967                    avr_full_offset(a->vrb), 16, 16, true, &g);
2968
2969    return true;
2970}
2971
2972static bool trans_VPDEPD(DisasContext *ctx, arg_VX *a)
2973{
2974    static const GVecGen3 g = {
2975        .fni8 = gen_helper_PDEPD,
2976        .vece = MO_64,
2977    };
2978
2979    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2980    REQUIRE_VECTOR(ctx);
2981
2982    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
2983                   avr_full_offset(a->vrb), 16, 16, &g);
2984
2985    return true;
2986}
2987
2988static bool trans_VPEXTD(DisasContext *ctx, arg_VX *a)
2989{
2990    static const GVecGen3 g = {
2991        .fni8 = gen_helper_PEXTD,
2992        .vece = MO_64,
2993    };
2994
2995    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2996    REQUIRE_VECTOR(ctx);
2997
2998    tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
2999                   avr_full_offset(a->vrb), 16, 16, &g);
3000
3001    return true;
3002}
3003
3004static bool trans_VMSUMUDM(DisasContext *ctx, arg_VA *a)
3005{
3006    TCGv_i64 rl, rh, src1, src2;
3007    int dw;
3008
3009    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
3010    REQUIRE_VECTOR(ctx);
3011
3012    rh = tcg_temp_new_i64();
3013    rl = tcg_temp_new_i64();
3014    src1 = tcg_temp_new_i64();
3015    src2 = tcg_temp_new_i64();
3016
3017    get_avr64(rl, a->rc, false);
3018    get_avr64(rh, a->rc, true);
3019
3020    for (dw = 0; dw < 2; dw++) {
3021        get_avr64(src1, a->vra, dw);
3022        get_avr64(src2, a->vrb, dw);
3023        tcg_gen_mulu2_i64(src1, src2, src1, src2);
3024        tcg_gen_add2_i64(rl, rh, rl, rh, src1, src2);
3025    }
3026
3027    set_avr64(a->vrt, rl, false);
3028    set_avr64(a->vrt, rh, true);
3029
3030    tcg_temp_free_i64(rl);
3031    tcg_temp_free_i64(rh);
3032    tcg_temp_free_i64(src1);
3033    tcg_temp_free_i64(src2);
3034
3035    return true;
3036}
3037
3038static bool trans_VMSUMCUD(DisasContext *ctx, arg_VA *a)
3039{
3040    TCGv_i64 tmp0, tmp1, prod1h, prod1l, prod0h, prod0l, zero;
3041
3042    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
3043    REQUIRE_VECTOR(ctx);
3044
3045    tmp0 = tcg_temp_new_i64();
3046    tmp1 = tcg_temp_new_i64();
3047    prod1h = tcg_temp_new_i64();
3048    prod1l = tcg_temp_new_i64();
3049    prod0h = tcg_temp_new_i64();
3050    prod0l = tcg_temp_new_i64();
3051    zero = tcg_constant_i64(0);
3052
3053    /* prod1 = vsr[vra+32].dw[1] * vsr[vrb+32].dw[1] */
3054    get_avr64(tmp0, a->vra, false);
3055    get_avr64(tmp1, a->vrb, false);
3056    tcg_gen_mulu2_i64(prod1l, prod1h, tmp0, tmp1);
3057
3058    /* prod0 = vsr[vra+32].dw[0] * vsr[vrb+32].dw[0] */
3059    get_avr64(tmp0, a->vra, true);
3060    get_avr64(tmp1, a->vrb, true);
3061    tcg_gen_mulu2_i64(prod0l, prod0h, tmp0, tmp1);
3062
3063    /* Sum lower 64-bits elements */
3064    get_avr64(tmp1, a->rc, false);
3065    tcg_gen_add2_i64(tmp1, tmp0, tmp1, zero, prod1l, zero);
3066    tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0l, zero);
3067
3068    /*
3069     * Discard lower 64-bits, leaving the carry into bit 64.
3070     * Then sum the higher 64-bit elements.
3071     */
3072    get_avr64(tmp1, a->rc, true);
3073    tcg_gen_add2_i64(tmp1, tmp0, tmp0, zero, tmp1, zero);
3074    tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod1h, zero);
3075    tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0h, zero);
3076
3077    /* Discard 64 more bits to complete the CHOP128(temp >> 128) */
3078    set_avr64(a->vrt, tmp0, false);
3079    set_avr64(a->vrt, zero, true);
3080
3081    tcg_temp_free_i64(tmp0);
3082    tcg_temp_free_i64(tmp1);
3083    tcg_temp_free_i64(prod1h);
3084    tcg_temp_free_i64(prod1l);
3085    tcg_temp_free_i64(prod0h);
3086    tcg_temp_free_i64(prod0l);
3087
3088    return true;
3089}
3090
3091static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
3092                         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
3093{
3094    TCGv_ptr ra, rb, rd;
3095    REQUIRE_VECTOR(ctx);
3096
3097    ra = gen_avr_ptr(a->vra);
3098    rb = gen_avr_ptr(a->vrb);
3099    rd = gen_avr_ptr(a->vrt);
3100    gen_helper(rd, ra, rb);
3101    tcg_temp_free_ptr(ra);
3102    tcg_temp_free_ptr(rb);
3103    tcg_temp_free_ptr(rd);
3104
3105    return true;
3106}
3107
3108static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
3109                         void (*gen_mul)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
3110{
3111    TCGv_i64 vra, vrb, vrt0, vrt1;
3112    REQUIRE_VECTOR(ctx);
3113
3114    vra = tcg_temp_new_i64();
3115    vrb = tcg_temp_new_i64();
3116    vrt0 = tcg_temp_new_i64();
3117    vrt1 = tcg_temp_new_i64();
3118
3119    get_avr64(vra, a->vra, even);
3120    get_avr64(vrb, a->vrb, even);
3121    gen_mul(vrt0, vrt1, vra, vrb);
3122    set_avr64(a->vrt, vrt0, false);
3123    set_avr64(a->vrt, vrt1, true);
3124
3125    tcg_temp_free_i64(vra);
3126    tcg_temp_free_i64(vrb);
3127    tcg_temp_free_i64(vrt0);
3128    tcg_temp_free_i64(vrt1);
3129
3130    return true;
3131}
3132
3133static bool trans_VMULLD(DisasContext *ctx, arg_VX *a)
3134{
3135    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
3136    REQUIRE_VECTOR(ctx);
3137
3138    tcg_gen_gvec_mul(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->vra),
3139                     avr_full_offset(a->vrb), 16, 16);
3140
3141    return true;
3142}
3143
3144TRANS_FLAGS2(ALTIVEC_207, VMULESB, do_vx_helper, gen_helper_VMULESB)
3145TRANS_FLAGS2(ALTIVEC_207, VMULOSB, do_vx_helper, gen_helper_VMULOSB)
3146TRANS_FLAGS2(ALTIVEC_207, VMULEUB, do_vx_helper, gen_helper_VMULEUB)
3147TRANS_FLAGS2(ALTIVEC_207, VMULOUB, do_vx_helper, gen_helper_VMULOUB)
3148TRANS_FLAGS2(ALTIVEC_207, VMULESH, do_vx_helper, gen_helper_VMULESH)
3149TRANS_FLAGS2(ALTIVEC_207, VMULOSH, do_vx_helper, gen_helper_VMULOSH)
3150TRANS_FLAGS2(ALTIVEC_207, VMULEUH, do_vx_helper, gen_helper_VMULEUH)
3151TRANS_FLAGS2(ALTIVEC_207, VMULOUH, do_vx_helper, gen_helper_VMULOUH)
3152TRANS_FLAGS2(ALTIVEC_207, VMULESW, do_vx_helper, gen_helper_VMULESW)
3153TRANS_FLAGS2(ALTIVEC_207, VMULOSW, do_vx_helper, gen_helper_VMULOSW)
3154TRANS_FLAGS2(ALTIVEC_207, VMULEUW, do_vx_helper, gen_helper_VMULEUW)
3155TRANS_FLAGS2(ALTIVEC_207, VMULOUW, do_vx_helper, gen_helper_VMULOUW)
3156TRANS_FLAGS2(ISA310, VMULESD, do_vx_vmuleo, true , tcg_gen_muls2_i64)
3157TRANS_FLAGS2(ISA310, VMULOSD, do_vx_vmuleo, false, tcg_gen_muls2_i64)
3158TRANS_FLAGS2(ISA310, VMULEUD, do_vx_vmuleo, true , tcg_gen_mulu2_i64)
3159TRANS_FLAGS2(ISA310, VMULOUD, do_vx_vmuleo, false, tcg_gen_mulu2_i64)
3160
3161static void do_vx_vmulhw_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
3162{
3163    TCGv_i64 hh, lh, temp;
3164
3165    uint64_t c;
3166    hh = tcg_temp_new_i64();
3167    lh = tcg_temp_new_i64();
3168    temp = tcg_temp_new_i64();
3169
3170    c = 0xFFFFFFFF;
3171
3172    if (sign) {
3173        tcg_gen_ext32s_i64(lh, a);
3174        tcg_gen_ext32s_i64(temp, b);
3175    } else {
3176        tcg_gen_andi_i64(lh, a, c);
3177        tcg_gen_andi_i64(temp, b, c);
3178    }
3179    tcg_gen_mul_i64(lh, lh, temp);
3180
3181    if (sign) {
3182        tcg_gen_sari_i64(hh, a, 32);
3183        tcg_gen_sari_i64(temp, b, 32);
3184    } else {
3185        tcg_gen_shri_i64(hh, a, 32);
3186        tcg_gen_shri_i64(temp, b, 32);
3187    }
3188    tcg_gen_mul_i64(hh, hh, temp);
3189
3190    tcg_gen_shri_i64(lh, lh, 32);
3191    tcg_gen_andi_i64(hh, hh, c << 32);
3192    tcg_gen_or_i64(t, hh, lh);
3193
3194    tcg_temp_free_i64(hh);
3195    tcg_temp_free_i64(lh);
3196    tcg_temp_free_i64(temp);
3197}
3198
3199static void do_vx_vmulhd_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
3200{
3201    TCGv_i64 tlow;
3202
3203    tlow  = tcg_temp_new_i64();
3204    if (sign) {
3205        tcg_gen_muls2_i64(tlow, t, a, b);
3206    } else {
3207        tcg_gen_mulu2_i64(tlow, t, a, b);
3208    }
3209
3210    tcg_temp_free_i64(tlow);
3211}
3212
3213static bool do_vx_mulh(DisasContext *ctx, arg_VX *a, bool sign,
3214                       void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, bool))
3215{
3216    REQUIRE_INSNS_FLAGS2(ctx, ISA310);
3217    REQUIRE_VECTOR(ctx);
3218
3219    TCGv_i64 vra, vrb, vrt;
3220    int i;
3221
3222    vra = tcg_temp_new_i64();
3223    vrb = tcg_temp_new_i64();
3224    vrt = tcg_temp_new_i64();
3225
3226    for (i = 0; i < 2; i++) {
3227        get_avr64(vra, a->vra, i);
3228        get_avr64(vrb, a->vrb, i);
3229        get_avr64(vrt, a->vrt, i);
3230
3231        func(vrt, vra, vrb, sign);
3232
3233        set_avr64(a->vrt, vrt, i);
3234    }
3235
3236    tcg_temp_free_i64(vra);
3237    tcg_temp_free_i64(vrb);
3238    tcg_temp_free_i64(vrt);
3239
3240    return true;
3241
3242}
3243
3244TRANS(VMULHSW, do_vx_mulh, true , do_vx_vmulhw_i64)
3245TRANS(VMULHSD, do_vx_mulh, true , do_vx_vmulhd_i64)
3246TRANS(VMULHUW, do_vx_mulh, false, do_vx_vmulhw_i64)
3247TRANS(VMULHUD, do_vx_mulh, false, do_vx_vmulhd_i64)
3248
3249#undef GEN_VR_LDX
3250#undef GEN_VR_STX
3251#undef GEN_VR_LVE
3252#undef GEN_VR_STVE
3253
3254#undef GEN_VX_LOGICAL
3255#undef GEN_VX_LOGICAL_207
3256#undef GEN_VXFORM
3257#undef GEN_VXFORM_207
3258#undef GEN_VXFORM_DUAL
3259#undef GEN_VXRFORM_DUAL
3260#undef GEN_VXRFORM1
3261#undef GEN_VXRFORM
3262#undef GEN_VXFORM_VSPLTI
3263#undef GEN_VXFORM_NOA
3264#undef GEN_VXFORM_UIMM
3265#undef GEN_VAFORM_PAIRED
3266
3267#undef GEN_BCD2
3268