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