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