vmx-impl.c.inc (128838B)
1 /* 2 * translate/vmx-impl.c 3 * 4 * Altivec/VMX translation 5 */ 6 7 /*** Altivec vector extension ***/ 8 /* Altivec registers moves */ 9 10 static 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) \ 18 static 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) \ 53 static 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) \ 88 static 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) \ 109 static 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 129 GEN_VR_LDX(lvx, 0x07, 0x03); 130 /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */ 131 GEN_VR_LDX(lvxl, 0x07, 0x0B); 132 133 GEN_VR_LVE(bx, 0x07, 0x00, 1); 134 GEN_VR_LVE(hx, 0x07, 0x01, 2); 135 GEN_VR_LVE(wx, 0x07, 0x02, 4); 136 137 GEN_VR_STX(svx, 0x07, 0x07); 138 /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */ 139 GEN_VR_STX(svxl, 0x07, 0x0F); 140 141 GEN_VR_STVE(bx, 0x07, 0x04, 1); 142 GEN_VR_STVE(hx, 0x07, 0x05, 2); 143 GEN_VR_STVE(wx, 0x07, 0x06, 4); 144 145 static 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 164 static 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) \ 186 static 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 240 GEN_VX_VMUL10(vmul10uq, 0, 0); 241 GEN_VX_VMUL10(vmul10euq, 1, 0); 242 GEN_VX_VMUL10(vmul10cuq, 0, 1); 243 GEN_VX_VMUL10(vmul10ecuq, 1, 1); 244 245 #define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3) \ 246 static 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 */ 261 GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16); 262 GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17); 263 GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18); 264 GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19); 265 GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20); 266 GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26); 267 GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22); 268 GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21); 269 270 #define GEN_VXFORM(name, opc2, opc3) \ 271 static 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) \ 288 static 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) \ 298 static 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) \ 315 static 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) \ 340 static 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)\ 358 static 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) \ 378 static 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) \ 394 static 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 406 GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0); 407 GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0, \ 408 vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800) 409 GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1); 410 GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE, \ 411 vmul10ecuq, PPC_NONE, PPC2_ISA300) 412 GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2); 413 GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3); 414 GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16); 415 GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17); 416 GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18); 417 GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19); 418 GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0); 419 GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1); 420 GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2); 421 GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3); 422 GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4); 423 GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5); 424 GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6); 425 GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7); 426 GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8); 427 GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9); 428 GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10); 429 GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11); 430 GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12); 431 GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13); 432 GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14); 433 GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15); 434 GEN_VXFORM(vmrghb, 6, 0); 435 GEN_VXFORM(vmrghh, 6, 1); 436 GEN_VXFORM(vmrghw, 6, 2); 437 GEN_VXFORM(vmrglb, 6, 4); 438 GEN_VXFORM(vmrglh, 6, 5); 439 GEN_VXFORM(vmrglw, 6, 6); 440 441 static 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 465 static 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 */ 496 static 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 */ 534 static 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 */ 573 static 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 */ 620 static 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 */ 685 static 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 */ 741 static 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 */ 767 static 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 786 GEN_VXFORM_V(vmuluwm, MO_32, tcg_gen_gvec_mul, 4, 2); 787 GEN_VXFORM(vsrv, 2, 28); 788 GEN_VXFORM(vslv, 2, 29); 789 GEN_VXFORM(vslo, 6, 16); 790 GEN_VXFORM(vsro, 6, 17); 791 792 static 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 804 TRANS_FLAGS(ALTIVEC, VSLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shlv); 805 TRANS_FLAGS(ALTIVEC, VSLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shlv); 806 TRANS_FLAGS(ALTIVEC, VSLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shlv); 807 TRANS_FLAGS2(ALTIVEC_207, VSLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shlv); 808 809 TRANS_FLAGS(ALTIVEC, VSRB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shrv); 810 TRANS_FLAGS(ALTIVEC, VSRH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shrv); 811 TRANS_FLAGS(ALTIVEC, VSRW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shrv); 812 TRANS_FLAGS2(ALTIVEC_207, VSRD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shrv); 813 814 TRANS_FLAGS(ALTIVEC, VSRAB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_sarv); 815 TRANS_FLAGS(ALTIVEC, VSRAH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_sarv); 816 TRANS_FLAGS(ALTIVEC, VSRAW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_sarv); 817 TRANS_FLAGS2(ALTIVEC_207, VSRAD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_sarv); 818 819 TRANS_FLAGS(ALTIVEC, VRLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_rotlv) 820 TRANS_FLAGS(ALTIVEC, VRLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_rotlv) 821 TRANS_FLAGS(ALTIVEC, VRLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_rotlv) 822 TRANS_FLAGS2(ALTIVEC_207, VRLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_rotlv) 823 824 static 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 858 static 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 878 static 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 910 TRANS(VRLWNM, do_vrlnm, MO_32) 911 TRANS(VRLDNM, do_vrlnm, MO_64) 912 913 static 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 935 static 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 967 TRANS(VRLWMI, do_vrlmi, MO_32) 968 TRANS(VRLDMI, do_vrlmi, MO_64) 969 970 static 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 1037 TRANS_FLAGS2(ISA310, VSLQ, do_vector_shift_quad, false, false); 1038 TRANS_FLAGS2(ISA310, VSRQ, do_vector_shift_quad, true, false); 1039 TRANS_FLAGS2(ISA310, VSRAQ, do_vector_shift_quad, true, true); 1040 1041 static 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 1093 static 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 1163 TRANS(VRLQ, do_vector_rotl_quad, false, false) 1164 TRANS(VRLQNM, do_vector_rotl_quad, true, false) 1165 TRANS(VRLQMI, do_vector_rotl_quad, false, true) 1166 1167 #define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3) \ 1168 static 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 } \ 1179 static 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 1204 GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8); 1205 GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0, \ 1206 vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800) 1207 GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9); 1208 GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \ 1209 vmul10euq, PPC_NONE, PPC2_ISA300) 1210 GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10); 1211 GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12); 1212 GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13); 1213 GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14); 1214 GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24); 1215 GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25); 1216 GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26); 1217 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28); 1218 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29); 1219 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30); 1220 GEN_VXFORM_TRANS(vsl, 2, 7); 1221 GEN_VXFORM_TRANS(vsr, 2, 11); 1222 GEN_VXFORM_ENV(vpkuhum, 7, 0); 1223 GEN_VXFORM_ENV(vpkuwum, 7, 1); 1224 GEN_VXFORM_ENV(vpkudum, 7, 17); 1225 GEN_VXFORM_ENV(vpkuhus, 7, 2); 1226 GEN_VXFORM_ENV(vpkuwus, 7, 3); 1227 GEN_VXFORM_ENV(vpkudus, 7, 19); 1228 GEN_VXFORM_ENV(vpkshus, 7, 4); 1229 GEN_VXFORM_ENV(vpkswus, 7, 5); 1230 GEN_VXFORM_ENV(vpksdus, 7, 21); 1231 GEN_VXFORM_ENV(vpkshss, 7, 6); 1232 GEN_VXFORM_ENV(vpkswss, 7, 7); 1233 GEN_VXFORM_ENV(vpksdss, 7, 23); 1234 GEN_VXFORM(vpkpx, 7, 12); 1235 GEN_VXFORM_ENV(vsum4ubs, 4, 24); 1236 GEN_VXFORM_ENV(vsum4sbs, 4, 28); 1237 GEN_VXFORM_ENV(vsum4shs, 4, 25); 1238 GEN_VXFORM_ENV(vsum2sws, 4, 26); 1239 GEN_VXFORM_ENV(vsumsws, 4, 30); 1240 GEN_VXFORM_ENV(vaddfp, 5, 0); 1241 GEN_VXFORM_ENV(vsubfp, 5, 1); 1242 GEN_VXFORM_ENV(vmaxfp, 5, 16); 1243 GEN_VXFORM_ENV(vminfp, 5, 17); 1244 GEN_VXFORM_HETRO(vextublx, 6, 24) 1245 GEN_VXFORM_HETRO(vextuhlx, 6, 25) 1246 GEN_VXFORM_HETRO(vextuwlx, 6, 26) 1247 GEN_VXFORM_TRANS_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207, 1248 vextuwlx, PPC_NONE, PPC2_ISA300) 1249 GEN_VXFORM_HETRO(vextubrx, 6, 28) 1250 GEN_VXFORM_HETRO(vextuhrx, 6, 29) 1251 GEN_VXFORM_HETRO(vextuwrx, 6, 30) 1252 GEN_VXFORM_TRANS(lvsl, 6, 31) 1253 GEN_VXFORM_TRANS(lvsr, 6, 32) 1254 GEN_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) \ 1258 static 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) \ 1285 static 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 1306 static 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 1334 static 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 1348 TRANS_FLAGS(ALTIVEC, VCMPEQUB, do_vcmp, TCG_COND_EQ, MO_8) 1349 TRANS_FLAGS(ALTIVEC, VCMPEQUH, do_vcmp, TCG_COND_EQ, MO_16) 1350 TRANS_FLAGS(ALTIVEC, VCMPEQUW, do_vcmp, TCG_COND_EQ, MO_32) 1351 TRANS_FLAGS2(ALTIVEC_207, VCMPEQUD, do_vcmp, TCG_COND_EQ, MO_64) 1352 1353 TRANS_FLAGS(ALTIVEC, VCMPGTSB, do_vcmp, TCG_COND_GT, MO_8) 1354 TRANS_FLAGS(ALTIVEC, VCMPGTSH, do_vcmp, TCG_COND_GT, MO_16) 1355 TRANS_FLAGS(ALTIVEC, VCMPGTSW, do_vcmp, TCG_COND_GT, MO_32) 1356 TRANS_FLAGS2(ALTIVEC_207, VCMPGTSD, do_vcmp, TCG_COND_GT, MO_64) 1357 TRANS_FLAGS(ALTIVEC, VCMPGTUB, do_vcmp, TCG_COND_GTU, MO_8) 1358 TRANS_FLAGS(ALTIVEC, VCMPGTUH, do_vcmp, TCG_COND_GTU, MO_16) 1359 TRANS_FLAGS(ALTIVEC, VCMPGTUW, do_vcmp, TCG_COND_GTU, MO_32) 1360 TRANS_FLAGS2(ALTIVEC_207, VCMPGTUD, do_vcmp, TCG_COND_GTU, MO_64) 1361 1362 TRANS_FLAGS2(ISA300, VCMPNEB, do_vcmp, TCG_COND_NE, MO_8) 1363 TRANS_FLAGS2(ISA300, VCMPNEH, do_vcmp, TCG_COND_NE, MO_16) 1364 TRANS_FLAGS2(ISA300, VCMPNEW, do_vcmp, TCG_COND_NE, MO_32) 1365 1366 static 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 1385 static 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 1424 TRANS(VCMPNEZB, do_vcmpnez, MO_8) 1425 TRANS(VCMPNEZH, do_vcmpnez, MO_16) 1426 TRANS(VCMPNEZW, do_vcmpnez, MO_32) 1427 1428 static 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 1464 static 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 1500 TRANS(VCMPGTSQ, do_vcmpgtq, true) 1501 TRANS(VCMPGTUQ, do_vcmpgtq, false) 1502 1503 static 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 1545 TRANS(VCMPSQ, do_vcmpq, true) 1546 TRANS(VCMPUQ, do_vcmpq, false) 1547 1548 GEN_VXRFORM(vcmpeqfp, 3, 3) 1549 GEN_VXRFORM(vcmpgefp, 3, 7) 1550 GEN_VXRFORM(vcmpgtfp, 3, 11) 1551 GEN_VXRFORM(vcmpbfp, 3, 15) 1552 1553 static 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) \ 1567 static void glue(gen_, name)(DisasContext *ctx) { gen_vsplti(ctx, vece); } 1568 1569 GEN_VXFORM_VSPLTI(vspltisb, MO_8, 6, 12); 1570 GEN_VXFORM_VSPLTI(vspltish, MO_16, 6, 13); 1571 GEN_VXFORM_VSPLTI(vspltisw, MO_32, 6, 14); 1572 1573 #define GEN_VXFORM_NOA(name, opc2, opc3) \ 1574 static 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) \ 1589 static 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) \ 1605 static 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) \ 1620 static 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 } 1631 GEN_VXFORM_NOA(vupkhsb, 7, 8); 1632 GEN_VXFORM_NOA(vupkhsh, 7, 9); 1633 GEN_VXFORM_NOA(vupkhsw, 7, 25); 1634 GEN_VXFORM_NOA(vupklsb, 7, 10); 1635 GEN_VXFORM_NOA(vupklsh, 7, 11); 1636 GEN_VXFORM_NOA(vupklsw, 7, 27); 1637 GEN_VXFORM_NOA(vupkhpx, 7, 13); 1638 GEN_VXFORM_NOA(vupklpx, 7, 15); 1639 GEN_VXFORM_NOA_ENV(vrefp, 5, 4); 1640 GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5); 1641 GEN_VXFORM_NOA_ENV(vexptefp, 5, 6); 1642 GEN_VXFORM_NOA_ENV(vlogefp, 5, 7); 1643 GEN_VXFORM_NOA_ENV(vrfim, 5, 11); 1644 GEN_VXFORM_NOA_ENV(vrfin, 5, 8); 1645 GEN_VXFORM_NOA_ENV(vrfip, 5, 10); 1646 GEN_VXFORM_NOA_ENV(vrfiz, 5, 9); 1647 1648 static 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 */ 1662 static 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 */ 1669 static 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 1675 static 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 1709 TRANS(VPRTYBW, do_vx_vprtyb, MO_32) 1710 TRANS(VPRTYBD, do_vx_vprtyb, MO_64) 1711 TRANS(VPRTYBQ, do_vx_vprtyb, MO_128) 1712 1713 static 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) \ 1737 static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); } 1738 1739 #define GEN_VXFORM_UIMM_ENV(name, opc2, opc3) \ 1740 static 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) \ 1759 static 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 1781 GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8); 1782 GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9); 1783 GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10); 1784 GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15); 1785 GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14); 1786 GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12); 1787 GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8); 1788 GEN_VXFORM_UIMM_ENV(vcfux, 5, 12); 1789 GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13); 1790 GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14); 1791 GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15); 1792 GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE, 1793 vextractub, PPC_NONE, PPC2_ISA300); 1794 GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE, 1795 vextractuh, PPC_NONE, PPC2_ISA300); 1796 GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE, 1797 vextractuw, PPC_NONE, PPC2_ISA300); 1798 1799 static 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 1934 static 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 1961 TRANS(VEXTDUBVLX, do_vextdx, 1, false, gen_helper_VEXTDUBVLX) 1962 TRANS(VEXTDUHVLX, do_vextdx, 2, false, gen_helper_VEXTDUHVLX) 1963 TRANS(VEXTDUWVLX, do_vextdx, 4, false, gen_helper_VEXTDUWVLX) 1964 TRANS(VEXTDDVLX, do_vextdx, 8, false, gen_helper_VEXTDDVLX) 1965 1966 TRANS(VEXTDUBVRX, do_vextdx, 1, true, gen_helper_VEXTDUBVLX) 1967 TRANS(VEXTDUHVRX, do_vextdx, 2, true, gen_helper_VEXTDUHVLX) 1968 TRANS(VEXTDUWVRX, do_vextdx, 4, true, gen_helper_VEXTDUWVLX) 1969 TRANS(VEXTDDVRX, do_vextdx, 8, true, gen_helper_VEXTDDVLX) 1970 1971 static 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 1993 static 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 2007 static 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 2025 static 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 2035 static 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 2069 static 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 2086 TRANS(VINSBLX, do_vinsx_VX, 1, false, gen_helper_VINSBLX) 2087 TRANS(VINSHLX, do_vinsx_VX, 2, false, gen_helper_VINSHLX) 2088 TRANS(VINSWLX, do_vinsx_VX, 4, false, gen_helper_VINSWLX) 2089 TRANS(VINSDLX, do_vinsx_VX, 8, false, gen_helper_VINSDLX) 2090 2091 TRANS(VINSBRX, do_vinsx_VX, 1, true, gen_helper_VINSBLX) 2092 TRANS(VINSHRX, do_vinsx_VX, 2, true, gen_helper_VINSHLX) 2093 TRANS(VINSWRX, do_vinsx_VX, 4, true, gen_helper_VINSWLX) 2094 TRANS(VINSDRX, do_vinsx_VX, 8, true, gen_helper_VINSDLX) 2095 2096 TRANS(VINSW, do_vins_VX_uim4, 4, gen_helper_VINSWLX) 2097 TRANS(VINSD, do_vins_VX_uim4, 8, gen_helper_VINSDLX) 2098 2099 TRANS(VINSBVLX, do_vinsvx_VX, 1, false, gen_helper_VINSBLX) 2100 TRANS(VINSHVLX, do_vinsvx_VX, 2, false, gen_helper_VINSHLX) 2101 TRANS(VINSWVLX, do_vinsvx_VX, 4, false, gen_helper_VINSWLX) 2102 2103 TRANS(VINSBVRX, do_vinsvx_VX, 1, true, gen_helper_VINSBLX) 2104 TRANS(VINSHVRX, do_vinsvx_VX, 2, true, gen_helper_VINSHLX) 2105 TRANS(VINSWVRX, do_vinsvx_VX, 4, true, gen_helper_VINSWLX) 2106 2107 TRANS(VINSERTB, do_vinsert_VX_uim4, 1, gen_helper_VINSBLX) 2108 TRANS(VINSERTH, do_vinsert_VX_uim4, 2, gen_helper_VINSHLX) 2109 TRANS(VINSERTW, do_vinsert_VX_uim4, 4, gen_helper_VINSWLX) 2110 TRANS(VINSERTD, do_vinsert_VX_uim4, 8, gen_helper_VINSDLX) 2111 2112 static 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 2131 static 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 2164 static 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 2197 static 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 2208 TRANS(VEXPANDBM, do_vexpand, MO_8) 2209 TRANS(VEXPANDHM, do_vexpand, MO_16) 2210 TRANS(VEXPANDWM, do_vexpand, MO_32) 2211 TRANS(VEXPANDDM, do_vexpand, MO_64) 2212 2213 static 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 2231 static 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 2290 TRANS(VEXTRACTBM, do_vextractm, MO_8) 2291 TRANS(VEXTRACTHM, do_vextractm, MO_16) 2292 TRANS(VEXTRACTWM, do_vextractm, MO_32) 2293 TRANS(VEXTRACTDM, do_vextractm, MO_64) 2294 2295 static 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 2313 static 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 2379 TRANS(MTVSRBM, do_mtvsrm, MO_8) 2380 TRANS(MTVSRHM, do_mtvsrm, MO_16) 2381 TRANS(MTVSRWM, do_mtvsrm, MO_32) 2382 TRANS(MTVSRDM, do_mtvsrm, MO_64) 2383 2384 static 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 2403 static 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 2428 static 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 2455 TRANS(VCNTMBB, do_vcntmb, MO_8) 2456 TRANS(VCNTMBH, do_vcntmb, MO_16) 2457 TRANS(VCNTMBW, do_vcntmb, MO_32) 2458 TRANS(VCNTMBD, do_vcntmb, MO_64) 2459 2460 static 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 2485 TRANS(VSTRIBL, do_vstri, gen_helper_VSTRIBL) 2486 TRANS(VSTRIBR, do_vstri, gen_helper_VSTRIBR) 2487 TRANS(VSTRIHL, do_vstri, gen_helper_VSTRIHL) 2488 TRANS(VSTRIHR, do_vstri, gen_helper_VSTRIHR) 2489 2490 static 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 2543 TRANS(VCLRLB, do_vclrb, false) 2544 TRANS(VCLRRB, do_vclrb, true) 2545 2546 #define GEN_VAFORM_PAIRED(name0, name1, opc2) \ 2547 static 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 2569 GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23) 2570 2571 static 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 2590 TRANS_FLAGS2(ALTIVEC_207, VADDECUQ, do_va_helper, gen_helper_VADDECUQ) 2591 TRANS_FLAGS2(ALTIVEC_207, VADDEUQM, do_va_helper, gen_helper_VADDEUQM) 2592 2593 TRANS_FLAGS2(ALTIVEC_207, VSUBEUQM, do_va_helper, gen_helper_VSUBEUQM) 2594 TRANS_FLAGS2(ALTIVEC_207, VSUBECUQ, do_va_helper, gen_helper_VSUBECUQ) 2595 2596 TRANS_FLAGS(ALTIVEC, VPERM, do_va_helper, gen_helper_VPERM) 2597 TRANS_FLAGS2(ISA300, VPERMR, do_va_helper, gen_helper_VPERMR) 2598 2599 static 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 2606 static 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 2629 static 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 2641 TRANS_FLAGS(ALTIVEC, VMSUMUBM, do_va_helper, gen_helper_VMSUMUBM) 2642 TRANS_FLAGS(ALTIVEC, VMSUMMBM, do_va_helper, gen_helper_VMSUMMBM) 2643 TRANS_FLAGS(ALTIVEC, VMSUMSHM, do_va_helper, gen_helper_VMSUMSHM) 2644 TRANS_FLAGS(ALTIVEC, VMSUMUHM, do_va_helper, gen_helper_VMSUMUHM) 2645 2646 static 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 2665 TRANS_FLAGS(ALTIVEC, VMSUMUHS, do_va_env_helper, gen_helper_VMSUMUHS) 2666 TRANS_FLAGS(ALTIVEC, VMSUMSHS, do_va_env_helper, gen_helper_VMSUMSHS) 2667 2668 TRANS_FLAGS(ALTIVEC, VMHADDSHS, do_va_env_helper, gen_helper_VMHADDSHS) 2669 TRANS_FLAGS(ALTIVEC, VMHRADDSHS, do_va_env_helper, gen_helper_VMHRADDSHS) 2670 2671 GEN_VXFORM_NOA(vclzb, 1, 28) 2672 GEN_VXFORM_NOA(vclzh, 1, 29) 2673 GEN_VXFORM_TRANS(vclzw, 1, 30) 2674 GEN_VXFORM_TRANS(vclzd, 1, 31) 2675 2676 static 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 2686 TRANS(VNEGW, do_vneg, MO_32) 2687 TRANS(VNEGD, do_vneg, MO_64) 2688 2689 static 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 2694 static 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 2699 static 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 2705 static 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 2735 TRANS(VEXTSB2W, do_vexts, MO_32, 24); 2736 TRANS(VEXTSH2W, do_vexts, MO_32, 16); 2737 TRANS(VEXTSB2D, do_vexts, MO_64, 56); 2738 TRANS(VEXTSH2D, do_vexts, MO_64, 48); 2739 TRANS(VEXTSW2D, do_vexts, MO_64, 32); 2740 2741 static 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 2759 GEN_VXFORM_NOA_2(vctzb, 1, 24, 28) 2760 GEN_VXFORM_NOA_2(vctzh, 1, 24, 29) 2761 GEN_VXFORM_NOA_2(vctzw, 1, 24, 30) 2762 GEN_VXFORM_NOA_2(vctzd, 1, 24, 31) 2763 GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0) 2764 GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1) 2765 GEN_VXFORM_NOA(vpopcntb, 1, 28) 2766 GEN_VXFORM_NOA(vpopcnth, 1, 29) 2767 GEN_VXFORM_NOA(vpopcntw, 1, 30) 2768 GEN_VXFORM_NOA(vpopcntd, 1, 31) 2769 GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \ 2770 vpopcntb, PPC_NONE, PPC2_ALTIVEC_207) 2771 GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \ 2772 vpopcnth, PPC_NONE, PPC2_ALTIVEC_207) 2773 GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \ 2774 vpopcntw, PPC_NONE, PPC2_ALTIVEC_207) 2775 GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \ 2776 vpopcntd, PPC_NONE, PPC2_ALTIVEC_207) 2777 GEN_VXFORM(vbpermd, 6, 23); 2778 GEN_VXFORM(vbpermq, 6, 21); 2779 GEN_VXFORM_TRANS(vgbbd, 6, 20); 2780 GEN_VXFORM(vpmsumb, 4, 16) 2781 GEN_VXFORM(vpmsumh, 4, 17) 2782 GEN_VXFORM(vpmsumw, 4, 18) 2783 2784 #define GEN_BCD(op) \ 2785 static 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) \ 2810 static 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 2832 GEN_BCD(bcdadd) 2833 GEN_BCD(bcdsub) 2834 GEN_BCD2(bcdcfn) 2835 GEN_BCD2(bcdctn) 2836 GEN_BCD2(bcdcfz) 2837 GEN_BCD2(bcdctz) 2838 GEN_BCD2(bcdcfsq) 2839 GEN_BCD2(bcdctsq) 2840 GEN_BCD2(bcdsetsgn) 2841 GEN_BCD(bcdcpsgn); 2842 GEN_BCD(bcds); 2843 GEN_BCD(bcdus); 2844 GEN_BCD(bcdsr); 2845 GEN_BCD(bcdtrunc); 2846 GEN_BCD(bcdutrunc); 2847 2848 static 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 2878 static 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 2906 GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \ 2907 xpnd04_2, PPC_NONE, PPC2_ISA300) 2908 2909 GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \ 2910 bcdadd, PPC_NONE, PPC2_ALTIVEC_207) 2911 GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \ 2912 bcdadd, PPC_NONE, PPC2_ALTIVEC_207) 2913 GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \ 2914 bcdsub, PPC_NONE, PPC2_ALTIVEC_207) 2915 GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \ 2916 bcdsub, PPC_NONE, PPC2_ALTIVEC_207) 2917 GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \ 2918 bcdcpsgn, PPC_NONE, PPC2_ISA300) 2919 GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \ 2920 bcds, PPC_NONE, PPC2_ISA300) 2921 GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \ 2922 bcdus, PPC_NONE, PPC2_ISA300) 2923 GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \ 2924 bcdtrunc, PPC_NONE, PPC2_ISA300) 2925 2926 static 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 2940 GEN_VXFORM(vcipher, 4, 20) 2941 GEN_VXFORM(vcipherlast, 4, 20) 2942 GEN_VXFORM(vncipher, 4, 21) 2943 GEN_VXFORM(vncipherlast, 4, 21) 2944 2945 GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207, 2946 vcipherlast, PPC_NONE, PPC2_ALTIVEC_207) 2947 GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207, 2948 vncipherlast, PPC_NONE, PPC2_ALTIVEC_207) 2949 2950 #define VSHASIGMA(op) \ 2951 static 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 2968 VSHASIGMA(vshasigmaw) 2969 VSHASIGMA(vshasigmad) 2970 2971 GEN_VXFORM3(vpermxor, 22, 0xFF) 2972 GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE, 2973 vpermxor, PPC_NONE, PPC2_ALTIVEC_207) 2974 2975 static 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 2991 static 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 3007 static 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 3023 static 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 3039 static 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 3055 static 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 3089 static 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 3142 static 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 3159 TRANS_FLAGS2(ALTIVEC_207, VADDCUQ, do_vx_helper, gen_helper_VADDCUQ) 3160 TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, gen_helper_VADDUQM) 3161 3162 TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD) 3163 3164 TRANS_FLAGS2(ALTIVEC_207, VSUBCUQ, do_vx_helper, gen_helper_VSUBCUQ) 3165 TRANS_FLAGS2(ALTIVEC_207, VSUBUQM, do_vx_helper, gen_helper_VSUBUQM) 3166 3167 static 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 3174 static 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 3180 static 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 3186 static 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 3191 static 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 3221 TRANS(VSUBCUW, do_vx_vaddsubcuw, 0) 3222 TRANS(VADDCUW, do_vx_vaddsubcuw, 1) 3223 3224 static 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 3249 static 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 3260 TRANS_FLAGS(ALTIVEC, VMULESB, do_vx_helper, gen_helper_VMULESB) 3261 TRANS_FLAGS(ALTIVEC, VMULOSB, do_vx_helper, gen_helper_VMULOSB) 3262 TRANS_FLAGS(ALTIVEC, VMULEUB, do_vx_helper, gen_helper_VMULEUB) 3263 TRANS_FLAGS(ALTIVEC, VMULOUB, do_vx_helper, gen_helper_VMULOUB) 3264 TRANS_FLAGS(ALTIVEC, VMULESH, do_vx_helper, gen_helper_VMULESH) 3265 TRANS_FLAGS(ALTIVEC, VMULOSH, do_vx_helper, gen_helper_VMULOSH) 3266 TRANS_FLAGS(ALTIVEC, VMULEUH, do_vx_helper, gen_helper_VMULEUH) 3267 TRANS_FLAGS(ALTIVEC, VMULOUH, do_vx_helper, gen_helper_VMULOUH) 3268 TRANS_FLAGS2(ALTIVEC_207, VMULESW, do_vx_helper, gen_helper_VMULESW) 3269 TRANS_FLAGS2(ALTIVEC_207, VMULOSW, do_vx_helper, gen_helper_VMULOSW) 3270 TRANS_FLAGS2(ALTIVEC_207, VMULEUW, do_vx_helper, gen_helper_VMULEUW) 3271 TRANS_FLAGS2(ALTIVEC_207, VMULOUW, do_vx_helper, gen_helper_VMULOUW) 3272 TRANS_FLAGS2(ISA310, VMULESD, do_vx_vmuleo, true , tcg_gen_muls2_i64) 3273 TRANS_FLAGS2(ISA310, VMULOSD, do_vx_vmuleo, false, tcg_gen_muls2_i64) 3274 TRANS_FLAGS2(ISA310, VMULEUD, do_vx_vmuleo, true , tcg_gen_mulu2_i64) 3275 TRANS_FLAGS2(ISA310, VMULOUD, do_vx_vmuleo, false, tcg_gen_mulu2_i64) 3276 3277 static 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 3311 static 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 3325 static 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 3356 TRANS(VMULHSW, do_vx_mulh, true , do_vx_vmulhw_i64) 3357 TRANS(VMULHSD, do_vx_mulh, true , do_vx_vmulhd_i64) 3358 TRANS(VMULHUW, do_vx_mulh, false, do_vx_vmulhw_i64) 3359 TRANS(VMULHUD, do_vx_mulh, false, do_vx_vmulhd_i64) 3360 3361 static 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 3374 QEMU_FLATTEN 3375 static 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 3380 QEMU_FLATTEN 3381 static 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 3386 static 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 3448 TRANS_FLAGS(ALTIVEC, VAVGSB, do_vx_vavg, 1, MO_8) 3449 TRANS_FLAGS(ALTIVEC, VAVGSH, do_vx_vavg, 1, MO_16) 3450 TRANS_FLAGS(ALTIVEC, VAVGSW, do_vx_vavg, 1, MO_32) 3451 TRANS_FLAGS(ALTIVEC, VAVGUB, do_vx_vavg, 0, MO_8) 3452 TRANS_FLAGS(ALTIVEC, VAVGUH, do_vx_vavg, 0, MO_16) 3453 TRANS_FLAGS(ALTIVEC, VAVGUW, do_vx_vavg, 0, MO_32) 3454 3455 static 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 3462 static 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 3497 TRANS_FLAGS2(ISA300, VABSDUB, do_vabsdu, MO_8) 3498 TRANS_FLAGS2(ISA300, VABSDUH, do_vabsdu, MO_16) 3499 TRANS_FLAGS2(ISA300, VABSDUW, do_vabsdu, MO_32) 3500 3501 static 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) \ 3520 static 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) \ 3529 static 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) \ 3546 static 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) \ 3555 static 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 3571 DIVS32(do_divsw, tcg_gen_div_i32) 3572 DIVU32(do_divuw, tcg_gen_divu_i32) 3573 DIVS64(do_divsd, tcg_gen_div_i64) 3574 DIVU64(do_divud, tcg_gen_divu_i64) 3575 3576 TRANS_FLAGS2(ISA310, VDIVSW, do_vdiv_vmod, MO_32, do_divsw, NULL) 3577 TRANS_FLAGS2(ISA310, VDIVUW, do_vdiv_vmod, MO_32, do_divuw, NULL) 3578 TRANS_FLAGS2(ISA310, VDIVSD, do_vdiv_vmod, MO_64, NULL, do_divsd) 3579 TRANS_FLAGS2(ISA310, VDIVUD, do_vdiv_vmod, MO_64, NULL, do_divud) 3580 TRANS_FLAGS2(ISA310, VDIVSQ, do_vx_helper, gen_helper_VDIVSQ) 3581 TRANS_FLAGS2(ISA310, VDIVUQ, do_vx_helper, gen_helper_VDIVUQ) 3582 3583 static 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 3604 static 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 3625 DIVS32(do_divesw, do_dives_i32) 3626 DIVU32(do_diveuw, do_diveu_i32) 3627 3628 DIVS32(do_modsw, tcg_gen_rem_i32) 3629 DIVU32(do_moduw, tcg_gen_remu_i32) 3630 DIVS64(do_modsd, tcg_gen_rem_i64) 3631 DIVU64(do_modud, tcg_gen_remu_i64) 3632 3633 TRANS_FLAGS2(ISA310, VDIVESW, do_vdiv_vmod, MO_32, do_divesw, NULL) 3634 TRANS_FLAGS2(ISA310, VDIVEUW, do_vdiv_vmod, MO_32, do_diveuw, NULL) 3635 TRANS_FLAGS2(ISA310, VDIVESD, do_vx_helper, gen_helper_VDIVESD) 3636 TRANS_FLAGS2(ISA310, VDIVEUD, do_vx_helper, gen_helper_VDIVEUD) 3637 TRANS_FLAGS2(ISA310, VDIVESQ, do_vx_helper, gen_helper_VDIVESQ) 3638 TRANS_FLAGS2(ISA310, VDIVEUQ, do_vx_helper, gen_helper_VDIVEUQ) 3639 3640 TRANS_FLAGS2(ISA310, VMODSW, do_vdiv_vmod, MO_32, do_modsw , NULL) 3641 TRANS_FLAGS2(ISA310, VMODUW, do_vdiv_vmod, MO_32, do_moduw, NULL) 3642 TRANS_FLAGS2(ISA310, VMODSD, do_vdiv_vmod, MO_64, NULL, do_modsd) 3643 TRANS_FLAGS2(ISA310, VMODUD, do_vdiv_vmod, MO_64, NULL, do_modud) 3644 TRANS_FLAGS2(ISA310, VMODSQ, do_vx_helper, gen_helper_VMODSQ) 3645 TRANS_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