1/*** VSX extension ***/ 2 3static 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 8static 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 13static 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 18static 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 23static 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 30static 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 37static 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 52TRANS_FLAGS2(VSX, LXSDX, do_lxs, gen_qemu_ld64_i64); 53TRANS_FLAGS2(VSX207, LXSIWAX, do_lxs, gen_qemu_ld32s_i64); 54TRANS_FLAGS2(ISA300, LXSIBZX, do_lxs, gen_qemu_ld8u_i64); 55TRANS_FLAGS2(ISA300, LXSIHZX, do_lxs, gen_qemu_ld16u_i64); 56TRANS_FLAGS2(VSX207, LXSIWZX, do_lxs, gen_qemu_ld32u_i64); 57TRANS_FLAGS2(VSX207, LXSSPX, do_lxs, gen_qemu_ld32fs); 58 59static bool trans_LXVD2X(DisasContext *ctx, arg_LXVD2X *a) 60{ 61 TCGv EA; 62 TCGv_i64 t0; 63 64 REQUIRE_VSX(ctx); 65 REQUIRE_INSNS_FLAGS2(ctx, VSX); 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 78static bool trans_LXVW4X(DisasContext *ctx, arg_LXVW4X *a) 79{ 80 TCGv EA; 81 TCGv_i64 xth, xtl; 82 83 REQUIRE_VSX(ctx); 84 REQUIRE_INSNS_FLAGS2(ctx, VSX); 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 111static bool trans_LXVWSX(DisasContext *ctx, arg_LXVWSX *a) 112{ 113 TCGv EA; 114 TCGv_i32 data; 115 116 if (a->rt < 32) { 117 REQUIRE_VSX(ctx); 118 } else { 119 REQUIRE_VECTOR(ctx); 120 } 121 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 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 131static bool trans_LXVDSX(DisasContext *ctx, arg_LXVDSX *a) 132{ 133 TCGv EA; 134 TCGv_i64 data; 135 136 REQUIRE_VSX(ctx); 137 REQUIRE_INSNS_FLAGS2(ctx, VSX); 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 147static 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 169static 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 183static bool trans_LXVH8X(DisasContext *ctx, arg_LXVH8X *a) 184{ 185 TCGv EA; 186 TCGv_i64 xth, xtl; 187 188 REQUIRE_VSX(ctx); 189 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 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 206static bool trans_LXVB16X(DisasContext *ctx, arg_LXVB16X *a) 207{ 208 TCGv EA; 209 TCGv_i128 data; 210 211 REQUIRE_VSX(ctx); 212 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 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) 224static 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 242static 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 254static 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 266static 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 278static 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 290static 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 304TRANS_FLAGS2(VSX, STXSDX, do_stxs, gen_qemu_st64_i64); 305TRANS_FLAGS2(ISA300, STXSIBX, do_stxs, gen_qemu_st8_i64); 306TRANS_FLAGS2(ISA300, STXSIHX, do_stxs, gen_qemu_st16_i64); 307TRANS_FLAGS2(VSX207, STXSIWX, do_stxs, gen_qemu_st32_i64); 308TRANS_FLAGS2(VSX207, STXSSPX, do_stxs, gen_qemu_st32fs); 309 310static bool trans_STXVD2X(DisasContext *ctx, arg_STXVD2X *a) 311{ 312 TCGv EA; 313 TCGv_i64 t0; 314 315 REQUIRE_VSX(ctx); 316 REQUIRE_INSNS_FLAGS2(ctx, VSX); 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 329static bool trans_STXVW4X(DisasContext *ctx, arg_STXVW4X *a) 330{ 331 TCGv EA; 332 TCGv_i64 xsh, xsl; 333 334 REQUIRE_VSX(ctx); 335 REQUIRE_INSNS_FLAGS2(ctx, VSX); 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 362static bool trans_STXVH8X(DisasContext *ctx, arg_STXVH8X *a) 363{ 364 TCGv EA; 365 TCGv_i64 xsh, xsl; 366 367 REQUIRE_VSX(ctx); 368 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 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 392static bool trans_STXVB16X(DisasContext *ctx, arg_STXVB16X *a) 393{ 394 TCGv EA; 395 TCGv_i128 data; 396 397 REQUIRE_VSX(ctx); 398 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 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 409static 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 429static 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 449static 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) 470static 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 489static 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 508static 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 527static 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 554static 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) \ 590static 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 627VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP) 628VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP) 629VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP) 630VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP) 631 632#define VSX_SCALAR_MOVE_QP(name, op, sgn_mask) \ 633static 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 674VSX_SCALAR_MOVE_QP(xsabsqp, OP_ABS, SGN_MASK_DP) 675VSX_SCALAR_MOVE_QP(xsnabsqp, OP_NABS, SGN_MASK_DP) 676VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP) 677VSX_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 685TCG_OP_IMM_i64(do_xvabssp_i64, tcg_gen_andi_i64, ~SGN_MASK_SP) 686TCG_OP_IMM_i64(do_xvnabssp_i64, tcg_gen_ori_i64, SGN_MASK_SP) 687TCG_OP_IMM_i64(do_xvnegsp_i64, tcg_gen_xori_i64, SGN_MASK_SP) 688TCG_OP_IMM_i64(do_xvabsdp_i64, tcg_gen_andi_i64, ~SGN_MASK_DP) 689TCG_OP_IMM_i64(do_xvnabsdp_i64, tcg_gen_ori_i64, SGN_MASK_DP) 690TCG_OP_IMM_i64(do_xvnegdp_i64, tcg_gen_xori_i64, SGN_MASK_DP) 691#undef TCG_OP_IMM_i64 692 693static 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 700static 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 705static 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 710static 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 715static 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 739TRANS(XVABSDP, do_vsx_msb_op, MO_64, do_xvabs_vec, do_xvabsdp_i64) 740TRANS(XVNABSDP, do_vsx_msb_op, MO_64, do_xvnabs_vec, do_xvnabsdp_i64) 741TRANS(XVNEGDP, do_vsx_msb_op, MO_64, do_xvneg_vec, do_xvnegdp_i64) 742TRANS(XVABSSP, do_vsx_msb_op, MO_32, do_xvabs_vec, do_xvabssp_i64) 743TRANS(XVNABSSP, do_vsx_msb_op, MO_32, do_xvnabs_vec, do_xvnabssp_i64) 744TRANS(XVNEGSP, do_vsx_msb_op, MO_32, do_xvneg_vec, do_xvnegsp_i64) 745 746static 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 753static 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 760static 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 766static 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 796TRANS(XVCPSGNSP, do_xvcpsgn, MO_32) 797TRANS(XVCPSGNDP, do_xvcpsgn, MO_64) 798 799static 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 813TRANS_FLAGS2(VSX, XVCMPEQSP, do_cmp, gen_helper_XVCMPEQSP); 814TRANS_FLAGS2(VSX, XVCMPGTSP, do_cmp, gen_helper_XVCMPGTSP); 815TRANS_FLAGS2(VSX, XVCMPGESP, do_cmp, gen_helper_XVCMPGESP); 816TRANS_FLAGS2(ISA300, XVCMPNESP, do_cmp, gen_helper_XVCMPNESP); 817TRANS_FLAGS2(VSX, XVCMPEQDP, do_cmp, gen_helper_XVCMPEQDP); 818TRANS_FLAGS2(VSX, XVCMPGTDP, do_cmp, gen_helper_XVCMPGTDP); 819TRANS_FLAGS2(VSX, XVCMPGEDP, do_cmp, gen_helper_XVCMPGEDP); 820TRANS_FLAGS2(ISA300, XVCMPNEDP, do_cmp, gen_helper_XVCMPNEDP); 821 822static 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 838static 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 852TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP) 853TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP) 854TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ) 855TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ) 856 857#define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \ 858static 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) \ 870static 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) \ 883static 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) \ 898static 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) \ 912static 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) \ 928static 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) \ 943static 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) \ 958static 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 974GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300) 975GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300) 976GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300) 977GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX) 978GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX) 979GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX) 980GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX) 981GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX) 982GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300) 983GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300) 984GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX) 985GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX) 986GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX) 987GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX) 988GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300) 989GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX) 990GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300) 991GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207) 992GEN_VSX_HELPER_R2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300) 993GEN_VSX_HELPER_R2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300) 994GEN_VSX_HELPER_R2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300) 995GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300) 996GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300) 997GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300) 998GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX) 999 1000/* test if +Inf */ 1001static 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 */ 1009static 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 */ 1018static 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 */ 1028static 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 */ 1035static 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 */ 1043static 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 */ 1052static 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 */ 1064static 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 */ 1077static 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 */ 1091static 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 1100static 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 1166TRANS_FLAGS2(VSX, XVTSTDCSP, do_xvtstdc, MO_32) 1167TRANS_FLAGS2(VSX, XVTSTDCDP, do_xvtstdc, MO_64) 1168 1169static 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 1180TRANS_FLAGS2(ISA300, XSTSTDCSP, do_XX2_bf_uim, true, gen_helper_XSTSTDCSP) 1181TRANS_FLAGS2(ISA300, XSTSTDCDP, do_XX2_bf_uim, true, gen_helper_XSTSTDCDP) 1182TRANS_FLAGS2(ISA300, XSTSTDCQP, do_XX2_bf_uim, false, gen_helper_XSTSTDCQP) 1183 1184bool trans_XSCVSPDPN(DisasContext *ctx, arg_XX2 *a) 1185{ 1186 TCGv_i64 tmp; 1187 1188 REQUIRE_INSNS_FLAGS2(ctx, VSX207); 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 1201GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX) 1202GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX) 1203GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX) 1204GEN_VSX_HELPER_X2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX) 1205GEN_VSX_HELPER_X2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX) 1206GEN_VSX_HELPER_R2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300) 1207GEN_VSX_HELPER_X2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX) 1208GEN_VSX_HELPER_X2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX) 1209GEN_VSX_HELPER_X2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX) 1210GEN_VSX_HELPER_X2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX) 1211GEN_VSX_HELPER_X2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX) 1212GEN_VSX_HELPER_X2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX) 1213GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207) 1214GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300) 1215GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300) 1216GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300) 1217GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300) 1218GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207) 1219GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207) 1220GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207) 1221GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207) 1222GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207) 1223 1224GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX) 1225GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX) 1226GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX) 1227GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX) 1228GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX) 1229GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX) 1230GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX) 1231GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX) 1232GEN_VSX_HELPER_X2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX) 1233GEN_VSX_HELPER_X2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX) 1234GEN_VSX_HELPER_X2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX) 1235GEN_VSX_HELPER_X2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX) 1236GEN_VSX_HELPER_X2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX) 1237GEN_VSX_HELPER_X2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX) 1238GEN_VSX_HELPER_X2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX) 1239GEN_VSX_HELPER_X2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX) 1240GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX) 1241GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX) 1242GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX) 1243 1244GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX) 1245GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX) 1246GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX) 1247GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX) 1248GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX) 1249GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX) 1250GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300) 1251GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300) 1252GEN_VSX_HELPER_X2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX) 1253GEN_VSX_HELPER_X2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX) 1254GEN_VSX_HELPER_X2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX) 1255GEN_VSX_HELPER_X2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX) 1256GEN_VSX_HELPER_X2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX) 1257GEN_VSX_HELPER_X2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX) 1258GEN_VSX_HELPER_X2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX) 1259GEN_VSX_HELPER_X2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX) 1260GEN_VSX_HELPER_X2(xvrspi, 0x12, 0x08, 0, PPC2_VSX) 1261GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX) 1262GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX) 1263GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX) 1264GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX) 1265 1266static 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 1281static 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 1296static 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 1323static 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 1339typedef void (*xxgenpcv_genfn)(TCGv_ptr, TCGv_ptr); 1340 1341static 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 1373XXGENPCV(XXGENPCVBM) 1374XXGENPCV(XXGENPCVHM) 1375XXGENPCV(XXGENPCVWM) 1376XXGENPCV(XXGENPCVDM) 1377#undef XXGENPCV 1378 1379static 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 1393static 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 1404TRANS_FLAGS2(VSX, XSMADDADP, do_xsmadd_XX3, true, gen_helper_XSMADDDP) 1405TRANS_FLAGS2(VSX, XSMADDMDP, do_xsmadd_XX3, false, gen_helper_XSMADDDP) 1406TRANS_FLAGS2(VSX, XSMSUBADP, do_xsmadd_XX3, true, gen_helper_XSMSUBDP) 1407TRANS_FLAGS2(VSX, XSMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSMSUBDP) 1408TRANS_FLAGS2(VSX, XSNMADDADP, do_xsmadd_XX3, true, gen_helper_XSNMADDDP) 1409TRANS_FLAGS2(VSX, XSNMADDMDP, do_xsmadd_XX3, false, gen_helper_XSNMADDDP) 1410TRANS_FLAGS2(VSX, XSNMSUBADP, do_xsmadd_XX3, true, gen_helper_XSNMSUBDP) 1411TRANS_FLAGS2(VSX, XSNMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSNMSUBDP) 1412TRANS_FLAGS2(VSX207, XSMADDASP, do_xsmadd_XX3, true, gen_helper_XSMADDSP) 1413TRANS_FLAGS2(VSX207, XSMADDMSP, do_xsmadd_XX3, false, gen_helper_XSMADDSP) 1414TRANS_FLAGS2(VSX207, XSMSUBASP, do_xsmadd_XX3, true, gen_helper_XSMSUBSP) 1415TRANS_FLAGS2(VSX207, XSMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSMSUBSP) 1416TRANS_FLAGS2(VSX207, XSNMADDASP, do_xsmadd_XX3, true, gen_helper_XSNMADDSP) 1417TRANS_FLAGS2(VSX207, XSNMADDMSP, do_xsmadd_XX3, false, gen_helper_XSNMADDSP) 1418TRANS_FLAGS2(VSX207, XSNMSUBASP, do_xsmadd_XX3, true, gen_helper_XSNMSUBSP) 1419TRANS_FLAGS2(VSX207, XSNMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSNMSUBSP) 1420 1421static 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 1441TRANS(XSMADDQP, do_xsmadd_X, gen_helper_XSMADDQP, gen_helper_XSMADDQPO) 1442TRANS(XSMSUBQP, do_xsmadd_X, gen_helper_XSMSUBQP, gen_helper_XSMSUBQPO) 1443TRANS(XSNMADDQP, do_xsmadd_X, gen_helper_XSNMADDQP, gen_helper_XSNMADDQPO) 1444TRANS(XSNMSUBQP, do_xsmadd_X, gen_helper_XSNMSUBQP, gen_helper_XSNMSUBQPO) 1445 1446#define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type) \ 1447static 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 1472GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX) 1473GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX) 1474GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX) 1475GEN_VSX_HELPER_VSX_MADD(xvnmsubdp, 0x04, 0x1E, 0x1F, 0, PPC2_VSX) 1476GEN_VSX_HELPER_VSX_MADD(xvmaddsp, 0x04, 0x08, 0x09, 0, PPC2_VSX) 1477GEN_VSX_HELPER_VSX_MADD(xvmsubsp, 0x04, 0x0A, 0x0B, 0, PPC2_VSX) 1478GEN_VSX_HELPER_VSX_MADD(xvnmaddsp, 0x04, 0x18, 0x19, 0, PPC2_VSX) 1479GEN_VSX_HELPER_VSX_MADD(xvnmsubsp, 0x04, 0x1A, 0x1B, 0, PPC2_VSX) 1480 1481static 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 1505static 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 1528static 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 1555static 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 1578static 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 1588TRANS_FLAGS2(VSX, XXLAND, do_logical_op, MO_64, tcg_gen_gvec_and); 1589TRANS_FLAGS2(VSX, XXLANDC, do_logical_op, MO_64, tcg_gen_gvec_andc); 1590TRANS_FLAGS2(VSX, XXLOR, do_logical_op, MO_64, tcg_gen_gvec_or); 1591TRANS_FLAGS2(VSX, XXLXOR, do_logical_op, MO_64, tcg_gen_gvec_xor); 1592TRANS_FLAGS2(VSX, XXLNOR, do_logical_op, MO_64, tcg_gen_gvec_nor); 1593TRANS_FLAGS2(VSX207, XXLEQV, do_logical_op, MO_64, tcg_gen_gvec_eqv); 1594TRANS_FLAGS2(VSX207, XXLNAND, do_logical_op, MO_64, tcg_gen_gvec_nand); 1595TRANS_FLAGS2(VSX207, XXLORC, do_logical_op, MO_64, tcg_gen_gvec_orc); 1596 1597#define VSX_XXMRG(name, high) \ 1598static 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 1622VSX_XXMRG(xxmrghw, 1) 1623VSX_XXMRG(xxmrglw, 0) 1624 1625static 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 1636static 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 1655static 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 1666static 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 1676static 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 1686static 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 1703static 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 1746static 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 1779static 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 1834static 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 1858TRANS(XXEXTRACTUW, do_vsx_extract_insert, gen_helper_XXEXTRACTUW) 1859TRANS(XXINSERTW, do_vsx_extract_insert, gen_helper_XXINSERTW) 1860 1861#ifdef TARGET_PPC64 1862static 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 1875static 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 1896static 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 1917static 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 1949static 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 1973static 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 2007static 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 2045static 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 2076static 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 2102static 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 2126static 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 2140static 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 2178static 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 2221static 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 2232static 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 2245static 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 2256static 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 2285static 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 2290static 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 2301static 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 2324static 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 2329static 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 2340TRANS_FLAGS2(ISA300, LXSD, do_lstxsd_DS, false) 2341TRANS_FLAGS2(ISA300, STXSD, do_lstxsd_DS, true) 2342TRANS_FLAGS2(ISA300, LXSSP, do_lstxssp_DS, false) 2343TRANS_FLAGS2(ISA300, STXSSP, do_lstxssp_DS, true) 2344TRANS_FLAGS2(ISA300, STXV, do_lstxv_D, true, false) 2345TRANS_FLAGS2(ISA300, LXV, do_lstxv_D, false, false) 2346TRANS_FLAGS2(ISA310, STXVP, do_lstxv_D, true, true) 2347TRANS_FLAGS2(ISA310, LXVP, do_lstxv_D, false, true) 2348TRANS_FLAGS2(ISA300, STXVX, do_lstxv_X, true, false) 2349TRANS_FLAGS2(ISA300, LXVX, do_lstxv_X, false, false) 2350TRANS_FLAGS2(ISA310, STXVPX, do_lstxv_X, true, true) 2351TRANS_FLAGS2(ISA310, LXVPX, do_lstxv_X, false, true) 2352TRANS64_FLAGS2(ISA310, PLXSD, do_plstxsd_PLS_D, false) 2353TRANS64_FLAGS2(ISA310, PSTXSD, do_plstxsd_PLS_D, true) 2354TRANS64_FLAGS2(ISA310, PLXSSP, do_plstxssp_PLS_D, false) 2355TRANS64_FLAGS2(ISA310, PSTXSSP, do_plstxssp_PLS_D, true) 2356TRANS64_FLAGS2(ISA310, PSTXV, do_lstxv_PLS_D, true, false) 2357TRANS64_FLAGS2(ISA310, PLXV, do_lstxv_PLS_D, false, false) 2358TRANS64_FLAGS2(ISA310, PSTXVP, do_lstxv_PLS_D, true, true) 2359TRANS64_FLAGS2(ISA310, PLXVP, do_lstxv_PLS_D, false, true) 2360 2361static 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 2384TRANS_FLAGS2(ISA310, LXVRBX, do_lstrm, DEF_MEMOP(MO_UB), false) 2385TRANS_FLAGS2(ISA310, LXVRHX, do_lstrm, DEF_MEMOP(MO_UW), false) 2386TRANS_FLAGS2(ISA310, LXVRWX, do_lstrm, DEF_MEMOP(MO_UL), false) 2387TRANS_FLAGS2(ISA310, LXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), false) 2388TRANS_FLAGS2(ISA310, STXVRBX, do_lstrm, DEF_MEMOP(MO_UB), true) 2389TRANS_FLAGS2(ISA310, STXVRHX, do_lstrm, DEF_MEMOP(MO_UW), true) 2390TRANS_FLAGS2(ISA310, STXVRWX, do_lstrm, DEF_MEMOP(MO_UL), true) 2391TRANS_FLAGS2(ISA310, STXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), true) 2392 2393static 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 2438static 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 2483static 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 2609static 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 2617static 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 2658TRANS(XXBLENDVB, do_xxblendv, MO_8) 2659TRANS(XXBLENDVH, do_xxblendv, MO_16) 2660TRANS(XXBLENDVW, do_xxblendv, MO_32) 2661TRANS(XXBLENDVD, do_xxblendv, MO_64) 2662 2663static 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 2677TRANS_FLAGS2(ISA300, XSCMPEQDP, do_helper_XX3, gen_helper_XSCMPEQDP) 2678TRANS_FLAGS2(ISA300, XSCMPGEDP, do_helper_XX3, gen_helper_XSCMPGEDP) 2679TRANS_FLAGS2(ISA300, XSCMPGTDP, do_helper_XX3, gen_helper_XSCMPGTDP) 2680TRANS_FLAGS2(ISA300, XSMAXCDP, do_helper_XX3, gen_helper_XSMAXCDP) 2681TRANS_FLAGS2(ISA300, XSMINCDP, do_helper_XX3, gen_helper_XSMINCDP) 2682TRANS_FLAGS2(ISA300, XSMAXJDP, do_helper_XX3, gen_helper_XSMAXJDP) 2683TRANS_FLAGS2(ISA300, XSMINJDP, do_helper_XX3, gen_helper_XSMINJDP) 2684 2685TRANS_FLAGS2(VSX207, XSADDSP, do_helper_XX3, gen_helper_XSADDSP) 2686TRANS_FLAGS2(VSX207, XSSUBSP, do_helper_XX3, gen_helper_XSSUBSP) 2687TRANS_FLAGS2(VSX207, XSMULSP, do_helper_XX3, gen_helper_XSMULSP) 2688TRANS_FLAGS2(VSX207, XSDIVSP, do_helper_XX3, gen_helper_XSDIVSP) 2689 2690TRANS_FLAGS2(VSX, XSADDDP, do_helper_XX3, gen_helper_XSADDDP) 2691TRANS_FLAGS2(VSX, XSSUBDP, do_helper_XX3, gen_helper_XSSUBDP) 2692TRANS_FLAGS2(VSX, XSMULDP, do_helper_XX3, gen_helper_XSMULDP) 2693TRANS_FLAGS2(VSX, XSDIVDP, do_helper_XX3, gen_helper_XSDIVDP) 2694 2695TRANS_FLAGS2(VSX, XVADDSP, do_helper_XX3, gen_helper_XVADDSP) 2696TRANS_FLAGS2(VSX, XVSUBSP, do_helper_XX3, gen_helper_XVSUBSP) 2697TRANS_FLAGS2(VSX, XVMULSP, do_helper_XX3, gen_helper_XVMULSP) 2698TRANS_FLAGS2(VSX, XVDIVSP, do_helper_XX3, gen_helper_XVDIVSP) 2699 2700TRANS_FLAGS2(VSX, XVADDDP, do_helper_XX3, gen_helper_XVADDDP) 2701TRANS_FLAGS2(VSX, XVSUBDP, do_helper_XX3, gen_helper_XVSUBDP) 2702TRANS_FLAGS2(VSX, XVMULDP, do_helper_XX3, gen_helper_XVMULDP) 2703TRANS_FLAGS2(VSX, XVDIVDP, do_helper_XX3, gen_helper_XVDIVDP) 2704 2705TRANS_FLAGS2(VSX, XSMAXDP, do_helper_XX3, gen_helper_XSMAXDP) 2706TRANS_FLAGS2(VSX, XSMINDP, do_helper_XX3, gen_helper_XSMINDP) 2707TRANS_FLAGS2(VSX, XVMAXSP, do_helper_XX3, gen_helper_XVMAXSP) 2708TRANS_FLAGS2(VSX, XVMINSP, do_helper_XX3, gen_helper_XVMINSP) 2709TRANS_FLAGS2(VSX, XVMAXDP, do_helper_XX3, gen_helper_XVMAXDP) 2710TRANS_FLAGS2(VSX, XVMINDP, do_helper_XX3, gen_helper_XVMINDP) 2711 2712static 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 2725static 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 2734TRANS(XSCMPEQQP, do_xscmpqp, gen_helper_XSCMPEQQP) 2735TRANS(XSCMPGEQP, do_xscmpqp, gen_helper_XSCMPGEQP) 2736TRANS(XSCMPGTQP, do_xscmpqp, gen_helper_XSCMPGTQP) 2737TRANS(XSMAXCQP, do_xscmpqp, gen_helper_XSMAXCQP) 2738TRANS(XSMINCQP, do_xscmpqp, gen_helper_XSMINCQP) 2739 2740static 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 2754static 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 */ 2774static 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 2781static 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 2788static 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 2796static 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 2817TRANS(XVI4GER8, do_ger, gen_helper_XVI4GER8) 2818TRANS(XVI4GER8PP, do_ger, gen_helper_XVI4GER8PP) 2819TRANS(XVI8GER4, do_ger, gen_helper_XVI8GER4) 2820TRANS(XVI8GER4PP, do_ger, gen_helper_XVI8GER4PP) 2821TRANS(XVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP) 2822TRANS(XVI16GER2, do_ger, gen_helper_XVI16GER2) 2823TRANS(XVI16GER2PP, do_ger, gen_helper_XVI16GER2PP) 2824TRANS(XVI16GER2S, do_ger, gen_helper_XVI16GER2S) 2825TRANS(XVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP) 2826 2827TRANS64(PMXVI4GER8, do_ger, gen_helper_XVI4GER8) 2828TRANS64(PMXVI4GER8PP, do_ger, gen_helper_XVI4GER8PP) 2829TRANS64(PMXVI8GER4, do_ger, gen_helper_XVI8GER4) 2830TRANS64(PMXVI8GER4PP, do_ger, gen_helper_XVI8GER4PP) 2831TRANS64(PMXVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP) 2832TRANS64(PMXVI16GER2, do_ger, gen_helper_XVI16GER2) 2833TRANS64(PMXVI16GER2PP, do_ger, gen_helper_XVI16GER2PP) 2834TRANS64(PMXVI16GER2S, do_ger, gen_helper_XVI16GER2S) 2835TRANS64(PMXVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP) 2836 2837TRANS(XVBF16GER2, do_ger, gen_helper_XVBF16GER2) 2838TRANS(XVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP) 2839TRANS(XVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN) 2840TRANS(XVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP) 2841TRANS(XVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN) 2842 2843TRANS(XVF16GER2, do_ger, gen_helper_XVF16GER2) 2844TRANS(XVF16GER2PP, do_ger, gen_helper_XVF16GER2PP) 2845TRANS(XVF16GER2PN, do_ger, gen_helper_XVF16GER2PN) 2846TRANS(XVF16GER2NP, do_ger, gen_helper_XVF16GER2NP) 2847TRANS(XVF16GER2NN, do_ger, gen_helper_XVF16GER2NN) 2848 2849TRANS(XVF32GER, do_ger, gen_helper_XVF32GER) 2850TRANS(XVF32GERPP, do_ger, gen_helper_XVF32GERPP) 2851TRANS(XVF32GERPN, do_ger, gen_helper_XVF32GERPN) 2852TRANS(XVF32GERNP, do_ger, gen_helper_XVF32GERNP) 2853TRANS(XVF32GERNN, do_ger, gen_helper_XVF32GERNN) 2854 2855TRANS(XVF64GER, do_ger, gen_helper_XVF64GER) 2856TRANS(XVF64GERPP, do_ger, gen_helper_XVF64GERPP) 2857TRANS(XVF64GERPN, do_ger, gen_helper_XVF64GERPN) 2858TRANS(XVF64GERNP, do_ger, gen_helper_XVF64GERNP) 2859TRANS(XVF64GERNN, do_ger, gen_helper_XVF64GERNN) 2860 2861TRANS64(PMXVBF16GER2, do_ger, gen_helper_XVBF16GER2) 2862TRANS64(PMXVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP) 2863TRANS64(PMXVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN) 2864TRANS64(PMXVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP) 2865TRANS64(PMXVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN) 2866 2867TRANS64(PMXVF16GER2, do_ger, gen_helper_XVF16GER2) 2868TRANS64(PMXVF16GER2PP, do_ger, gen_helper_XVF16GER2PP) 2869TRANS64(PMXVF16GER2PN, do_ger, gen_helper_XVF16GER2PN) 2870TRANS64(PMXVF16GER2NP, do_ger, gen_helper_XVF16GER2NP) 2871TRANS64(PMXVF16GER2NN, do_ger, gen_helper_XVF16GER2NN) 2872 2873TRANS64(PMXVF32GER, do_ger, gen_helper_XVF32GER) 2874TRANS64(PMXVF32GERPP, do_ger, gen_helper_XVF32GERPP) 2875TRANS64(PMXVF32GERPN, do_ger, gen_helper_XVF32GERPN) 2876TRANS64(PMXVF32GERNP, do_ger, gen_helper_XVF32GERNP) 2877TRANS64(PMXVF32GERNN, do_ger, gen_helper_XVF32GERNN) 2878 2879TRANS64(PMXVF64GER, do_ger, gen_helper_XVF64GER) 2880TRANS64(PMXVF64GERPP, do_ger, gen_helper_XVF64GERPP) 2881TRANS64(PMXVF64GERPN, do_ger, gen_helper_XVF64GERPN) 2882TRANS64(PMXVF64GERNP, do_ger, gen_helper_XVF64GERNP) 2883TRANS64(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 2890