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