master
inc 2,889 lines 94.7 KB
Raw
1 /*** VSX extension ***/
2
3 static inline void get_cpu_vsr(TCGv_i64 dst, int n, bool high)
4 {
5 tcg_gen_ld_i64(dst, tcg_env, vsr64_offset(n, high));
6 }
7
8 static inline void set_cpu_vsr(int n, TCGv_i64 src, bool high)
9 {
10 tcg_gen_st_i64(src, tcg_env, vsr64_offset(n, high));
11 }
12
13 static inline void get_vsr_full(TCGv_i128 dst, int reg)
14 {
15 tcg_gen_ld_i128(dst, tcg_env, vsr_full_offset(reg));
16 }
17
18 static inline void set_vsr_full(int reg, TCGv_i128 src)
19 {
20 tcg_gen_st_i128(src, tcg_env, vsr_full_offset(reg));
21 }
22
23 static inline TCGv_ptr gen_vsr_ptr(int reg)
24 {
25 TCGv_ptr r = tcg_temp_new_ptr();
26 tcg_gen_addi_ptr(r, tcg_env, vsr_full_offset(reg));
27 return r;
28 }
29
30 static inline TCGv_ptr gen_acc_ptr(int reg)
31 {
32 TCGv_ptr r = tcg_temp_new_ptr();
33 tcg_gen_addi_ptr(r, tcg_env, acc_full_offset(reg));
34 return r;
35 }
36
37 static bool do_lxs(DisasContext *ctx, arg_X *a,
38 void (*op)(DisasContext *, TCGv_i64, TCGv))
39 {
40 TCGv EA;
41 TCGv_i64 t0;
42 REQUIRE_VSX(ctx);
43 t0 = tcg_temp_new_i64();
44 gen_set_access_type(ctx, ACCESS_INT);
45 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
46 op(ctx, t0, EA);
47 set_cpu_vsr(a->rt, t0, true);
48 /* NOTE: cpu_vsrl is undefined */
49 return true;
50 }
51
52 TRANS_FLAGS2(VSX, LXSDX, do_lxs, gen_qemu_ld64_i64);
53 TRANS_FLAGS2(ISA207, LXSIWAX, do_lxs, gen_qemu_ld32s_i64);
54 TRANS_FLAGS2(ISA300, LXSIBZX, do_lxs, gen_qemu_ld8u_i64);
55 TRANS_FLAGS2(ISA300, LXSIHZX, do_lxs, gen_qemu_ld16u_i64);
56 TRANS_FLAGS2(ISA207, LXSIWZX, do_lxs, gen_qemu_ld32u_i64);
57 TRANS_FLAGS2(ISA207, LXSSPX, do_lxs, gen_qemu_ld32fs);
58
59 static bool trans_LXVD2X(DisasContext *ctx, arg_LXVD2X *a)
60 {
61 TCGv EA;
62 TCGv_i64 t0;
63
64 REQUIRE_INSNS_FLAGS2(ctx, VSX);
65 REQUIRE_VSX(ctx);
66
67 t0 = tcg_temp_new_i64();
68 gen_set_access_type(ctx, ACCESS_INT);
69 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
70 gen_qemu_ld64_i64(ctx, t0, EA);
71 set_cpu_vsr(a->rt, t0, true);
72 tcg_gen_addi_tl(EA, EA, 8);
73 gen_qemu_ld64_i64(ctx, t0, EA);
74 set_cpu_vsr(a->rt, t0, false);
75 return true;
76 }
77
78 static bool trans_LXVW4X(DisasContext *ctx, arg_LXVW4X *a)
79 {
80 TCGv EA;
81 TCGv_i64 xth, xtl;
82
83 REQUIRE_INSNS_FLAGS2(ctx, VSX);
84 REQUIRE_VSX(ctx);
85
86 xth = tcg_temp_new_i64();
87 xtl = tcg_temp_new_i64();
88 gen_set_access_type(ctx, ACCESS_INT);
89 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
90 if (ctx->le_mode) {
91 TCGv_i64 t0 = tcg_temp_new_i64();
92 TCGv_i64 t1 = tcg_temp_new_i64();
93
94 tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
95 tcg_gen_shri_i64(t1, t0, 32);
96 tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
97 tcg_gen_addi_tl(EA, EA, 8);
98 tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
99 tcg_gen_shri_i64(t1, t0, 32);
100 tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
101 } else {
102 tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
103 tcg_gen_addi_tl(EA, EA, 8);
104 tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
105 }
106 set_cpu_vsr(a->rt, xth, true);
107 set_cpu_vsr(a->rt, xtl, false);
108 return true;
109 }
110
111 static bool trans_LXVWSX(DisasContext *ctx, arg_LXVWSX *a)
112 {
113 TCGv EA;
114 TCGv_i32 data;
115
116 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
117 if (a->rt < 32) {
118 REQUIRE_VSX(ctx);
119 } else {
120 REQUIRE_VECTOR(ctx);
121 }
122
123 gen_set_access_type(ctx, ACCESS_INT);
124 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
125 data = tcg_temp_new_i32();
126 tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
127 tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(a->rt), 16, 16, data);
128 return true;
129 }
130
131 static bool trans_LXVDSX(DisasContext *ctx, arg_LXVDSX *a)
132 {
133 TCGv EA;
134 TCGv_i64 data;
135
136 REQUIRE_INSNS_FLAGS2(ctx, VSX);
137 REQUIRE_VSX(ctx);
138
139 gen_set_access_type(ctx, ACCESS_INT);
140 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
141 data = tcg_temp_new_i64();
142 tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ));
143 tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(a->rt), 16, 16, data);
144 return true;
145 }
146
147 static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
148 TCGv_i64 inh, TCGv_i64 inl)
149 {
150 TCGv_i64 mask = tcg_constant_i64(0x00FF00FF00FF00FF);
151 TCGv_i64 t0 = tcg_temp_new_i64();
152 TCGv_i64 t1 = tcg_temp_new_i64();
153
154 /* outh = ((inh & mask) << 8) | ((inh >> 8) & mask) */
155 tcg_gen_and_i64(t0, inh, mask);
156 tcg_gen_shli_i64(t0, t0, 8);
157 tcg_gen_shri_i64(t1, inh, 8);
158 tcg_gen_and_i64(t1, t1, mask);
159 tcg_gen_or_i64(outh, t0, t1);
160
161 /* outl = ((inl & mask) << 8) | ((inl >> 8) & mask) */
162 tcg_gen_and_i64(t0, inl, mask);
163 tcg_gen_shli_i64(t0, t0, 8);
164 tcg_gen_shri_i64(t1, inl, 8);
165 tcg_gen_and_i64(t1, t1, mask);
166 tcg_gen_or_i64(outl, t0, t1);
167 }
168
169 static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
170 TCGv_i64 inh, TCGv_i64 inl)
171 {
172 TCGv_i64 hi = tcg_temp_new_i64();
173 TCGv_i64 lo = tcg_temp_new_i64();
174
175 tcg_gen_bswap64_i64(hi, inh);
176 tcg_gen_bswap64_i64(lo, inl);
177 tcg_gen_shri_i64(outh, hi, 32);
178 tcg_gen_deposit_i64(outh, outh, hi, 32, 32);
179 tcg_gen_shri_i64(outl, lo, 32);
180 tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
181 }
182
183 static bool trans_LXVH8X(DisasContext *ctx, arg_LXVH8X *a)
184 {
185 TCGv EA;
186 TCGv_i64 xth, xtl;
187
188 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
189 REQUIRE_VSX(ctx);
190
191 xth = tcg_temp_new_i64();
192 xtl = tcg_temp_new_i64();
193 gen_set_access_type(ctx, ACCESS_INT);
194 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
195 tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
196 tcg_gen_addi_tl(EA, EA, 8);
197 tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
198 if (ctx->le_mode) {
199 gen_bswap16x8(xth, xtl, xth, xtl);
200 }
201 set_cpu_vsr(a->rt, xth, true);
202 set_cpu_vsr(a->rt, xtl, false);
203 return true;
204 }
205
206 static bool trans_LXVB16X(DisasContext *ctx, arg_LXVB16X *a)
207 {
208 TCGv EA;
209 TCGv_i128 data;
210
211 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
212 REQUIRE_VSX(ctx);
213
214 data = tcg_temp_new_i128();
215 gen_set_access_type(ctx, ACCESS_INT);
216 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
217 tcg_gen_qemu_ld_i128(data, EA, ctx->mem_idx,
218 MO_BE | MO_128 | MO_ATOM_IFALIGN_PAIR);
219 set_vsr_full(a->rt, data);
220 return true;
221 }
222
223 #if defined(TARGET_PPC64)
224 static bool do_ld_st_vl(DisasContext *ctx, arg_X *a,
225 void (*helper)(TCGv_ptr, TCGv, TCGv_ptr, TCGv))
226 {
227 TCGv EA;
228 TCGv_ptr xt;
229 if (a->rt < 32) {
230 REQUIRE_VSX(ctx);
231 } else {
232 REQUIRE_VECTOR(ctx);
233 }
234 xt = gen_vsr_ptr(a->rt);
235 gen_set_access_type(ctx, ACCESS_INT);
236 EA = do_ea_calc_ra(ctx, a->ra);
237 helper(tcg_env, EA, xt, cpu_gpr[a->rb]);
238 return true;
239 }
240 #endif
241
242 static bool trans_LXVL(DisasContext *ctx, arg_LXVL *a)
243 {
244 REQUIRE_64BIT(ctx);
245 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
246 #if defined(TARGET_PPC64)
247 return do_ld_st_vl(ctx, a, gen_helper_LXVL);
248 #else
249 qemu_build_not_reached();
250 #endif
251 return true;
252 }
253
254 static bool trans_LXVLL(DisasContext *ctx, arg_LXVLL *a)
255 {
256 REQUIRE_64BIT(ctx);
257 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
258 #if defined(TARGET_PPC64)
259 return do_ld_st_vl(ctx, a, gen_helper_LXVLL);
260 #else
261 qemu_build_not_reached();
262 #endif
263 return true;
264 }
265
266 static bool trans_STXVL(DisasContext *ctx, arg_STXVL *a)
267 {
268 REQUIRE_64BIT(ctx);
269 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
270 #if defined(TARGET_PPC64)
271 return do_ld_st_vl(ctx, a, gen_helper_STXVL);
272 #else
273 qemu_build_not_reached();
274 #endif
275 return true;
276 }
277
278 static bool trans_STXVLL(DisasContext *ctx, arg_STXVLL *a)
279 {
280 REQUIRE_64BIT(ctx);
281 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
282 #if defined(TARGET_PPC64)
283 return do_ld_st_vl(ctx, a, gen_helper_STXVLL);
284 #else
285 qemu_build_not_reached();
286 #endif
287 return true;
288 }
289
290 static bool do_stxs(DisasContext *ctx, arg_X *a,
291 void (*op)(DisasContext *, TCGv_i64, TCGv))
292 {
293 TCGv EA;
294 TCGv_i64 t0;
295 REQUIRE_VSX(ctx);
296 t0 = tcg_temp_new_i64();
297 gen_set_access_type(ctx, ACCESS_INT);
298 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
299 get_cpu_vsr(t0, a->rt, true);
300 op(ctx, t0, EA);
301 return true;
302 }
303
304 TRANS_FLAGS2(VSX, STXSDX, do_stxs, gen_qemu_st64_i64);
305 TRANS_FLAGS2(ISA300, STXSIBX, do_stxs, gen_qemu_st8_i64);
306 TRANS_FLAGS2(ISA300, STXSIHX, do_stxs, gen_qemu_st16_i64);
307 TRANS_FLAGS2(ISA207, STXSIWX, do_stxs, gen_qemu_st32_i64);
308 TRANS_FLAGS2(ISA207, STXSSPX, do_stxs, gen_qemu_st32fs);
309
310 static bool trans_STXVD2X(DisasContext *ctx, arg_STXVD2X *a)
311 {
312 TCGv EA;
313 TCGv_i64 t0;
314
315 REQUIRE_INSNS_FLAGS2(ctx, VSX);
316 REQUIRE_VSX(ctx);
317
318 t0 = tcg_temp_new_i64();
319 gen_set_access_type(ctx, ACCESS_INT);
320 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
321 get_cpu_vsr(t0, a->rt, true);
322 gen_qemu_st64_i64(ctx, t0, EA);
323 tcg_gen_addi_tl(EA, EA, 8);
324 get_cpu_vsr(t0, a->rt, false);
325 gen_qemu_st64_i64(ctx, t0, EA);
326 return true;
327 }
328
329 static bool trans_STXVW4X(DisasContext *ctx, arg_STXVW4X *a)
330 {
331 TCGv EA;
332 TCGv_i64 xsh, xsl;
333
334 REQUIRE_INSNS_FLAGS2(ctx, VSX);
335 REQUIRE_VSX(ctx);
336
337 xsh = tcg_temp_new_i64();
338 xsl = tcg_temp_new_i64();
339 get_cpu_vsr(xsh, a->rt, true);
340 get_cpu_vsr(xsl, a->rt, false);
341 gen_set_access_type(ctx, ACCESS_INT);
342 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
343 if (ctx->le_mode) {
344 TCGv_i64 t0 = tcg_temp_new_i64();
345 TCGv_i64 t1 = tcg_temp_new_i64();
346
347 tcg_gen_shri_i64(t0, xsh, 32);
348 tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
349 tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
350 tcg_gen_addi_tl(EA, EA, 8);
351 tcg_gen_shri_i64(t0, xsl, 32);
352 tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
353 tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
354 } else {
355 tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
356 tcg_gen_addi_tl(EA, EA, 8);
357 tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
358 }
359 return true;
360 }
361
362 static bool trans_STXVH8X(DisasContext *ctx, arg_STXVH8X *a)
363 {
364 TCGv EA;
365 TCGv_i64 xsh, xsl;
366
367 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
368 REQUIRE_VSX(ctx);
369
370 xsh = tcg_temp_new_i64();
371 xsl = tcg_temp_new_i64();
372 get_cpu_vsr(xsh, a->rt, true);
373 get_cpu_vsr(xsl, a->rt, false);
374 gen_set_access_type(ctx, ACCESS_INT);
375 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
376 if (ctx->le_mode) {
377 TCGv_i64 outh = tcg_temp_new_i64();
378 TCGv_i64 outl = tcg_temp_new_i64();
379
380 gen_bswap16x8(outh, outl, xsh, xsl);
381 tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEUQ);
382 tcg_gen_addi_tl(EA, EA, 8);
383 tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEUQ);
384 } else {
385 tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
386 tcg_gen_addi_tl(EA, EA, 8);
387 tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
388 }
389 return true;
390 }
391
392 static bool trans_STXVB16X(DisasContext *ctx, arg_STXVB16X *a)
393 {
394 TCGv EA;
395 TCGv_i128 data;
396
397 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
398 REQUIRE_VSX(ctx);
399
400 data = tcg_temp_new_i128();
401 gen_set_access_type(ctx, ACCESS_INT);
402 EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
403 get_vsr_full(data, a->rt);
404 tcg_gen_qemu_st_i128(data, EA, ctx->mem_idx,
405 MO_BE | MO_128 | MO_ATOM_IFALIGN_PAIR);
406 return true;
407 }
408
409 static void gen_mfvsrwz(DisasContext *ctx)
410 {
411 if (xS(ctx->opcode) < 32) {
412 if (unlikely(!ctx->fpu_enabled)) {
413 gen_exception(ctx, POWERPC_EXCP_FPU);
414 return;
415 }
416 } else {
417 if (unlikely(!ctx->altivec_enabled)) {
418 gen_exception(ctx, POWERPC_EXCP_VPU);
419 return;
420 }
421 }
422 TCGv_i64 tmp = tcg_temp_new_i64();
423 TCGv_i64 xsh = tcg_temp_new_i64();
424 get_cpu_vsr(xsh, xS(ctx->opcode), true);
425 tcg_gen_ext32u_i64(tmp, xsh);
426 tcg_gen_trunc_i64_tl(cpu_gpr[rA(ctx->opcode)], tmp);
427 }
428
429 static void gen_mtvsrwa(DisasContext *ctx)
430 {
431 if (xS(ctx->opcode) < 32) {
432 if (unlikely(!ctx->fpu_enabled)) {
433 gen_exception(ctx, POWERPC_EXCP_FPU);
434 return;
435 }
436 } else {
437 if (unlikely(!ctx->altivec_enabled)) {
438 gen_exception(ctx, POWERPC_EXCP_VPU);
439 return;
440 }
441 }
442 TCGv_i64 tmp = tcg_temp_new_i64();
443 TCGv_i64 xsh = tcg_temp_new_i64();
444 tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
445 tcg_gen_ext32s_i64(xsh, tmp);
446 set_cpu_vsr(xT(ctx->opcode), xsh, true);
447 }
448
449 static void gen_mtvsrwz(DisasContext *ctx)
450 {
451 if (xS(ctx->opcode) < 32) {
452 if (unlikely(!ctx->fpu_enabled)) {
453 gen_exception(ctx, POWERPC_EXCP_FPU);
454 return;
455 }
456 } else {
457 if (unlikely(!ctx->altivec_enabled)) {
458 gen_exception(ctx, POWERPC_EXCP_VPU);
459 return;
460 }
461 }
462 TCGv_i64 tmp = tcg_temp_new_i64();
463 TCGv_i64 xsh = tcg_temp_new_i64();
464 tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
465 tcg_gen_ext32u_i64(xsh, tmp);
466 set_cpu_vsr(xT(ctx->opcode), xsh, true);
467 }
468
469 #if defined(TARGET_PPC64)
470 static void gen_mfvsrd(DisasContext *ctx)
471 {
472 TCGv_i64 t0;
473 if (xS(ctx->opcode) < 32) {
474 if (unlikely(!ctx->fpu_enabled)) {
475 gen_exception(ctx, POWERPC_EXCP_FPU);
476 return;
477 }
478 } else {
479 if (unlikely(!ctx->altivec_enabled)) {
480 gen_exception(ctx, POWERPC_EXCP_VPU);
481 return;
482 }
483 }
484 t0 = tcg_temp_new_i64();
485 get_cpu_vsr(t0, xS(ctx->opcode), true);
486 tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
487 }
488
489 static void gen_mtvsrd(DisasContext *ctx)
490 {
491 TCGv_i64 t0;
492 if (xS(ctx->opcode) < 32) {
493 if (unlikely(!ctx->fpu_enabled)) {
494 gen_exception(ctx, POWERPC_EXCP_FPU);
495 return;
496 }
497 } else {
498 if (unlikely(!ctx->altivec_enabled)) {
499 gen_exception(ctx, POWERPC_EXCP_VPU);
500 return;
501 }
502 }
503 t0 = tcg_temp_new_i64();
504 tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
505 set_cpu_vsr(xT(ctx->opcode), t0, true);
506 }
507
508 static void gen_mfvsrld(DisasContext *ctx)
509 {
510 TCGv_i64 t0;
511 if (xS(ctx->opcode) < 32) {
512 if (unlikely(!ctx->vsx_enabled)) {
513 gen_exception(ctx, POWERPC_EXCP_VSXU);
514 return;
515 }
516 } else {
517 if (unlikely(!ctx->altivec_enabled)) {
518 gen_exception(ctx, POWERPC_EXCP_VPU);
519 return;
520 }
521 }
522 t0 = tcg_temp_new_i64();
523 get_cpu_vsr(t0, xS(ctx->opcode), false);
524 tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
525 }
526
527 static void gen_mtvsrdd(DisasContext *ctx)
528 {
529 TCGv_i64 t0;
530 if (xT(ctx->opcode) < 32) {
531 if (unlikely(!ctx->vsx_enabled)) {
532 gen_exception(ctx, POWERPC_EXCP_VSXU);
533 return;
534 }
535 } else {
536 if (unlikely(!ctx->altivec_enabled)) {
537 gen_exception(ctx, POWERPC_EXCP_VPU);
538 return;
539 }
540 }
541
542 t0 = tcg_temp_new_i64();
543 if (!rA(ctx->opcode)) {
544 tcg_gen_movi_i64(t0, 0);
545 } else {
546 tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
547 }
548 set_cpu_vsr(xT(ctx->opcode), t0, true);
549
550 tcg_gen_mov_i64(t0, cpu_gpr[rB(ctx->opcode)]);
551 set_cpu_vsr(xT(ctx->opcode), t0, false);
552 }
553
554 static void gen_mtvsrws(DisasContext *ctx)
555 {
556 TCGv_i64 t0;
557 if (xT(ctx->opcode) < 32) {
558 if (unlikely(!ctx->vsx_enabled)) {
559 gen_exception(ctx, POWERPC_EXCP_VSXU);
560 return;
561 }
562 } else {
563 if (unlikely(!ctx->altivec_enabled)) {
564 gen_exception(ctx, POWERPC_EXCP_VPU);
565 return;
566 }
567 }
568
569 t0 = tcg_temp_new_i64();
570 tcg_gen_deposit_i64(t0, cpu_gpr[rA(ctx->opcode)],
571 cpu_gpr[rA(ctx->opcode)], 32, 32);
572 set_cpu_vsr(xT(ctx->opcode), t0, false);
573 set_cpu_vsr(xT(ctx->opcode), t0, true);
574 }
575
576 #endif
577
578 #define OP_ABS 1
579 #define OP_NABS 2
580 #define OP_NEG 3
581 #define OP_CPSGN 4
582 #define SGN_MASK_DP 0x8000000000000000ull
583 #define SGN_MASK_SP 0x8000000080000000ull
584 #define EXP_MASK_DP 0x7FF0000000000000ull
585 #define EXP_MASK_SP 0x7F8000007F800000ull
586 #define FRC_MASK_DP (~(SGN_MASK_DP | EXP_MASK_DP))
587 #define FRC_MASK_SP (~(SGN_MASK_SP | EXP_MASK_SP))
588
589 #define VSX_SCALAR_MOVE(name, op, sgn_mask) \
590 static void glue(gen_, name)(DisasContext *ctx) \
591 { \
592 TCGv_i64 xb, sgm; \
593 if (unlikely(!ctx->vsx_enabled)) { \
594 gen_exception(ctx, POWERPC_EXCP_VSXU); \
595 return; \
596 } \
597 xb = tcg_temp_new_i64(); \
598 sgm = tcg_temp_new_i64(); \
599 get_cpu_vsr(xb, xB(ctx->opcode), true); \
600 tcg_gen_movi_i64(sgm, sgn_mask); \
601 switch (op) { \
602 case OP_ABS: { \
603 tcg_gen_andc_i64(xb, xb, sgm); \
604 break; \
605 } \
606 case OP_NABS: { \
607 tcg_gen_or_i64(xb, xb, sgm); \
608 break; \
609 } \
610 case OP_NEG: { \
611 tcg_gen_xor_i64(xb, xb, sgm); \
612 break; \
613 } \
614 case OP_CPSGN: { \
615 TCGv_i64 xa = tcg_temp_new_i64(); \
616 get_cpu_vsr(xa, xA(ctx->opcode), true); \
617 tcg_gen_and_i64(xa, xa, sgm); \
618 tcg_gen_andc_i64(xb, xb, sgm); \
619 tcg_gen_or_i64(xb, xb, xa); \
620 break; \
621 } \
622 } \
623 set_cpu_vsr(xT(ctx->opcode), xb, true); \
624 set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
625 }
626
627 VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
628 VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
629 VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
630 VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
631
632 #define VSX_SCALAR_MOVE_QP(name, op, sgn_mask) \
633 static void glue(gen_, name)(DisasContext *ctx) \
634 { \
635 int xa; \
636 int xt = rD(ctx->opcode) + 32; \
637 int xb = rB(ctx->opcode) + 32; \
638 TCGv_i64 xah, xbh, xbl, sgm, tmp; \
639 \
640 if (unlikely(!ctx->vsx_enabled)) { \
641 gen_exception(ctx, POWERPC_EXCP_VSXU); \
642 return; \
643 } \
644 xbh = tcg_temp_new_i64(); \
645 xbl = tcg_temp_new_i64(); \
646 sgm = tcg_temp_new_i64(); \
647 tmp = tcg_temp_new_i64(); \
648 get_cpu_vsr(xbh, xb, true); \
649 get_cpu_vsr(xbl, xb, false); \
650 tcg_gen_movi_i64(sgm, sgn_mask); \
651 switch (op) { \
652 case OP_ABS: \
653 tcg_gen_andc_i64(xbh, xbh, sgm); \
654 break; \
655 case OP_NABS: \
656 tcg_gen_or_i64(xbh, xbh, sgm); \
657 break; \
658 case OP_NEG: \
659 tcg_gen_xor_i64(xbh, xbh, sgm); \
660 break; \
661 case OP_CPSGN: \
662 xah = tcg_temp_new_i64(); \
663 xa = rA(ctx->opcode) + 32; \
664 get_cpu_vsr(tmp, xa, true); \
665 tcg_gen_and_i64(xah, tmp, sgm); \
666 tcg_gen_andc_i64(xbh, xbh, sgm); \
667 tcg_gen_or_i64(xbh, xbh, xah); \
668 break; \
669 } \
670 set_cpu_vsr(xt, xbh, true); \
671 set_cpu_vsr(xt, xbl, false); \
672 }
673
674 VSX_SCALAR_MOVE_QP(xsabsqp, OP_ABS, SGN_MASK_DP)
675 VSX_SCALAR_MOVE_QP(xsnabsqp, OP_NABS, SGN_MASK_DP)
676 VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP)
677 VSX_SCALAR_MOVE_QP(xscpsgnqp, OP_CPSGN, SGN_MASK_DP)
678
679 #define TCG_OP_IMM_i64(FUNC, OP, IMM) \
680 static void FUNC(TCGv_i64 t, TCGv_i64 b) \
681 { \
682 OP(t, b, IMM); \
683 }
684
685 TCG_OP_IMM_i64(do_xvabssp_i64, tcg_gen_andi_i64, ~SGN_MASK_SP)
686 TCG_OP_IMM_i64(do_xvnabssp_i64, tcg_gen_ori_i64, SGN_MASK_SP)
687 TCG_OP_IMM_i64(do_xvnegsp_i64, tcg_gen_xori_i64, SGN_MASK_SP)
688 TCG_OP_IMM_i64(do_xvabsdp_i64, tcg_gen_andi_i64, ~SGN_MASK_DP)
689 TCG_OP_IMM_i64(do_xvnabsdp_i64, tcg_gen_ori_i64, SGN_MASK_DP)
690 TCG_OP_IMM_i64(do_xvnegdp_i64, tcg_gen_xori_i64, SGN_MASK_DP)
691 #undef TCG_OP_IMM_i64
692
693 static void xv_msb_op1(unsigned vece, TCGv_vec t, TCGv_vec b,
694 void (*tcg_gen_op_vec)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
695 {
696 uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
697 tcg_gen_op_vec(vece, t, b, tcg_constant_vec_matching(t, vece, msb));
698 }
699
700 static void do_xvabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
701 {
702 xv_msb_op1(vece, t, b, tcg_gen_andc_vec);
703 }
704
705 static void do_xvnabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
706 {
707 xv_msb_op1(vece, t, b, tcg_gen_or_vec);
708 }
709
710 static void do_xvneg_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
711 {
712 xv_msb_op1(vece, t, b, tcg_gen_xor_vec);
713 }
714
715 static bool do_vsx_msb_op(DisasContext *ctx, arg_XX2 *a, unsigned vece,
716 void (*vec)(unsigned, TCGv_vec, TCGv_vec),
717 void (*i64)(TCGv_i64, TCGv_i64))
718 {
719 static const TCGOpcode vecop_list[] = {
720 0
721 };
722
723 const GVecGen2 op = {
724 .fni8 = i64,
725 .fniv = vec,
726 .opt_opc = vecop_list,
727 .vece = vece
728 };
729
730 REQUIRE_INSNS_FLAGS2(ctx, VSX);
731 REQUIRE_VSX(ctx);
732
733 tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
734 16, 16, &op);
735
736 return true;
737 }
738
739 TRANS(XVABSDP, do_vsx_msb_op, MO_64, do_xvabs_vec, do_xvabsdp_i64)
740 TRANS(XVNABSDP, do_vsx_msb_op, MO_64, do_xvnabs_vec, do_xvnabsdp_i64)
741 TRANS(XVNEGDP, do_vsx_msb_op, MO_64, do_xvneg_vec, do_xvnegdp_i64)
742 TRANS(XVABSSP, do_vsx_msb_op, MO_32, do_xvabs_vec, do_xvabssp_i64)
743 TRANS(XVNABSSP, do_vsx_msb_op, MO_32, do_xvnabs_vec, do_xvnabssp_i64)
744 TRANS(XVNEGSP, do_vsx_msb_op, MO_32, do_xvneg_vec, do_xvnegsp_i64)
745
746 static void do_xvcpsgndp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
747 {
748 tcg_gen_andi_i64(a, a, SGN_MASK_DP);
749 tcg_gen_andi_i64(b, b, ~SGN_MASK_DP);
750 tcg_gen_or_i64(t, a, b);
751 }
752
753 static void do_xvcpsgnsp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
754 {
755 tcg_gen_andi_i64(a, a, SGN_MASK_SP);
756 tcg_gen_andi_i64(b, b, ~SGN_MASK_SP);
757 tcg_gen_or_i64(t, a, b);
758 }
759
760 static void do_xvcpsgn_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
761 {
762 uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
763 tcg_gen_bitsel_vec(vece, t, tcg_constant_vec_matching(t, vece, msb), a, b);
764 }
765
766 static bool do_xvcpsgn(DisasContext *ctx, arg_XX3 *a, unsigned vece)
767 {
768 static const TCGOpcode vecop_list[] = {
769 0
770 };
771
772 static const GVecGen3 op[] = {
773 {
774 .fni8 = do_xvcpsgnsp_i64,
775 .fniv = do_xvcpsgn_vec,
776 .opt_opc = vecop_list,
777 .vece = MO_32
778 },
779 {
780 .fni8 = do_xvcpsgndp_i64,
781 .fniv = do_xvcpsgn_vec,
782 .opt_opc = vecop_list,
783 .vece = MO_64
784 },
785 };
786
787 REQUIRE_INSNS_FLAGS2(ctx, VSX);
788 REQUIRE_VSX(ctx);
789
790 tcg_gen_gvec_3(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
791 vsr_full_offset(a->xb), 16, 16, &op[vece - MO_32]);
792
793 return true;
794 }
795
796 TRANS(XVCPSGNSP, do_xvcpsgn, MO_32)
797 TRANS(XVCPSGNDP, do_xvcpsgn, MO_64)
798
799 static bool do_cmp(DisasContext *ctx, arg_XX3_rc *a,
800 void (*helper)(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
801 {
802 TCGv_i32 dest;
803 TCGv_ptr xt, xa, xb;
804 REQUIRE_VSX(ctx);
805 xt = gen_vsr_ptr(a->xt);
806 xa = gen_vsr_ptr(a->xa);
807 xb = gen_vsr_ptr(a->xb);
808 dest = a->rc ? cpu_crf[6] : tcg_temp_new_i32();
809 helper(dest, tcg_env, xt, xa, xb);
810 return true;
811 }
812
813 TRANS_FLAGS2(VSX, XVCMPEQSP, do_cmp, gen_helper_XVCMPEQSP);
814 TRANS_FLAGS2(VSX, XVCMPGTSP, do_cmp, gen_helper_XVCMPGTSP);
815 TRANS_FLAGS2(VSX, XVCMPGESP, do_cmp, gen_helper_XVCMPGESP);
816 TRANS_FLAGS2(ISA300, XVCMPNESP, do_cmp, gen_helper_XVCMPNESP);
817 TRANS_FLAGS2(VSX, XVCMPEQDP, do_cmp, gen_helper_XVCMPEQDP);
818 TRANS_FLAGS2(VSX, XVCMPGTDP, do_cmp, gen_helper_XVCMPGTDP);
819 TRANS_FLAGS2(VSX, XVCMPGEDP, do_cmp, gen_helper_XVCMPGEDP);
820 TRANS_FLAGS2(ISA300, XVCMPNEDP, do_cmp, gen_helper_XVCMPNEDP);
821
822 static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a)
823 {
824 TCGv_i32 ro;
825 TCGv_ptr xt, xb;
826
827 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
828 REQUIRE_VSX(ctx);
829
830 ro = tcg_constant_i32(a->rc);
831
832 xt = gen_avr_ptr(a->rt);
833 xb = gen_avr_ptr(a->rb);
834 gen_helper_XSCVQPDP(tcg_env, ro, xt, xb);
835 return true;
836 }
837
838 static bool do_helper_env_X_tb(DisasContext *ctx, arg_X_tb *a,
839 void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
840 {
841 TCGv_ptr xt, xb;
842
843 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
844 REQUIRE_VSX(ctx);
845
846 xt = gen_avr_ptr(a->rt);
847 xb = gen_avr_ptr(a->rb);
848 gen_helper(tcg_env, xt, xb);
849 return true;
850 }
851
852 TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP)
853 TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP)
854 TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ)
855 TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ)
856
857 #define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \
858 static void gen_##name(DisasContext *ctx) \
859 { \
860 TCGv_i32 opc; \
861 if (unlikely(!ctx->vsx_enabled)) { \
862 gen_exception(ctx, POWERPC_EXCP_VSXU); \
863 return; \
864 } \
865 opc = tcg_constant_i32(ctx->opcode); \
866 gen_helper_##name(tcg_env, opc); \
867 }
868
869 #define GEN_VSX_HELPER_X2(name, op1, op2, inval, type) \
870 static void gen_##name(DisasContext *ctx) \
871 { \
872 TCGv_ptr xt, xb; \
873 if (unlikely(!ctx->vsx_enabled)) { \
874 gen_exception(ctx, POWERPC_EXCP_VSXU); \
875 return; \
876 } \
877 xt = gen_vsr_ptr(xT(ctx->opcode)); \
878 xb = gen_vsr_ptr(xB(ctx->opcode)); \
879 gen_helper_##name(tcg_env, xt, xb); \
880 }
881
882 #define GEN_VSX_HELPER_X2_AB(name, op1, op2, inval, type) \
883 static void gen_##name(DisasContext *ctx) \
884 { \
885 TCGv_i32 opc; \
886 TCGv_ptr xa, xb; \
887 if (unlikely(!ctx->vsx_enabled)) { \
888 gen_exception(ctx, POWERPC_EXCP_VSXU); \
889 return; \
890 } \
891 opc = tcg_constant_i32(ctx->opcode); \
892 xa = gen_vsr_ptr(xA(ctx->opcode)); \
893 xb = gen_vsr_ptr(xB(ctx->opcode)); \
894 gen_helper_##name(tcg_env, opc, xa, xb); \
895 }
896
897 #define GEN_VSX_HELPER_X1(name, op1, op2, inval, type) \
898 static void gen_##name(DisasContext *ctx) \
899 { \
900 TCGv_i32 opc; \
901 TCGv_ptr xb; \
902 if (unlikely(!ctx->vsx_enabled)) { \
903 gen_exception(ctx, POWERPC_EXCP_VSXU); \
904 return; \
905 } \
906 opc = tcg_constant_i32(ctx->opcode); \
907 xb = gen_vsr_ptr(xB(ctx->opcode)); \
908 gen_helper_##name(tcg_env, opc, xb); \
909 }
910
911 #define GEN_VSX_HELPER_R3(name, op1, op2, inval, type) \
912 static void gen_##name(DisasContext *ctx) \
913 { \
914 TCGv_i32 opc; \
915 TCGv_ptr xt, xa, xb; \
916 if (unlikely(!ctx->vsx_enabled)) { \
917 gen_exception(ctx, POWERPC_EXCP_VSXU); \
918 return; \
919 } \
920 opc = tcg_constant_i32(ctx->opcode); \
921 xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \
922 xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \
923 xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
924 gen_helper_##name(tcg_env, opc, xt, xa, xb); \
925 }
926
927 #define GEN_VSX_HELPER_R2(name, op1, op2, inval, type) \
928 static void gen_##name(DisasContext *ctx) \
929 { \
930 TCGv_i32 opc; \
931 TCGv_ptr xt, xb; \
932 if (unlikely(!ctx->vsx_enabled)) { \
933 gen_exception(ctx, POWERPC_EXCP_VSXU); \
934 return; \
935 } \
936 opc = tcg_constant_i32(ctx->opcode); \
937 xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \
938 xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
939 gen_helper_##name(tcg_env, opc, xt, xb); \
940 }
941
942 #define GEN_VSX_HELPER_R2_AB(name, op1, op2, inval, type) \
943 static void gen_##name(DisasContext *ctx) \
944 { \
945 TCGv_i32 opc; \
946 TCGv_ptr xa, xb; \
947 if (unlikely(!ctx->vsx_enabled)) { \
948 gen_exception(ctx, POWERPC_EXCP_VSXU); \
949 return; \
950 } \
951 opc = tcg_constant_i32(ctx->opcode); \
952 xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \
953 xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
954 gen_helper_##name(tcg_env, opc, xa, xb); \
955 }
956
957 #define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
958 static void gen_##name(DisasContext *ctx) \
959 { \
960 TCGv_i64 t0; \
961 TCGv_i64 t1; \
962 if (unlikely(!ctx->vsx_enabled)) { \
963 gen_exception(ctx, POWERPC_EXCP_VSXU); \
964 return; \
965 } \
966 t0 = tcg_temp_new_i64(); \
967 t1 = tcg_temp_new_i64(); \
968 get_cpu_vsr(t0, xB(ctx->opcode), true); \
969 gen_helper_##name(t1, tcg_env, t0); \
970 set_cpu_vsr(xT(ctx->opcode), t1, true); \
971 set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
972 }
973
974 GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300)
975 GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300)
976 GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300)
977 GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
978 GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
979 GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
980 GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
981 GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
982 GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300)
983 GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300)
984 GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
985 GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
986 GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX)
987 GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX)
988 GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300)
989 GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
990 GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
991 GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_ISA207)
992 GEN_VSX_HELPER_R2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300)
993 GEN_VSX_HELPER_R2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300)
994 GEN_VSX_HELPER_R2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300)
995 GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300)
996 GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
997 GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
998 GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
999
1000 /* test if +Inf */
1001 static void gen_is_pos_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1002 {
1003 uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
1004 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1005 tcg_constant_vec_matching(t, vece, exp_msk));
1006 }
1007
1008 /* test if -Inf */
1009 static void gen_is_neg_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1010 {
1011 uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
1012 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1013 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1014 tcg_constant_vec_matching(t, vece, sgn_msk | exp_msk));
1015 }
1016
1017 /* test if +Inf or -Inf */
1018 static void gen_is_any_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1019 {
1020 uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
1021 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1022 tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
1023 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1024 tcg_constant_vec_matching(t, vece, exp_msk));
1025 }
1026
1027 /* test if +0 */
1028 static void gen_is_pos_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1029 {
1030 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1031 tcg_constant_vec_matching(t, vece, 0));
1032 }
1033
1034 /* test if -0 */
1035 static void gen_is_neg_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1036 {
1037 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1038 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1039 tcg_constant_vec_matching(t, vece, sgn_msk));
1040 }
1041
1042 /* test if +0 or -0 */
1043 static void gen_is_any_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1044 {
1045 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1046 tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
1047 tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
1048 tcg_constant_vec_matching(t, vece, 0));
1049 }
1050
1051 /* test if +Denormal */
1052 static void gen_is_pos_denormal(unsigned vece, TCGv_vec t,
1053 TCGv_vec b, int64_t v)
1054 {
1055 uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
1056 tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
1057 tcg_constant_vec_matching(t, vece, frc_msk));
1058 tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
1059 tcg_constant_vec_matching(t, vece, 0));
1060 tcg_gen_and_vec(vece, t, t, b);
1061 }
1062
1063 /* test if -Denormal */
1064 static void gen_is_neg_denormal(unsigned vece, TCGv_vec t,
1065 TCGv_vec b, int64_t v)
1066 {
1067 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1068 uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
1069 tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
1070 tcg_constant_vec_matching(t, vece, sgn_msk | frc_msk));
1071 tcg_gen_cmp_vec(TCG_COND_GTU, vece, b, b,
1072 tcg_constant_vec_matching(t, vece, sgn_msk));
1073 tcg_gen_and_vec(vece, t, t, b);
1074 }
1075
1076 /* test if +Denormal or -Denormal */
1077 static void gen_is_any_denormal(unsigned vece, TCGv_vec t,
1078 TCGv_vec b, int64_t v)
1079 {
1080 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1081 uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
1082 tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
1083 tcg_gen_cmp_vec(TCG_COND_LE, vece, t, b,
1084 tcg_constant_vec_matching(t, vece, frc_msk));
1085 tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
1086 tcg_constant_vec_matching(t, vece, 0));
1087 tcg_gen_and_vec(vece, t, t, b);
1088 }
1089
1090 /* test if NaN */
1091 static void gen_is_nan(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
1092 {
1093 uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
1094 uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
1095 tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
1096 tcg_gen_cmp_vec(TCG_COND_GT, vece, t, b,
1097 tcg_constant_vec_matching(t, vece, exp_msk));
1098 }
1099
1100 static bool do_xvtstdc(DisasContext *ctx, arg_XX2_uim *a, unsigned vece)
1101 {
1102 static const TCGOpcode vecop_list[] = {
1103 INDEX_op_cmp_vec, 0
1104 };
1105
1106 GVecGen2i op = {
1107 .fnoi = (vece == MO_32) ? gen_helper_XVTSTDCSP : gen_helper_XVTSTDCDP,
1108 .vece = vece,
1109 .opt_opc = vecop_list
1110 };
1111
1112 REQUIRE_VSX(ctx);
1113
1114 switch (a->uim) {
1115 case 0:
1116 set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
1117 set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
1118 return true;
1119 case ((1 << 0) | (1 << 1)):
1120 /* test if +Denormal or -Denormal */
1121 op.fniv = gen_is_any_denormal;
1122 break;
1123 case (1 << 0):
1124 /* test if -Denormal */
1125 op.fniv = gen_is_neg_denormal;
1126 break;
1127 case (1 << 1):
1128 /* test if +Denormal */
1129 op.fniv = gen_is_pos_denormal;
1130 break;
1131 case ((1 << 2) | (1 << 3)):
1132 /* test if +0 or -0 */
1133 op.fniv = gen_is_any_zero;
1134 break;
1135 case (1 << 2):
1136 /* test if -0 */
1137 op.fniv = gen_is_neg_zero;
1138 break;
1139 case (1 << 3):
1140 /* test if +0 */
1141 op.fniv = gen_is_pos_zero;
1142 break;
1143 case ((1 << 4) | (1 << 5)):
1144 /* test if +Inf or -Inf */
1145 op.fniv = gen_is_any_inf;
1146 break;
1147 case (1 << 4):
1148 /* test if -Inf */
1149 op.fniv = gen_is_neg_inf;
1150 break;
1151 case (1 << 5):
1152 /* test if +Inf */
1153 op.fniv = gen_is_pos_inf;
1154 break;
1155 case (1 << 6):
1156 /* test if NaN */
1157 op.fniv = gen_is_nan;
1158 break;
1159 }
1160 tcg_gen_gvec_2i(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
1161 16, 16, a->uim, &op);
1162
1163 return true;
1164 }
1165
1166 TRANS_FLAGS2(VSX, XVTSTDCSP, do_xvtstdc, MO_32)
1167 TRANS_FLAGS2(VSX, XVTSTDCDP, do_xvtstdc, MO_64)
1168
1169 static bool do_XX2_bf_uim(DisasContext *ctx, arg_XX2_bf_uim *a, bool vsr,
1170 void (*gen_helper)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_ptr))
1171 {
1172 TCGv_ptr xb;
1173
1174 REQUIRE_VSX(ctx);
1175 xb = vsr ? gen_vsr_ptr(a->xb) : gen_avr_ptr(a->xb);
1176 gen_helper(tcg_env, tcg_constant_i32(a->bf), tcg_constant_i32(a->uim), xb);
1177 return true;
1178 }
1179
1180 TRANS_FLAGS2(ISA300, XSTSTDCSP, do_XX2_bf_uim, true, gen_helper_XSTSTDCSP)
1181 TRANS_FLAGS2(ISA300, XSTSTDCDP, do_XX2_bf_uim, true, gen_helper_XSTSTDCDP)
1182 TRANS_FLAGS2(ISA300, XSTSTDCQP, do_XX2_bf_uim, false, gen_helper_XSTSTDCQP)
1183
1184 bool trans_XSCVSPDPN(DisasContext *ctx, arg_XX2 *a)
1185 {
1186 TCGv_i64 tmp;
1187
1188 REQUIRE_INSNS_FLAGS2(ctx, ISA207);
1189 REQUIRE_VSX(ctx);
1190
1191 tmp = tcg_temp_new_i64();
1192 get_cpu_vsr(tmp, a->xb, true);
1193
1194 gen_helper_XSCVSPDPN(tmp, tmp);
1195
1196 set_cpu_vsr(a->xt, tmp, true);
1197 set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
1198 return true;
1199 }
1200
1201 GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
1202 GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
1203 GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
1204 GEN_VSX_HELPER_X2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
1205 GEN_VSX_HELPER_X2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
1206 GEN_VSX_HELPER_R2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300)
1207 GEN_VSX_HELPER_X2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
1208 GEN_VSX_HELPER_X2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
1209 GEN_VSX_HELPER_X2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
1210 GEN_VSX_HELPER_X2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
1211 GEN_VSX_HELPER_X2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
1212 GEN_VSX_HELPER_X2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
1213 GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_ISA207)
1214 GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300)
1215 GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300)
1216 GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300)
1217 GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300)
1218 GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_ISA207)
1219 GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_ISA207)
1220 GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_ISA207)
1221 GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_ISA207)
1222 GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_ISA207)
1223
1224 GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
1225 GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
1226 GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
1227 GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
1228 GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
1229 GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
1230 GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
1231 GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
1232 GEN_VSX_HELPER_X2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
1233 GEN_VSX_HELPER_X2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
1234 GEN_VSX_HELPER_X2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
1235 GEN_VSX_HELPER_X2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
1236 GEN_VSX_HELPER_X2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
1237 GEN_VSX_HELPER_X2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
1238 GEN_VSX_HELPER_X2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
1239 GEN_VSX_HELPER_X2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
1240 GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
1241 GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
1242 GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
1243
1244 GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
1245 GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
1246 GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
1247 GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
1248 GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
1249 GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
1250 GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300)
1251 GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300)
1252 GEN_VSX_HELPER_X2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
1253 GEN_VSX_HELPER_X2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
1254 GEN_VSX_HELPER_X2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
1255 GEN_VSX_HELPER_X2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
1256 GEN_VSX_HELPER_X2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
1257 GEN_VSX_HELPER_X2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
1258 GEN_VSX_HELPER_X2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
1259 GEN_VSX_HELPER_X2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
1260 GEN_VSX_HELPER_X2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
1261 GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
1262 GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
1263 GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
1264 GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
1265
1266 static bool trans_XXPERM(DisasContext *ctx, arg_XX3 *a)
1267 {
1268 TCGv_ptr xt, xa, xb;
1269
1270 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1271 REQUIRE_VSX(ctx);
1272
1273 xt = gen_vsr_ptr(a->xt);
1274 xa = gen_vsr_ptr(a->xa);
1275 xb = gen_vsr_ptr(a->xb);
1276
1277 gen_helper_VPERM(xt, xa, xt, xb);
1278 return true;
1279 }
1280
1281 static bool trans_XXPERMR(DisasContext *ctx, arg_XX3 *a)
1282 {
1283 TCGv_ptr xt, xa, xb;
1284
1285 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1286 REQUIRE_VSX(ctx);
1287
1288 xt = gen_vsr_ptr(a->xt);
1289 xa = gen_vsr_ptr(a->xa);
1290 xb = gen_vsr_ptr(a->xb);
1291
1292 gen_helper_VPERMR(xt, xa, xt, xb);
1293 return true;
1294 }
1295
1296 static bool trans_XXPERMDI(DisasContext *ctx, arg_XX3_dm *a)
1297 {
1298 TCGv_i64 t0, t1;
1299
1300 REQUIRE_INSNS_FLAGS2(ctx, VSX);
1301 REQUIRE_VSX(ctx);
1302
1303 t0 = tcg_temp_new_i64();
1304
1305 if (unlikely(a->xt == a->xa || a->xt == a->xb)) {
1306 t1 = tcg_temp_new_i64();
1307
1308 get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
1309 get_cpu_vsr(t1, a->xb, (a->dm & 1) == 0);
1310
1311 set_cpu_vsr(a->xt, t0, true);
1312 set_cpu_vsr(a->xt, t1, false);
1313 } else {
1314 get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
1315 set_cpu_vsr(a->xt, t0, true);
1316
1317 get_cpu_vsr(t0, a->xb, (a->dm & 1) == 0);
1318 set_cpu_vsr(a->xt, t0, false);
1319 }
1320 return true;
1321 }
1322
1323 static bool trans_XXPERMX(DisasContext *ctx, arg_8RR_XX4_uim3 *a)
1324 {
1325 TCGv_ptr xt, xa, xb, xc;
1326
1327 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1328 REQUIRE_VSX(ctx);
1329
1330 xt = gen_vsr_ptr(a->xt);
1331 xa = gen_vsr_ptr(a->xa);
1332 xb = gen_vsr_ptr(a->xb);
1333 xc = gen_vsr_ptr(a->xc);
1334
1335 gen_helper_XXPERMX(xt, xa, xb, xc, tcg_constant_tl(a->uim3));
1336 return true;
1337 }
1338
1339 typedef void (*xxgenpcv_genfn)(TCGv_ptr, TCGv_ptr);
1340
1341 static bool do_xxgenpcv(DisasContext *ctx, arg_X_imm5 *a,
1342 const xxgenpcv_genfn fn[4])
1343 {
1344 TCGv_ptr xt, vrb;
1345
1346 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1347 REQUIRE_VSX(ctx);
1348
1349 if (a->imm & ~0x3) {
1350 gen_invalid(ctx);
1351 return true;
1352 }
1353
1354 xt = gen_vsr_ptr(a->xt);
1355 vrb = gen_avr_ptr(a->vrb);
1356
1357 fn[a->imm](xt, vrb);
1358 return true;
1359 }
1360
1361 #define XXGENPCV(NAME) \
1362 static bool trans_##NAME(DisasContext *ctx, arg_X_imm5 *a) \
1363 { \
1364 static const xxgenpcv_genfn fn[4] = { \
1365 gen_helper_##NAME##_be_exp, \
1366 gen_helper_##NAME##_be_comp, \
1367 gen_helper_##NAME##_le_exp, \
1368 gen_helper_##NAME##_le_comp, \
1369 }; \
1370 return do_xxgenpcv(ctx, a, fn); \
1371 }
1372
1373 XXGENPCV(XXGENPCVBM)
1374 XXGENPCV(XXGENPCVHM)
1375 XXGENPCV(XXGENPCVWM)
1376 XXGENPCV(XXGENPCVDM)
1377 #undef XXGENPCV
1378
1379 static bool do_xsmadd(DisasContext *ctx, int tgt, int src1, int src2, int src3,
1380 void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
1381 {
1382 TCGv_ptr t, s1, s2, s3;
1383
1384 t = gen_vsr_ptr(tgt);
1385 s1 = gen_vsr_ptr(src1);
1386 s2 = gen_vsr_ptr(src2);
1387 s3 = gen_vsr_ptr(src3);
1388
1389 gen_helper(tcg_env, t, s1, s2, s3);
1390 return true;
1391 }
1392
1393 static bool do_xsmadd_XX3(DisasContext *ctx, arg_XX3 *a, bool type_a,
1394 void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
1395 {
1396 REQUIRE_VSX(ctx);
1397
1398 if (type_a) {
1399 return do_xsmadd(ctx, a->xt, a->xa, a->xt, a->xb, gen_helper);
1400 }
1401 return do_xsmadd(ctx, a->xt, a->xa, a->xb, a->xt, gen_helper);
1402 }
1403
1404 TRANS_FLAGS2(VSX, XSMADDADP, do_xsmadd_XX3, true, gen_helper_XSMADDDP)
1405 TRANS_FLAGS2(VSX, XSMADDMDP, do_xsmadd_XX3, false, gen_helper_XSMADDDP)
1406 TRANS_FLAGS2(VSX, XSMSUBADP, do_xsmadd_XX3, true, gen_helper_XSMSUBDP)
1407 TRANS_FLAGS2(VSX, XSMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSMSUBDP)
1408 TRANS_FLAGS2(VSX, XSNMADDADP, do_xsmadd_XX3, true, gen_helper_XSNMADDDP)
1409 TRANS_FLAGS2(VSX, XSNMADDMDP, do_xsmadd_XX3, false, gen_helper_XSNMADDDP)
1410 TRANS_FLAGS2(VSX, XSNMSUBADP, do_xsmadd_XX3, true, gen_helper_XSNMSUBDP)
1411 TRANS_FLAGS2(VSX, XSNMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSNMSUBDP)
1412 TRANS_FLAGS2(ISA207, XSMADDASP, do_xsmadd_XX3, true, gen_helper_XSMADDSP)
1413 TRANS_FLAGS2(ISA207, XSMADDMSP, do_xsmadd_XX3, false, gen_helper_XSMADDSP)
1414 TRANS_FLAGS2(ISA207, XSMSUBASP, do_xsmadd_XX3, true, gen_helper_XSMSUBSP)
1415 TRANS_FLAGS2(ISA207, XSMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSMSUBSP)
1416 TRANS_FLAGS2(ISA207, XSNMADDASP, do_xsmadd_XX3, true, gen_helper_XSNMADDSP)
1417 TRANS_FLAGS2(ISA207, XSNMADDMSP, do_xsmadd_XX3, false, gen_helper_XSNMADDSP)
1418 TRANS_FLAGS2(ISA207, XSNMSUBASP, do_xsmadd_XX3, true, gen_helper_XSNMSUBSP)
1419 TRANS_FLAGS2(ISA207, XSNMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSNMSUBSP)
1420
1421 static bool do_xsmadd_X(DisasContext *ctx, arg_X_rc *a,
1422 void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr),
1423 void (*gen_helper_ro)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
1424 {
1425 int vrt, vra, vrb;
1426
1427 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1428 REQUIRE_VSX(ctx);
1429
1430 vrt = a->rt + 32;
1431 vra = a->ra + 32;
1432 vrb = a->rb + 32;
1433
1434 if (a->rc) {
1435 return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper_ro);
1436 }
1437
1438 return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper);
1439 }
1440
1441 TRANS(XSMADDQP, do_xsmadd_X, gen_helper_XSMADDQP, gen_helper_XSMADDQPO)
1442 TRANS(XSMSUBQP, do_xsmadd_X, gen_helper_XSMSUBQP, gen_helper_XSMSUBQPO)
1443 TRANS(XSNMADDQP, do_xsmadd_X, gen_helper_XSNMADDQP, gen_helper_XSNMADDQPO)
1444 TRANS(XSNMSUBQP, do_xsmadd_X, gen_helper_XSNMSUBQP, gen_helper_XSNMSUBQPO)
1445
1446 #define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type) \
1447 static void gen_##name(DisasContext *ctx) \
1448 { \
1449 TCGv_ptr xt, s1, s2, s3; \
1450 if (unlikely(!ctx->vsx_enabled)) { \
1451 gen_exception(ctx, POWERPC_EXCP_VSXU); \
1452 return; \
1453 } \
1454 xt = gen_vsr_ptr(xT(ctx->opcode)); \
1455 s1 = gen_vsr_ptr(xA(ctx->opcode)); \
1456 if (ctx->opcode & PPC_BIT32(25)) { \
1457 /* \
1458 * AxT + B \
1459 */ \
1460 s2 = gen_vsr_ptr(xB(ctx->opcode)); \
1461 s3 = gen_vsr_ptr(xT(ctx->opcode)); \
1462 } else { \
1463 /* \
1464 * AxB + T \
1465 */ \
1466 s2 = gen_vsr_ptr(xT(ctx->opcode)); \
1467 s3 = gen_vsr_ptr(xB(ctx->opcode)); \
1468 } \
1469 gen_helper_##name(tcg_env, xt, s1, s2, s3); \
1470 }
1471
1472 GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX)
1473 GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX)
1474 GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX)
1475 GEN_VSX_HELPER_VSX_MADD(xvnmsubdp, 0x04, 0x1E, 0x1F, 0, PPC2_VSX)
1476 GEN_VSX_HELPER_VSX_MADD(xvmaddsp, 0x04, 0x08, 0x09, 0, PPC2_VSX)
1477 GEN_VSX_HELPER_VSX_MADD(xvmsubsp, 0x04, 0x0A, 0x0B, 0, PPC2_VSX)
1478 GEN_VSX_HELPER_VSX_MADD(xvnmaddsp, 0x04, 0x18, 0x19, 0, PPC2_VSX)
1479 GEN_VSX_HELPER_VSX_MADD(xvnmsubsp, 0x04, 0x1A, 0x1B, 0, PPC2_VSX)
1480
1481 static void gen_xxbrd(DisasContext *ctx)
1482 {
1483 TCGv_i64 xth;
1484 TCGv_i64 xtl;
1485 TCGv_i64 xbh;
1486 TCGv_i64 xbl;
1487
1488 if (unlikely(!ctx->vsx_enabled)) {
1489 gen_exception(ctx, POWERPC_EXCP_VSXU);
1490 return;
1491 }
1492 xth = tcg_temp_new_i64();
1493 xtl = tcg_temp_new_i64();
1494 xbh = tcg_temp_new_i64();
1495 xbl = tcg_temp_new_i64();
1496 get_cpu_vsr(xbh, xB(ctx->opcode), true);
1497 get_cpu_vsr(xbl, xB(ctx->opcode), false);
1498
1499 tcg_gen_bswap64_i64(xth, xbh);
1500 tcg_gen_bswap64_i64(xtl, xbl);
1501 set_cpu_vsr(xT(ctx->opcode), xth, true);
1502 set_cpu_vsr(xT(ctx->opcode), xtl, false);
1503 }
1504
1505 static void gen_xxbrh(DisasContext *ctx)
1506 {
1507 TCGv_i64 xth;
1508 TCGv_i64 xtl;
1509 TCGv_i64 xbh;
1510 TCGv_i64 xbl;
1511
1512 if (unlikely(!ctx->vsx_enabled)) {
1513 gen_exception(ctx, POWERPC_EXCP_VSXU);
1514 return;
1515 }
1516 xth = tcg_temp_new_i64();
1517 xtl = tcg_temp_new_i64();
1518 xbh = tcg_temp_new_i64();
1519 xbl = tcg_temp_new_i64();
1520 get_cpu_vsr(xbh, xB(ctx->opcode), true);
1521 get_cpu_vsr(xbl, xB(ctx->opcode), false);
1522
1523 gen_bswap16x8(xth, xtl, xbh, xbl);
1524 set_cpu_vsr(xT(ctx->opcode), xth, true);
1525 set_cpu_vsr(xT(ctx->opcode), xtl, false);
1526 }
1527
1528 static void gen_xxbrq(DisasContext *ctx)
1529 {
1530 TCGv_i64 xth;
1531 TCGv_i64 xtl;
1532 TCGv_i64 xbh;
1533 TCGv_i64 xbl;
1534 TCGv_i64 t0;
1535
1536 if (unlikely(!ctx->vsx_enabled)) {
1537 gen_exception(ctx, POWERPC_EXCP_VSXU);
1538 return;
1539 }
1540 xth = tcg_temp_new_i64();
1541 xtl = tcg_temp_new_i64();
1542 xbh = tcg_temp_new_i64();
1543 xbl = tcg_temp_new_i64();
1544 get_cpu_vsr(xbh, xB(ctx->opcode), true);
1545 get_cpu_vsr(xbl, xB(ctx->opcode), false);
1546 t0 = tcg_temp_new_i64();
1547
1548 tcg_gen_bswap64_i64(t0, xbl);
1549 tcg_gen_bswap64_i64(xtl, xbh);
1550 set_cpu_vsr(xT(ctx->opcode), xtl, false);
1551 tcg_gen_mov_i64(xth, t0);
1552 set_cpu_vsr(xT(ctx->opcode), xth, true);
1553 }
1554
1555 static void gen_xxbrw(DisasContext *ctx)
1556 {
1557 TCGv_i64 xth;
1558 TCGv_i64 xtl;
1559 TCGv_i64 xbh;
1560 TCGv_i64 xbl;
1561
1562 if (unlikely(!ctx->vsx_enabled)) {
1563 gen_exception(ctx, POWERPC_EXCP_VSXU);
1564 return;
1565 }
1566 xth = tcg_temp_new_i64();
1567 xtl = tcg_temp_new_i64();
1568 xbh = tcg_temp_new_i64();
1569 xbl = tcg_temp_new_i64();
1570 get_cpu_vsr(xbh, xB(ctx->opcode), true);
1571 get_cpu_vsr(xbl, xB(ctx->opcode), false);
1572
1573 gen_bswap32x4(xth, xtl, xbh, xbl);
1574 set_cpu_vsr(xT(ctx->opcode), xth, true);
1575 set_cpu_vsr(xT(ctx->opcode), xtl, false);
1576 }
1577
1578 static bool do_logical_op(DisasContext *ctx, arg_XX3 *a, unsigned vece,
1579 void (*helper)(unsigned, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t))
1580 {
1581 REQUIRE_VSX(ctx);
1582 helper(vece, vsr_full_offset(a->xt),
1583 vsr_full_offset(a->xa),
1584 vsr_full_offset(a->xb), 16, 16);
1585 return true;
1586 }
1587
1588 TRANS_FLAGS2(VSX, XXLAND, do_logical_op, MO_64, tcg_gen_gvec_and);
1589 TRANS_FLAGS2(VSX, XXLANDC, do_logical_op, MO_64, tcg_gen_gvec_andc);
1590 TRANS_FLAGS2(VSX, XXLOR, do_logical_op, MO_64, tcg_gen_gvec_or);
1591 TRANS_FLAGS2(VSX, XXLXOR, do_logical_op, MO_64, tcg_gen_gvec_xor);
1592 TRANS_FLAGS2(VSX, XXLNOR, do_logical_op, MO_64, tcg_gen_gvec_nor);
1593 TRANS_FLAGS2(ISA207, XXLEQV, do_logical_op, MO_64, tcg_gen_gvec_eqv);
1594 TRANS_FLAGS2(ISA207, XXLNAND, do_logical_op, MO_64, tcg_gen_gvec_nand);
1595 TRANS_FLAGS2(ISA207, XXLORC, do_logical_op, MO_64, tcg_gen_gvec_orc);
1596
1597 #define VSX_XXMRG(name, high) \
1598 static void glue(gen_, name)(DisasContext *ctx) \
1599 { \
1600 TCGv_i64 a0, a1, b0, b1, tmp; \
1601 if (unlikely(!ctx->vsx_enabled)) { \
1602 gen_exception(ctx, POWERPC_EXCP_VSXU); \
1603 return; \
1604 } \
1605 a0 = tcg_temp_new_i64(); \
1606 a1 = tcg_temp_new_i64(); \
1607 b0 = tcg_temp_new_i64(); \
1608 b1 = tcg_temp_new_i64(); \
1609 tmp = tcg_temp_new_i64(); \
1610 get_cpu_vsr(a0, xA(ctx->opcode), high); \
1611 get_cpu_vsr(a1, xA(ctx->opcode), high); \
1612 get_cpu_vsr(b0, xB(ctx->opcode), high); \
1613 get_cpu_vsr(b1, xB(ctx->opcode), high); \
1614 tcg_gen_shri_i64(a0, a0, 32); \
1615 tcg_gen_shri_i64(b0, b0, 32); \
1616 tcg_gen_deposit_i64(tmp, b0, a0, 32, 32); \
1617 set_cpu_vsr(xT(ctx->opcode), tmp, true); \
1618 tcg_gen_deposit_i64(tmp, b1, a1, 32, 32); \
1619 set_cpu_vsr(xT(ctx->opcode), tmp, false); \
1620 }
1621
1622 VSX_XXMRG(xxmrghw, 1)
1623 VSX_XXMRG(xxmrglw, 0)
1624
1625 static bool trans_XXSEL(DisasContext *ctx, arg_XX4 *a)
1626 {
1627 REQUIRE_INSNS_FLAGS2(ctx, VSX);
1628 REQUIRE_VSX(ctx);
1629
1630 tcg_gen_gvec_bitsel(MO_64, vsr_full_offset(a->xt), vsr_full_offset(a->xc),
1631 vsr_full_offset(a->xb), vsr_full_offset(a->xa), 16, 16);
1632
1633 return true;
1634 }
1635
1636 static bool trans_XXSPLTW(DisasContext *ctx, arg_XX2_uim *a)
1637 {
1638 int tofs, bofs;
1639
1640 REQUIRE_VSX(ctx);
1641
1642 tofs = vsr_full_offset(a->xt);
1643 bofs = vsr_full_offset(a->xb);
1644 bofs += a->uim << MO_32;
1645 #if !HOST_BIG_ENDIAN
1646 bofs ^= 8 | 4;
1647 #endif
1648
1649 tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
1650 return true;
1651 }
1652
1653 #define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
1654
1655 static bool trans_XXSPLTIB(DisasContext *ctx, arg_X_imm8 *a)
1656 {
1657 if (a->xt < 32) {
1658 REQUIRE_VSX(ctx);
1659 } else {
1660 REQUIRE_VECTOR(ctx);
1661 }
1662 tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(a->xt), 16, 16, a->imm);
1663 return true;
1664 }
1665
1666 static bool trans_XXSPLTIW(DisasContext *ctx, arg_8RR_D *a)
1667 {
1668 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1669 REQUIRE_VSX(ctx);
1670
1671 tcg_gen_gvec_dup_imm(MO_32, vsr_full_offset(a->xt), 16, 16, a->si);
1672
1673 return true;
1674 }
1675
1676 static bool trans_XXSPLTIDP(DisasContext *ctx, arg_8RR_D *a)
1677 {
1678 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1679 REQUIRE_VSX(ctx);
1680
1681 tcg_gen_gvec_dup_imm(MO_64, vsr_full_offset(a->xt), 16, 16,
1682 helper_todouble(a->si));
1683 return true;
1684 }
1685
1686 static bool trans_XXSPLTI32DX(DisasContext *ctx, arg_8RR_D_IX *a)
1687 {
1688 TCGv_i32 imm;
1689
1690 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1691 REQUIRE_VSX(ctx);
1692
1693 imm = tcg_constant_i32(a->si);
1694
1695 tcg_gen_st_i32(imm, tcg_env,
1696 offsetof(CPUPPCState, vsr[a->xt].VsrW(0 + a->ix)));
1697 tcg_gen_st_i32(imm, tcg_env,
1698 offsetof(CPUPPCState, vsr[a->xt].VsrW(2 + a->ix)));
1699
1700 return true;
1701 }
1702
1703 static bool trans_LXVKQ(DisasContext *ctx, arg_X_uim5 *a)
1704 {
1705 static const uint64_t values[32] = {
1706 0, /* Unspecified */
1707 0x3FFF000000000000llu, /* QP +1.0 */
1708 0x4000000000000000llu, /* QP +2.0 */
1709 0x4000800000000000llu, /* QP +3.0 */
1710 0x4001000000000000llu, /* QP +4.0 */
1711 0x4001400000000000llu, /* QP +5.0 */
1712 0x4001800000000000llu, /* QP +6.0 */
1713 0x4001C00000000000llu, /* QP +7.0 */
1714 0x7FFF000000000000llu, /* QP +Inf */
1715 0x7FFF800000000000llu, /* QP dQNaN */
1716 0, /* Unspecified */
1717 0, /* Unspecified */
1718 0, /* Unspecified */
1719 0, /* Unspecified */
1720 0, /* Unspecified */
1721 0, /* Unspecified */
1722 0x8000000000000000llu, /* QP -0.0 */
1723 0xBFFF000000000000llu, /* QP -1.0 */
1724 0xC000000000000000llu, /* QP -2.0 */
1725 0xC000800000000000llu, /* QP -3.0 */
1726 0xC001000000000000llu, /* QP -4.0 */
1727 0xC001400000000000llu, /* QP -5.0 */
1728 0xC001800000000000llu, /* QP -6.0 */
1729 0xC001C00000000000llu, /* QP -7.0 */
1730 0xFFFF000000000000llu, /* QP -Inf */
1731 };
1732
1733 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1734 REQUIRE_VSX(ctx);
1735
1736 if (values[a->uim]) {
1737 set_cpu_vsr(a->xt, tcg_constant_i64(0x0), false);
1738 set_cpu_vsr(a->xt, tcg_constant_i64(values[a->uim]), true);
1739 } else {
1740 gen_invalid(ctx);
1741 }
1742
1743 return true;
1744 }
1745
1746 static bool trans_XVTLSBB(DisasContext *ctx, arg_XX2_bf_xb *a)
1747 {
1748 TCGv_i64 xb, t0, t1, all_true, all_false, mask, zero;
1749
1750 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1751 REQUIRE_VSX(ctx);
1752
1753 xb = tcg_temp_new_i64();
1754 t0 = tcg_temp_new_i64();
1755 t1 = tcg_temp_new_i64();
1756 all_true = tcg_temp_new_i64();
1757 all_false = tcg_temp_new_i64();
1758 mask = tcg_constant_i64(dup_const(MO_8, 1));
1759 zero = tcg_constant_i64(0);
1760
1761 get_cpu_vsr(xb, a->xb, true);
1762 tcg_gen_and_i64(t0, mask, xb);
1763 get_cpu_vsr(xb, a->xb, false);
1764 tcg_gen_and_i64(t1, mask, xb);
1765
1766 tcg_gen_or_i64(all_false, t0, t1);
1767 tcg_gen_and_i64(all_true, t0, t1);
1768
1769 tcg_gen_setcond_i64(TCG_COND_EQ, all_false, all_false, zero);
1770 tcg_gen_shli_i64(all_false, all_false, 1);
1771 tcg_gen_setcond_i64(TCG_COND_EQ, all_true, all_true, mask);
1772 tcg_gen_shli_i64(all_true, all_true, 3);
1773
1774 tcg_gen_or_i64(t0, all_false, all_true);
1775 tcg_gen_extrl_i64_i32(cpu_crf[a->bf], t0);
1776 return true;
1777 }
1778
1779 static void gen_xxsldwi(DisasContext *ctx)
1780 {
1781 TCGv_i64 xth, xtl;
1782 if (unlikely(!ctx->vsx_enabled)) {
1783 gen_exception(ctx, POWERPC_EXCP_VSXU);
1784 return;
1785 }
1786 xth = tcg_temp_new_i64();
1787 xtl = tcg_temp_new_i64();
1788
1789 switch (SHW(ctx->opcode)) {
1790 case 0: {
1791 get_cpu_vsr(xth, xA(ctx->opcode), true);
1792 get_cpu_vsr(xtl, xA(ctx->opcode), false);
1793 break;
1794 }
1795 case 1: {
1796 TCGv_i64 t0 = tcg_temp_new_i64();
1797 get_cpu_vsr(xth, xA(ctx->opcode), true);
1798 tcg_gen_shli_i64(xth, xth, 32);
1799 get_cpu_vsr(t0, xA(ctx->opcode), false);
1800 tcg_gen_shri_i64(t0, t0, 32);
1801 tcg_gen_or_i64(xth, xth, t0);
1802 get_cpu_vsr(xtl, xA(ctx->opcode), false);
1803 tcg_gen_shli_i64(xtl, xtl, 32);
1804 get_cpu_vsr(t0, xB(ctx->opcode), true);
1805 tcg_gen_shri_i64(t0, t0, 32);
1806 tcg_gen_or_i64(xtl, xtl, t0);
1807 break;
1808 }
1809 case 2: {
1810 get_cpu_vsr(xth, xA(ctx->opcode), false);
1811 get_cpu_vsr(xtl, xB(ctx->opcode), true);
1812 break;
1813 }
1814 case 3: {
1815 TCGv_i64 t0 = tcg_temp_new_i64();
1816 get_cpu_vsr(xth, xA(ctx->opcode), false);
1817 tcg_gen_shli_i64(xth, xth, 32);
1818 get_cpu_vsr(t0, xB(ctx->opcode), true);
1819 tcg_gen_shri_i64(t0, t0, 32);
1820 tcg_gen_or_i64(xth, xth, t0);
1821 get_cpu_vsr(xtl, xB(ctx->opcode), true);
1822 tcg_gen_shli_i64(xtl, xtl, 32);
1823 get_cpu_vsr(t0, xB(ctx->opcode), false);
1824 tcg_gen_shri_i64(t0, t0, 32);
1825 tcg_gen_or_i64(xtl, xtl, t0);
1826 break;
1827 }
1828 }
1829
1830 set_cpu_vsr(xT(ctx->opcode), xth, true);
1831 set_cpu_vsr(xT(ctx->opcode), xtl, false);
1832 }
1833
1834 static bool do_vsx_extract_insert(DisasContext *ctx, arg_XX2_uim *a,
1835 void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i32))
1836 {
1837 TCGv_i64 zero = tcg_constant_i64(0);
1838 TCGv_ptr xt, xb;
1839
1840 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1841 REQUIRE_VSX(ctx);
1842
1843 /*
1844 * uim > 15 out of bound and for
1845 * uim > 12 handle as per hardware in helper
1846 */
1847 if (a->uim > 15) {
1848 set_cpu_vsr(a->xt, zero, true);
1849 set_cpu_vsr(a->xt, zero, false);
1850 } else {
1851 xt = gen_vsr_ptr(a->xt);
1852 xb = gen_vsr_ptr(a->xb);
1853 gen_helper(xt, xb, tcg_constant_i32(a->uim));
1854 }
1855 return true;
1856 }
1857
1858 TRANS(XXEXTRACTUW, do_vsx_extract_insert, gen_helper_XXEXTRACTUW)
1859 TRANS(XXINSERTW, do_vsx_extract_insert, gen_helper_XXINSERTW)
1860
1861 #ifdef TARGET_PPC64
1862 static void gen_xsxexpdp(DisasContext *ctx)
1863 {
1864 TCGv rt = cpu_gpr[rD(ctx->opcode)];
1865 TCGv_i64 t0;
1866 if (unlikely(!ctx->vsx_enabled)) {
1867 gen_exception(ctx, POWERPC_EXCP_VSXU);
1868 return;
1869 }
1870 t0 = tcg_temp_new_i64();
1871 get_cpu_vsr(t0, xB(ctx->opcode), true);
1872 tcg_gen_extract_i64(rt, t0, 52, 11);
1873 }
1874
1875 static void gen_xsxexpqp(DisasContext *ctx)
1876 {
1877 TCGv_i64 xth;
1878 TCGv_i64 xtl;
1879 TCGv_i64 xbh;
1880
1881 if (unlikely(!ctx->vsx_enabled)) {
1882 gen_exception(ctx, POWERPC_EXCP_VSXU);
1883 return;
1884 }
1885 xth = tcg_temp_new_i64();
1886 xtl = tcg_temp_new_i64();
1887 xbh = tcg_temp_new_i64();
1888 get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
1889
1890 tcg_gen_extract_i64(xth, xbh, 48, 15);
1891 set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
1892 tcg_gen_movi_i64(xtl, 0);
1893 set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
1894 }
1895
1896 static void gen_xsiexpdp(DisasContext *ctx)
1897 {
1898 TCGv_i64 xth;
1899 TCGv ra = cpu_gpr[rA(ctx->opcode)];
1900 TCGv rb = cpu_gpr[rB(ctx->opcode)];
1901 TCGv_i64 t0;
1902
1903 if (unlikely(!ctx->vsx_enabled)) {
1904 gen_exception(ctx, POWERPC_EXCP_VSXU);
1905 return;
1906 }
1907 t0 = tcg_temp_new_i64();
1908 xth = tcg_temp_new_i64();
1909 tcg_gen_andi_i64(xth, ra, 0x800FFFFFFFFFFFFF);
1910 tcg_gen_andi_i64(t0, rb, 0x7FF);
1911 tcg_gen_shli_i64(t0, t0, 52);
1912 tcg_gen_or_i64(xth, xth, t0);
1913 set_cpu_vsr(xT(ctx->opcode), xth, true);
1914 set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false);
1915 }
1916
1917 static void gen_xsiexpqp(DisasContext *ctx)
1918 {
1919 TCGv_i64 xth;
1920 TCGv_i64 xtl;
1921 TCGv_i64 xah;
1922 TCGv_i64 xal;
1923 TCGv_i64 xbh;
1924 TCGv_i64 t0;
1925
1926 if (unlikely(!ctx->vsx_enabled)) {
1927 gen_exception(ctx, POWERPC_EXCP_VSXU);
1928 return;
1929 }
1930 xth = tcg_temp_new_i64();
1931 xtl = tcg_temp_new_i64();
1932 xah = tcg_temp_new_i64();
1933 xal = tcg_temp_new_i64();
1934 get_cpu_vsr(xah, rA(ctx->opcode) + 32, true);
1935 get_cpu_vsr(xal, rA(ctx->opcode) + 32, false);
1936 xbh = tcg_temp_new_i64();
1937 get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
1938 t0 = tcg_temp_new_i64();
1939
1940 tcg_gen_andi_i64(xth, xah, 0x8000FFFFFFFFFFFF);
1941 tcg_gen_andi_i64(t0, xbh, 0x7FFF);
1942 tcg_gen_shli_i64(t0, t0, 48);
1943 tcg_gen_or_i64(xth, xth, t0);
1944 set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
1945 tcg_gen_mov_i64(xtl, xal);
1946 set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
1947 }
1948
1949 static void gen_xsxsigdp(DisasContext *ctx)
1950 {
1951 TCGv rt = cpu_gpr[rD(ctx->opcode)];
1952 TCGv_i64 t0, t1, zr, nan, exp;
1953
1954 if (unlikely(!ctx->vsx_enabled)) {
1955 gen_exception(ctx, POWERPC_EXCP_VSXU);
1956 return;
1957 }
1958 exp = tcg_temp_new_i64();
1959 t0 = tcg_temp_new_i64();
1960 t1 = tcg_temp_new_i64();
1961 zr = tcg_constant_i64(0);
1962 nan = tcg_constant_i64(2047);
1963
1964 get_cpu_vsr(t1, xB(ctx->opcode), true);
1965 tcg_gen_extract_i64(exp, t1, 52, 11);
1966 tcg_gen_movi_i64(t0, 0x0010000000000000);
1967 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
1968 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
1969 get_cpu_vsr(t1, xB(ctx->opcode), true);
1970 tcg_gen_deposit_i64(rt, t0, t1, 0, 52);
1971 }
1972
1973 static void gen_xsxsigqp(DisasContext *ctx)
1974 {
1975 TCGv_i64 t0, zr, nan, exp;
1976 TCGv_i64 xth;
1977 TCGv_i64 xtl;
1978 TCGv_i64 xbh;
1979 TCGv_i64 xbl;
1980
1981 if (unlikely(!ctx->vsx_enabled)) {
1982 gen_exception(ctx, POWERPC_EXCP_VSXU);
1983 return;
1984 }
1985 xth = tcg_temp_new_i64();
1986 xtl = tcg_temp_new_i64();
1987 xbh = tcg_temp_new_i64();
1988 xbl = tcg_temp_new_i64();
1989 get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
1990 get_cpu_vsr(xbl, rB(ctx->opcode) + 32, false);
1991 exp = tcg_temp_new_i64();
1992 t0 = tcg_temp_new_i64();
1993 zr = tcg_constant_i64(0);
1994 nan = tcg_constant_i64(32767);
1995
1996 tcg_gen_extract_i64(exp, xbh, 48, 15);
1997 tcg_gen_movi_i64(t0, 0x0001000000000000);
1998 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
1999 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
2000 tcg_gen_deposit_i64(xth, t0, xbh, 0, 48);
2001 set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
2002 tcg_gen_mov_i64(xtl, xbl);
2003 set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
2004 }
2005 #endif
2006
2007 static void gen_xviexpsp(DisasContext *ctx)
2008 {
2009 TCGv_i64 xth;
2010 TCGv_i64 xtl;
2011 TCGv_i64 xah;
2012 TCGv_i64 xal;
2013 TCGv_i64 xbh;
2014 TCGv_i64 xbl;
2015 TCGv_i64 t0;
2016
2017 if (unlikely(!ctx->vsx_enabled)) {
2018 gen_exception(ctx, POWERPC_EXCP_VSXU);
2019 return;
2020 }
2021 xth = tcg_temp_new_i64();
2022 xtl = tcg_temp_new_i64();
2023 xah = tcg_temp_new_i64();
2024 xal = tcg_temp_new_i64();
2025 xbh = tcg_temp_new_i64();
2026 xbl = tcg_temp_new_i64();
2027 get_cpu_vsr(xah, xA(ctx->opcode), true);
2028 get_cpu_vsr(xal, xA(ctx->opcode), false);
2029 get_cpu_vsr(xbh, xB(ctx->opcode), true);
2030 get_cpu_vsr(xbl, xB(ctx->opcode), false);
2031 t0 = tcg_temp_new_i64();
2032
2033 tcg_gen_andi_i64(xth, xah, 0x807FFFFF807FFFFF);
2034 tcg_gen_andi_i64(t0, xbh, 0xFF000000FF);
2035 tcg_gen_shli_i64(t0, t0, 23);
2036 tcg_gen_or_i64(xth, xth, t0);
2037 set_cpu_vsr(xT(ctx->opcode), xth, true);
2038 tcg_gen_andi_i64(xtl, xal, 0x807FFFFF807FFFFF);
2039 tcg_gen_andi_i64(t0, xbl, 0xFF000000FF);
2040 tcg_gen_shli_i64(t0, t0, 23);
2041 tcg_gen_or_i64(xtl, xtl, t0);
2042 set_cpu_vsr(xT(ctx->opcode), xtl, false);
2043 }
2044
2045 static void gen_xviexpdp(DisasContext *ctx)
2046 {
2047 TCGv_i64 xth;
2048 TCGv_i64 xtl;
2049 TCGv_i64 xah;
2050 TCGv_i64 xal;
2051 TCGv_i64 xbh;
2052 TCGv_i64 xbl;
2053
2054 if (unlikely(!ctx->vsx_enabled)) {
2055 gen_exception(ctx, POWERPC_EXCP_VSXU);
2056 return;
2057 }
2058 xth = tcg_temp_new_i64();
2059 xtl = tcg_temp_new_i64();
2060 xah = tcg_temp_new_i64();
2061 xal = tcg_temp_new_i64();
2062 xbh = tcg_temp_new_i64();
2063 xbl = tcg_temp_new_i64();
2064 get_cpu_vsr(xah, xA(ctx->opcode), true);
2065 get_cpu_vsr(xal, xA(ctx->opcode), false);
2066 get_cpu_vsr(xbh, xB(ctx->opcode), true);
2067 get_cpu_vsr(xbl, xB(ctx->opcode), false);
2068
2069 tcg_gen_deposit_i64(xth, xah, xbh, 52, 11);
2070 set_cpu_vsr(xT(ctx->opcode), xth, true);
2071
2072 tcg_gen_deposit_i64(xtl, xal, xbl, 52, 11);
2073 set_cpu_vsr(xT(ctx->opcode), xtl, false);
2074 }
2075
2076 static void gen_xvxexpsp(DisasContext *ctx)
2077 {
2078 TCGv_i64 xth;
2079 TCGv_i64 xtl;
2080 TCGv_i64 xbh;
2081 TCGv_i64 xbl;
2082
2083 if (unlikely(!ctx->vsx_enabled)) {
2084 gen_exception(ctx, POWERPC_EXCP_VSXU);
2085 return;
2086 }
2087 xth = tcg_temp_new_i64();
2088 xtl = tcg_temp_new_i64();
2089 xbh = tcg_temp_new_i64();
2090 xbl = tcg_temp_new_i64();
2091 get_cpu_vsr(xbh, xB(ctx->opcode), true);
2092 get_cpu_vsr(xbl, xB(ctx->opcode), false);
2093
2094 tcg_gen_shri_i64(xth, xbh, 23);
2095 tcg_gen_andi_i64(xth, xth, 0xFF000000FF);
2096 set_cpu_vsr(xT(ctx->opcode), xth, true);
2097 tcg_gen_shri_i64(xtl, xbl, 23);
2098 tcg_gen_andi_i64(xtl, xtl, 0xFF000000FF);
2099 set_cpu_vsr(xT(ctx->opcode), xtl, false);
2100 }
2101
2102 static void gen_xvxexpdp(DisasContext *ctx)
2103 {
2104 TCGv_i64 xth;
2105 TCGv_i64 xtl;
2106 TCGv_i64 xbh;
2107 TCGv_i64 xbl;
2108
2109 if (unlikely(!ctx->vsx_enabled)) {
2110 gen_exception(ctx, POWERPC_EXCP_VSXU);
2111 return;
2112 }
2113 xth = tcg_temp_new_i64();
2114 xtl = tcg_temp_new_i64();
2115 xbh = tcg_temp_new_i64();
2116 xbl = tcg_temp_new_i64();
2117 get_cpu_vsr(xbh, xB(ctx->opcode), true);
2118 get_cpu_vsr(xbl, xB(ctx->opcode), false);
2119
2120 tcg_gen_extract_i64(xth, xbh, 52, 11);
2121 set_cpu_vsr(xT(ctx->opcode), xth, true);
2122 tcg_gen_extract_i64(xtl, xbl, 52, 11);
2123 set_cpu_vsr(xT(ctx->opcode), xtl, false);
2124 }
2125
2126 static bool trans_XVXSIGSP(DisasContext *ctx, arg_XX2 *a)
2127 {
2128 TCGv_ptr t, b;
2129
2130 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2131 REQUIRE_VSX(ctx);
2132
2133 t = gen_vsr_ptr(a->xt);
2134 b = gen_vsr_ptr(a->xb);
2135
2136 gen_helper_XVXSIGSP(t, b);
2137 return true;
2138 }
2139
2140 static void gen_xvxsigdp(DisasContext *ctx)
2141 {
2142 TCGv_i64 xth;
2143 TCGv_i64 xtl;
2144 TCGv_i64 xbh;
2145 TCGv_i64 xbl;
2146 TCGv_i64 t0, zr, nan, exp;
2147
2148 if (unlikely(!ctx->vsx_enabled)) {
2149 gen_exception(ctx, POWERPC_EXCP_VSXU);
2150 return;
2151 }
2152 xth = tcg_temp_new_i64();
2153 xtl = tcg_temp_new_i64();
2154 xbh = tcg_temp_new_i64();
2155 xbl = tcg_temp_new_i64();
2156 get_cpu_vsr(xbh, xB(ctx->opcode), true);
2157 get_cpu_vsr(xbl, xB(ctx->opcode), false);
2158 exp = tcg_temp_new_i64();
2159 t0 = tcg_temp_new_i64();
2160 zr = tcg_constant_i64(0);
2161 nan = tcg_constant_i64(2047);
2162
2163 tcg_gen_extract_i64(exp, xbh, 52, 11);
2164 tcg_gen_movi_i64(t0, 0x0010000000000000);
2165 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
2166 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
2167 tcg_gen_deposit_i64(xth, t0, xbh, 0, 52);
2168 set_cpu_vsr(xT(ctx->opcode), xth, true);
2169
2170 tcg_gen_extract_i64(exp, xbl, 52, 11);
2171 tcg_gen_movi_i64(t0, 0x0010000000000000);
2172 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
2173 tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
2174 tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52);
2175 set_cpu_vsr(xT(ctx->opcode), xtl, false);
2176 }
2177
2178 static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
2179 int rt, bool store, bool paired)
2180 {
2181 TCGv ea;
2182 TCGv_i128 data;
2183 MemOp mop;
2184 int rt1, rt2;
2185
2186 data = tcg_temp_new_i128();
2187
2188 mop = DEF_MEMOP(MO_128 | MO_ATOM_IFALIGN_PAIR);
2189
2190 gen_set_access_type(ctx, ACCESS_INT);
2191 ea = do_ea_calc(ctx, ra, displ);
2192
2193 if (paired && ctx->le_mode) {
2194 rt1 = rt + 1;
2195 rt2 = rt;
2196 } else {
2197 rt1 = rt;
2198 rt2 = rt + 1;
2199 }
2200
2201 if (store) {
2202 get_vsr_full(data, rt1);
2203 tcg_gen_qemu_st_i128(data, ea, ctx->mem_idx, mop);
2204 if (paired) {
2205 gen_addr_add(ctx, ea, ea, 16);
2206 get_vsr_full(data, rt2);
2207 tcg_gen_qemu_st_i128(data, ea, ctx->mem_idx, mop);
2208 }
2209 } else {
2210 tcg_gen_qemu_ld_i128(data, ea, ctx->mem_idx, mop);
2211 set_vsr_full(rt1, data);
2212 if (paired) {
2213 gen_addr_add(ctx, ea, ea, 16);
2214 tcg_gen_qemu_ld_i128(data, ea, ctx->mem_idx, mop);
2215 set_vsr_full(rt2, data);
2216 }
2217 }
2218 return true;
2219 }
2220
2221 static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired)
2222 {
2223 if (paired || a->rt < 32) {
2224 REQUIRE_VSX(ctx);
2225 } else {
2226 REQUIRE_VECTOR(ctx);
2227 }
2228
2229 return do_lstxv(ctx, a->ra, tcg_constant_tl(a->si), a->rt, store, paired);
2230 }
2231
2232 static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a,
2233 bool store, bool paired)
2234 {
2235 arg_D d;
2236 REQUIRE_VSX(ctx);
2237
2238 if (!resolve_PLS_D(ctx, &d, a)) {
2239 return true;
2240 }
2241
2242 return do_lstxv(ctx, d.ra, tcg_constant_tl(d.si), d.rt, store, paired);
2243 }
2244
2245 static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired)
2246 {
2247 if (paired || a->rt < 32) {
2248 REQUIRE_VSX(ctx);
2249 } else {
2250 REQUIRE_VECTOR(ctx);
2251 }
2252
2253 return do_lstxv(ctx, a->ra, cpu_gpr[a->rb], a->rt, store, paired);
2254 }
2255
2256 static bool do_lstxsd(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
2257 {
2258 TCGv ea;
2259 TCGv_i64 xt;
2260 MemOp mop;
2261
2262 if (store) {
2263 REQUIRE_VECTOR(ctx);
2264 } else {
2265 REQUIRE_VSX(ctx);
2266 }
2267
2268 xt = tcg_temp_new_i64();
2269 mop = DEF_MEMOP(MO_UQ);
2270
2271 gen_set_access_type(ctx, ACCESS_INT);
2272 ea = do_ea_calc(ctx, ra, displ);
2273
2274 if (store) {
2275 get_cpu_vsr(xt, rt + 32, true);
2276 tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
2277 } else {
2278 tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
2279 set_cpu_vsr(rt + 32, xt, true);
2280 set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
2281 }
2282 return true;
2283 }
2284
2285 static bool do_lstxsd_DS(DisasContext *ctx, arg_D *a, bool store)
2286 {
2287 return do_lstxsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
2288 }
2289
2290 static bool do_plstxsd_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
2291 {
2292 arg_D d;
2293
2294 if (!resolve_PLS_D(ctx, &d, a)) {
2295 return true;
2296 }
2297
2298 return do_lstxsd(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
2299 }
2300
2301 static bool do_lstxssp(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
2302 {
2303 TCGv ea;
2304 TCGv_i64 xt;
2305
2306 REQUIRE_VECTOR(ctx);
2307
2308 xt = tcg_temp_new_i64();
2309
2310 gen_set_access_type(ctx, ACCESS_INT);
2311 ea = do_ea_calc(ctx, ra, displ);
2312
2313 if (store) {
2314 get_cpu_vsr(xt, rt + 32, true);
2315 gen_qemu_st32fs(ctx, xt, ea);
2316 } else {
2317 gen_qemu_ld32fs(ctx, xt, ea);
2318 set_cpu_vsr(rt + 32, xt, true);
2319 set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
2320 }
2321 return true;
2322 }
2323
2324 static bool do_lstxssp_DS(DisasContext *ctx, arg_D *a, bool store)
2325 {
2326 return do_lstxssp(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
2327 }
2328
2329 static bool do_plstxssp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
2330 {
2331 arg_D d;
2332
2333 if (!resolve_PLS_D(ctx, &d, a)) {
2334 return true;
2335 }
2336
2337 return do_lstxssp(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
2338 }
2339
2340 TRANS_FLAGS2(ISA300, LXSD, do_lstxsd_DS, false)
2341 TRANS_FLAGS2(ISA300, STXSD, do_lstxsd_DS, true)
2342 TRANS_FLAGS2(ISA300, LXSSP, do_lstxssp_DS, false)
2343 TRANS_FLAGS2(ISA300, STXSSP, do_lstxssp_DS, true)
2344 TRANS_FLAGS2(ISA300, STXV, do_lstxv_D, true, false)
2345 TRANS_FLAGS2(ISA300, LXV, do_lstxv_D, false, false)
2346 TRANS_FLAGS2(ISA310, STXVP, do_lstxv_D, true, true)
2347 TRANS_FLAGS2(ISA310, LXVP, do_lstxv_D, false, true)
2348 TRANS_FLAGS2(ISA300, STXVX, do_lstxv_X, true, false)
2349 TRANS_FLAGS2(ISA300, LXVX, do_lstxv_X, false, false)
2350 TRANS_FLAGS2(ISA310, STXVPX, do_lstxv_X, true, true)
2351 TRANS_FLAGS2(ISA310, LXVPX, do_lstxv_X, false, true)
2352 TRANS64_FLAGS2(ISA310, PLXSD, do_plstxsd_PLS_D, false)
2353 TRANS64_FLAGS2(ISA310, PSTXSD, do_plstxsd_PLS_D, true)
2354 TRANS64_FLAGS2(ISA310, PLXSSP, do_plstxssp_PLS_D, false)
2355 TRANS64_FLAGS2(ISA310, PSTXSSP, do_plstxssp_PLS_D, true)
2356 TRANS64_FLAGS2(ISA310, PSTXV, do_lstxv_PLS_D, true, false)
2357 TRANS64_FLAGS2(ISA310, PLXV, do_lstxv_PLS_D, false, false)
2358 TRANS64_FLAGS2(ISA310, PSTXVP, do_lstxv_PLS_D, true, true)
2359 TRANS64_FLAGS2(ISA310, PLXVP, do_lstxv_PLS_D, false, true)
2360
2361 static bool do_lstrm(DisasContext *ctx, arg_X *a, MemOp mop, bool store)
2362 {
2363 TCGv ea;
2364 TCGv_i64 xt;
2365
2366 REQUIRE_VSX(ctx);
2367
2368 xt = tcg_temp_new_i64();
2369
2370 gen_set_access_type(ctx, ACCESS_INT);
2371 ea = do_ea_calc(ctx, a->ra , cpu_gpr[a->rb]);
2372
2373 if (store) {
2374 get_cpu_vsr(xt, a->rt, false);
2375 tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
2376 } else {
2377 tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
2378 set_cpu_vsr(a->rt, xt, false);
2379 set_cpu_vsr(a->rt, tcg_constant_i64(0), true);
2380 }
2381 return true;
2382 }
2383
2384 TRANS_FLAGS2(ISA310, LXVRBX, do_lstrm, DEF_MEMOP(MO_UB), false)
2385 TRANS_FLAGS2(ISA310, LXVRHX, do_lstrm, DEF_MEMOP(MO_UW), false)
2386 TRANS_FLAGS2(ISA310, LXVRWX, do_lstrm, DEF_MEMOP(MO_UL), false)
2387 TRANS_FLAGS2(ISA310, LXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), false)
2388 TRANS_FLAGS2(ISA310, STXVRBX, do_lstrm, DEF_MEMOP(MO_UB), true)
2389 TRANS_FLAGS2(ISA310, STXVRHX, do_lstrm, DEF_MEMOP(MO_UW), true)
2390 TRANS_FLAGS2(ISA310, STXVRWX, do_lstrm, DEF_MEMOP(MO_UL), true)
2391 TRANS_FLAGS2(ISA310, STXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), true)
2392
2393 static void gen_xxeval_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c,
2394 int64_t imm)
2395 {
2396 /*
2397 * Instead of processing imm bit-by-bit, we'll skip the computation of
2398 * conjunctions whose corresponding bit is unset.
2399 */
2400 int bit;
2401 TCGv_i64 conj, disj;
2402
2403 conj = tcg_temp_new_i64();
2404 disj = tcg_temp_new_i64();
2405 tcg_gen_movi_i64(disj, 0);
2406
2407 /* Iterate over set bits from the least to the most significant bit */
2408 while (imm) {
2409 /*
2410 * Get the next bit to be processed with ctz64. Invert the result of
2411 * ctz64 to match the indexing used by PowerISA.
2412 */
2413 bit = 7 - ctz64(imm);
2414 if (bit & 0x4) {
2415 tcg_gen_mov_i64(conj, a);
2416 } else {
2417 tcg_gen_not_i64(conj, a);
2418 }
2419 if (bit & 0x2) {
2420 tcg_gen_and_i64(conj, conj, b);
2421 } else {
2422 tcg_gen_andc_i64(conj, conj, b);
2423 }
2424 if (bit & 0x1) {
2425 tcg_gen_and_i64(conj, conj, c);
2426 } else {
2427 tcg_gen_andc_i64(conj, conj, c);
2428 }
2429 tcg_gen_or_i64(disj, disj, conj);
2430
2431 /* Unset the least significant bit that is set */
2432 imm &= imm - 1;
2433 }
2434
2435 tcg_gen_mov_i64(t, disj);
2436 }
2437
2438 static void gen_xxeval_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
2439 TCGv_vec c, int64_t imm)
2440 {
2441 /*
2442 * Instead of processing imm bit-by-bit, we'll skip the computation of
2443 * conjunctions whose corresponding bit is unset.
2444 */
2445 int bit;
2446 TCGv_vec disj, conj;
2447
2448 conj = tcg_temp_new_vec_matching(t);
2449 disj = tcg_temp_new_vec_matching(t);
2450 tcg_gen_dupi_vec(vece, disj, 0);
2451
2452 /* Iterate over set bits from the least to the most significant bit */
2453 while (imm) {
2454 /*
2455 * Get the next bit to be processed with ctz64. Invert the result of
2456 * ctz64 to match the indexing used by PowerISA.
2457 */
2458 bit = 7 - ctz64(imm);
2459 if (bit & 0x4) {
2460 tcg_gen_mov_vec(conj, a);
2461 } else {
2462 tcg_gen_not_vec(vece, conj, a);
2463 }
2464 if (bit & 0x2) {
2465 tcg_gen_and_vec(vece, conj, conj, b);
2466 } else {
2467 tcg_gen_andc_vec(vece, conj, conj, b);
2468 }
2469 if (bit & 0x1) {
2470 tcg_gen_and_vec(vece, conj, conj, c);
2471 } else {
2472 tcg_gen_andc_vec(vece, conj, conj, c);
2473 }
2474 tcg_gen_or_vec(vece, disj, disj, conj);
2475
2476 /* Unset the least significant bit that is set */
2477 imm &= imm - 1;
2478 }
2479
2480 tcg_gen_mov_vec(t, disj);
2481 }
2482
2483 static bool trans_XXEVAL(DisasContext *ctx, arg_8RR_XX4_imm *a)
2484 {
2485 static const TCGOpcode vecop_list[] = {
2486 INDEX_op_andc_vec, 0
2487 };
2488 static const GVecGen4i op = {
2489 .fniv = gen_xxeval_vec,
2490 .fno = gen_helper_XXEVAL,
2491 .fni8 = gen_xxeval_i64,
2492 .opt_opc = vecop_list,
2493 .vece = MO_64
2494 };
2495 int xt = vsr_full_offset(a->xt), xa = vsr_full_offset(a->xa),
2496 xb = vsr_full_offset(a->xb), xc = vsr_full_offset(a->xc);
2497
2498 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2499 REQUIRE_VSX(ctx);
2500
2501 /* Equivalent functions that can be implemented with a single gen_gvec */
2502 switch (a->imm) {
2503 case 0b00000000: /* false */
2504 set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
2505 set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
2506 break;
2507 case 0b00000011: /* and(B,A) */
2508 tcg_gen_gvec_and(MO_64, xt, xb, xa, 16, 16);
2509 break;
2510 case 0b00000101: /* and(C,A) */
2511 tcg_gen_gvec_and(MO_64, xt, xc, xa, 16, 16);
2512 break;
2513 case 0b00001111: /* A */
2514 tcg_gen_gvec_mov(MO_64, xt, xa, 16, 16);
2515 break;
2516 case 0b00010001: /* and(C,B) */
2517 tcg_gen_gvec_and(MO_64, xt, xc, xb, 16, 16);
2518 break;
2519 case 0b00011011: /* C?B:A */
2520 tcg_gen_gvec_bitsel(MO_64, xt, xc, xb, xa, 16, 16);
2521 break;
2522 case 0b00011101: /* B?C:A */
2523 tcg_gen_gvec_bitsel(MO_64, xt, xb, xc, xa, 16, 16);
2524 break;
2525 case 0b00100111: /* C?A:B */
2526 tcg_gen_gvec_bitsel(MO_64, xt, xc, xa, xb, 16, 16);
2527 break;
2528 case 0b00110011: /* B */
2529 tcg_gen_gvec_mov(MO_64, xt, xb, 16, 16);
2530 break;
2531 case 0b00110101: /* A?C:B */
2532 tcg_gen_gvec_bitsel(MO_64, xt, xa, xc, xb, 16, 16);
2533 break;
2534 case 0b00111100: /* xor(B,A) */
2535 tcg_gen_gvec_xor(MO_64, xt, xb, xa, 16, 16);
2536 break;
2537 case 0b00111111: /* or(B,A) */
2538 tcg_gen_gvec_or(MO_64, xt, xb, xa, 16, 16);
2539 break;
2540 case 0b01000111: /* B?A:C */
2541 tcg_gen_gvec_bitsel(MO_64, xt, xb, xa, xc, 16, 16);
2542 break;
2543 case 0b01010011: /* A?B:C */
2544 tcg_gen_gvec_bitsel(MO_64, xt, xa, xb, xc, 16, 16);
2545 break;
2546 case 0b01010101: /* C */
2547 tcg_gen_gvec_mov(MO_64, xt, xc, 16, 16);
2548 break;
2549 case 0b01011010: /* xor(C,A) */
2550 tcg_gen_gvec_xor(MO_64, xt, xc, xa, 16, 16);
2551 break;
2552 case 0b01011111: /* or(C,A) */
2553 tcg_gen_gvec_or(MO_64, xt, xc, xa, 16, 16);
2554 break;
2555 case 0b01100110: /* xor(C,B) */
2556 tcg_gen_gvec_xor(MO_64, xt, xc, xb, 16, 16);
2557 break;
2558 case 0b01110111: /* or(C,B) */
2559 tcg_gen_gvec_or(MO_64, xt, xc, xb, 16, 16);
2560 break;
2561 case 0b10001000: /* nor(C,B) */
2562 tcg_gen_gvec_nor(MO_64, xt, xc, xb, 16, 16);
2563 break;
2564 case 0b10011001: /* eqv(C,B) */
2565 tcg_gen_gvec_eqv(MO_64, xt, xc, xb, 16, 16);
2566 break;
2567 case 0b10100000: /* nor(C,A) */
2568 tcg_gen_gvec_nor(MO_64, xt, xc, xa, 16, 16);
2569 break;
2570 case 0b10100101: /* eqv(C,A) */
2571 tcg_gen_gvec_eqv(MO_64, xt, xc, xa, 16, 16);
2572 break;
2573 case 0b10101010: /* not(C) */
2574 tcg_gen_gvec_not(MO_64, xt, xc, 16, 16);
2575 break;
2576 case 0b11000000: /* nor(B,A) */
2577 tcg_gen_gvec_nor(MO_64, xt, xb, xa, 16, 16);
2578 break;
2579 case 0b11000011: /* eqv(B,A) */
2580 tcg_gen_gvec_eqv(MO_64, xt, xb, xa, 16, 16);
2581 break;
2582 case 0b11001100: /* not(B) */
2583 tcg_gen_gvec_not(MO_64, xt, xb, 16, 16);
2584 break;
2585 case 0b11101110: /* nand(C,B) */
2586 tcg_gen_gvec_nand(MO_64, xt, xc, xb, 16, 16);
2587 break;
2588 case 0b11110000: /* not(A) */
2589 tcg_gen_gvec_not(MO_64, xt, xa, 16, 16);
2590 break;
2591 case 0b11111010: /* nand(C,A) */
2592 tcg_gen_gvec_nand(MO_64, xt, xc, xa, 16, 16);
2593 break;
2594 case 0b11111100: /* nand(B,A) */
2595 tcg_gen_gvec_nand(MO_64, xt, xb, xa, 16, 16);
2596 break;
2597 case 0b11111111: /* true */
2598 set_cpu_vsr(a->xt, tcg_constant_i64(-1), true);
2599 set_cpu_vsr(a->xt, tcg_constant_i64(-1), false);
2600 break;
2601 default:
2602 /* Fallback to compute all conjunctions/disjunctions */
2603 tcg_gen_gvec_4i(xt, xa, xb, xc, 16, 16, a->imm, &op);
2604 }
2605
2606 return true;
2607 }
2608
2609 static void gen_xxblendv_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
2610 TCGv_vec c)
2611 {
2612 TCGv_vec tmp = tcg_temp_new_vec_matching(c);
2613 tcg_gen_sari_vec(vece, tmp, c, (8 << vece) - 1);
2614 tcg_gen_bitsel_vec(vece, t, tmp, b, a);
2615 }
2616
2617 static bool do_xxblendv(DisasContext *ctx, arg_8RR_XX4 *a, unsigned vece)
2618 {
2619 static const TCGOpcode vecop_list[] = {
2620 INDEX_op_sari_vec, 0
2621 };
2622 static const GVecGen4 ops[4] = {
2623 {
2624 .fniv = gen_xxblendv_vec,
2625 .fno = gen_helper_XXBLENDVB,
2626 .opt_opc = vecop_list,
2627 .vece = MO_8
2628 },
2629 {
2630 .fniv = gen_xxblendv_vec,
2631 .fno = gen_helper_XXBLENDVH,
2632 .opt_opc = vecop_list,
2633 .vece = MO_16
2634 },
2635 {
2636 .fniv = gen_xxblendv_vec,
2637 .fno = gen_helper_XXBLENDVW,
2638 .opt_opc = vecop_list,
2639 .vece = MO_32
2640 },
2641 {
2642 .fniv = gen_xxblendv_vec,
2643 .fno = gen_helper_XXBLENDVD,
2644 .opt_opc = vecop_list,
2645 .vece = MO_64
2646 }
2647 };
2648
2649 REQUIRE_VSX(ctx);
2650
2651 tcg_gen_gvec_4(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
2652 vsr_full_offset(a->xb), vsr_full_offset(a->xc),
2653 16, 16, &ops[vece]);
2654
2655 return true;
2656 }
2657
2658 TRANS(XXBLENDVB, do_xxblendv, MO_8)
2659 TRANS(XXBLENDVH, do_xxblendv, MO_16)
2660 TRANS(XXBLENDVW, do_xxblendv, MO_32)
2661 TRANS(XXBLENDVD, do_xxblendv, MO_64)
2662
2663 static bool do_helper_XX3(DisasContext *ctx, arg_XX3 *a,
2664 void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
2665 {
2666 TCGv_ptr xt, xa, xb;
2667 REQUIRE_VSX(ctx);
2668
2669 xt = gen_vsr_ptr(a->xt);
2670 xa = gen_vsr_ptr(a->xa);
2671 xb = gen_vsr_ptr(a->xb);
2672
2673 helper(tcg_env, xt, xa, xb);
2674 return true;
2675 }
2676
2677 TRANS_FLAGS2(ISA300, XSCMPEQDP, do_helper_XX3, gen_helper_XSCMPEQDP)
2678 TRANS_FLAGS2(ISA300, XSCMPGEDP, do_helper_XX3, gen_helper_XSCMPGEDP)
2679 TRANS_FLAGS2(ISA300, XSCMPGTDP, do_helper_XX3, gen_helper_XSCMPGTDP)
2680 TRANS_FLAGS2(ISA300, XSMAXCDP, do_helper_XX3, gen_helper_XSMAXCDP)
2681 TRANS_FLAGS2(ISA300, XSMINCDP, do_helper_XX3, gen_helper_XSMINCDP)
2682 TRANS_FLAGS2(ISA300, XSMAXJDP, do_helper_XX3, gen_helper_XSMAXJDP)
2683 TRANS_FLAGS2(ISA300, XSMINJDP, do_helper_XX3, gen_helper_XSMINJDP)
2684
2685 TRANS_FLAGS2(ISA207, XSADDSP, do_helper_XX3, gen_helper_XSADDSP)
2686 TRANS_FLAGS2(ISA207, XSSUBSP, do_helper_XX3, gen_helper_XSSUBSP)
2687 TRANS_FLAGS2(ISA207, XSMULSP, do_helper_XX3, gen_helper_XSMULSP)
2688 TRANS_FLAGS2(ISA207, XSDIVSP, do_helper_XX3, gen_helper_XSDIVSP)
2689
2690 TRANS_FLAGS2(VSX, XSADDDP, do_helper_XX3, gen_helper_XSADDDP)
2691 TRANS_FLAGS2(VSX, XSSUBDP, do_helper_XX3, gen_helper_XSSUBDP)
2692 TRANS_FLAGS2(VSX, XSMULDP, do_helper_XX3, gen_helper_XSMULDP)
2693 TRANS_FLAGS2(VSX, XSDIVDP, do_helper_XX3, gen_helper_XSDIVDP)
2694
2695 TRANS_FLAGS2(VSX, XVADDSP, do_helper_XX3, gen_helper_XVADDSP)
2696 TRANS_FLAGS2(VSX, XVSUBSP, do_helper_XX3, gen_helper_XVSUBSP)
2697 TRANS_FLAGS2(VSX, XVMULSP, do_helper_XX3, gen_helper_XVMULSP)
2698 TRANS_FLAGS2(VSX, XVDIVSP, do_helper_XX3, gen_helper_XVDIVSP)
2699
2700 TRANS_FLAGS2(VSX, XVADDDP, do_helper_XX3, gen_helper_XVADDDP)
2701 TRANS_FLAGS2(VSX, XVSUBDP, do_helper_XX3, gen_helper_XVSUBDP)
2702 TRANS_FLAGS2(VSX, XVMULDP, do_helper_XX3, gen_helper_XVMULDP)
2703 TRANS_FLAGS2(VSX, XVDIVDP, do_helper_XX3, gen_helper_XVDIVDP)
2704
2705 TRANS_FLAGS2(VSX, XSMAXDP, do_helper_XX3, gen_helper_XSMAXDP)
2706 TRANS_FLAGS2(VSX, XSMINDP, do_helper_XX3, gen_helper_XSMINDP)
2707 TRANS_FLAGS2(VSX, XVMAXSP, do_helper_XX3, gen_helper_XVMAXSP)
2708 TRANS_FLAGS2(VSX, XVMINSP, do_helper_XX3, gen_helper_XVMINSP)
2709 TRANS_FLAGS2(VSX, XVMAXDP, do_helper_XX3, gen_helper_XVMAXDP)
2710 TRANS_FLAGS2(VSX, XVMINDP, do_helper_XX3, gen_helper_XVMINDP)
2711
2712 static bool do_helper_X(arg_X *a,
2713 void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
2714 {
2715 TCGv_ptr rt, ra, rb;
2716
2717 rt = gen_avr_ptr(a->rt);
2718 ra = gen_avr_ptr(a->ra);
2719 rb = gen_avr_ptr(a->rb);
2720
2721 helper(tcg_env, rt, ra, rb);
2722 return true;
2723 }
2724
2725 static bool do_xscmpqp(DisasContext *ctx, arg_X *a,
2726 void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
2727 {
2728 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2729 REQUIRE_VSX(ctx);
2730
2731 return do_helper_X(a, helper);
2732 }
2733
2734 TRANS(XSCMPEQQP, do_xscmpqp, gen_helper_XSCMPEQQP)
2735 TRANS(XSCMPGEQP, do_xscmpqp, gen_helper_XSCMPGEQP)
2736 TRANS(XSCMPGTQP, do_xscmpqp, gen_helper_XSCMPGTQP)
2737 TRANS(XSMAXCQP, do_xscmpqp, gen_helper_XSMAXCQP)
2738 TRANS(XSMINCQP, do_xscmpqp, gen_helper_XSMINCQP)
2739
2740 static bool trans_XVCVSPBF16(DisasContext *ctx, arg_XX2 *a)
2741 {
2742 TCGv_ptr xt, xb;
2743
2744 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2745 REQUIRE_VSX(ctx);
2746
2747 xt = gen_vsr_ptr(a->xt);
2748 xb = gen_vsr_ptr(a->xb);
2749
2750 gen_helper_XVCVSPBF16(tcg_env, xt, xb);
2751 return true;
2752 }
2753
2754 static bool trans_XVCVBF16SPN(DisasContext *ctx, arg_XX2 *a)
2755 {
2756 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2757 REQUIRE_VSX(ctx);
2758
2759 tcg_gen_gvec_shli(MO_32, vsr_full_offset(a->xt), vsr_full_offset(a->xb),
2760 16, 16, 16);
2761
2762 return true;
2763 }
2764
2765 /*
2766 * The PowerISA 3.1 mentions that for the current version of the
2767 * architecture, "the hardware implementation provides the effect of
2768 * ACC[i] and VSRs 4*i to 4*i + 3 logically containing the same data"
2769 * and "The Accumulators introduce no new logical state at this time"
2770 * (page 501). For now it seems unnecessary to create new structures,
2771 * so ACC[i] is the same as VSRs 4*i to 4*i+3 and therefore
2772 * move to and from accumulators are no-ops.
2773 */
2774 static bool trans_XXMFACC(DisasContext *ctx, arg_X_a *a)
2775 {
2776 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2777 REQUIRE_VSX(ctx);
2778 return true;
2779 }
2780
2781 static bool trans_XXMTACC(DisasContext *ctx, arg_X_a *a)
2782 {
2783 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2784 REQUIRE_VSX(ctx);
2785 return true;
2786 }
2787
2788 static bool trans_XXSETACCZ(DisasContext *ctx, arg_X_a *a)
2789 {
2790 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2791 REQUIRE_VSX(ctx);
2792 tcg_gen_gvec_dup_imm(MO_64, acc_full_offset(a->ra), 64, 64, 0);
2793 return true;
2794 }
2795
2796 static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
2797 void (*helper)(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32))
2798 {
2799 uint32_t mask;
2800 TCGv_ptr xt, xa, xb;
2801 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
2802 REQUIRE_VSX(ctx);
2803 if (unlikely((a->xa / 4 == a->xt) || (a->xb / 4 == a->xt))) {
2804 gen_invalid(ctx);
2805 return true;
2806 }
2807
2808 xt = gen_acc_ptr(a->xt);
2809 xa = gen_vsr_ptr(a->xa);
2810 xb = gen_vsr_ptr(a->xb);
2811
2812 mask = ger_pack_masks(a->pmsk, a->ymsk, a->xmsk);
2813 helper(tcg_env, xa, xb, xt, tcg_constant_i32(mask));
2814 return true;
2815 }
2816
2817 TRANS(XVI4GER8, do_ger, gen_helper_XVI4GER8)
2818 TRANS(XVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
2819 TRANS(XVI8GER4, do_ger, gen_helper_XVI8GER4)
2820 TRANS(XVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
2821 TRANS(XVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
2822 TRANS(XVI16GER2, do_ger, gen_helper_XVI16GER2)
2823 TRANS(XVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
2824 TRANS(XVI16GER2S, do_ger, gen_helper_XVI16GER2S)
2825 TRANS(XVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
2826
2827 TRANS64(PMXVI4GER8, do_ger, gen_helper_XVI4GER8)
2828 TRANS64(PMXVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
2829 TRANS64(PMXVI8GER4, do_ger, gen_helper_XVI8GER4)
2830 TRANS64(PMXVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
2831 TRANS64(PMXVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
2832 TRANS64(PMXVI16GER2, do_ger, gen_helper_XVI16GER2)
2833 TRANS64(PMXVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
2834 TRANS64(PMXVI16GER2S, do_ger, gen_helper_XVI16GER2S)
2835 TRANS64(PMXVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
2836
2837 TRANS(XVBF16GER2, do_ger, gen_helper_XVBF16GER2)
2838 TRANS(XVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
2839 TRANS(XVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
2840 TRANS(XVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
2841 TRANS(XVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
2842
2843 TRANS(XVF16GER2, do_ger, gen_helper_XVF16GER2)
2844 TRANS(XVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
2845 TRANS(XVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
2846 TRANS(XVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
2847 TRANS(XVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
2848
2849 TRANS(XVF32GER, do_ger, gen_helper_XVF32GER)
2850 TRANS(XVF32GERPP, do_ger, gen_helper_XVF32GERPP)
2851 TRANS(XVF32GERPN, do_ger, gen_helper_XVF32GERPN)
2852 TRANS(XVF32GERNP, do_ger, gen_helper_XVF32GERNP)
2853 TRANS(XVF32GERNN, do_ger, gen_helper_XVF32GERNN)
2854
2855 TRANS(XVF64GER, do_ger, gen_helper_XVF64GER)
2856 TRANS(XVF64GERPP, do_ger, gen_helper_XVF64GERPP)
2857 TRANS(XVF64GERPN, do_ger, gen_helper_XVF64GERPN)
2858 TRANS(XVF64GERNP, do_ger, gen_helper_XVF64GERNP)
2859 TRANS(XVF64GERNN, do_ger, gen_helper_XVF64GERNN)
2860
2861 TRANS64(PMXVBF16GER2, do_ger, gen_helper_XVBF16GER2)
2862 TRANS64(PMXVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
2863 TRANS64(PMXVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
2864 TRANS64(PMXVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
2865 TRANS64(PMXVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
2866
2867 TRANS64(PMXVF16GER2, do_ger, gen_helper_XVF16GER2)
2868 TRANS64(PMXVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
2869 TRANS64(PMXVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
2870 TRANS64(PMXVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
2871 TRANS64(PMXVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
2872
2873 TRANS64(PMXVF32GER, do_ger, gen_helper_XVF32GER)
2874 TRANS64(PMXVF32GERPP, do_ger, gen_helper_XVF32GERPP)
2875 TRANS64(PMXVF32GERPN, do_ger, gen_helper_XVF32GERPN)
2876 TRANS64(PMXVF32GERNP, do_ger, gen_helper_XVF32GERNP)
2877 TRANS64(PMXVF32GERNN, do_ger, gen_helper_XVF32GERNN)
2878
2879 TRANS64(PMXVF64GER, do_ger, gen_helper_XVF64GER)
2880 TRANS64(PMXVF64GERPP, do_ger, gen_helper_XVF64GERPP)
2881 TRANS64(PMXVF64GERPN, do_ger, gen_helper_XVF64GERPN)
2882 TRANS64(PMXVF64GERNP, do_ger, gen_helper_XVF64GERNP)
2883 TRANS64(PMXVF64GERNN, do_ger, gen_helper_XVF64GERNN)
2884
2885 #undef GEN_XX2FORM
2886 #undef GEN_XX3FORM
2887 #undef GEN_XX2IFORM
2888 #undef GEN_XX3_RC_FORM
2889 #undef GEN_XX3FORM_DM