1/* 2 * translate-spe.c 3 * 4 * Freescale SPE extension translation 5 */ 6 7/*** SPE extension ***/ 8/* Register moves */ 9 10static inline void gen_evmra(DisasContext *ctx) 11{ 12 13 if (unlikely(!ctx->spe_enabled)) { 14 gen_exception(ctx, POWERPC_EXCP_SPEU); 15 return; 16 } 17 18 TCGv_i64 tmp = tcg_temp_new_i64(); 19 20 /* tmp := rA_lo + rA_hi << 32 */ 21 tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], 22 cpu_gprh[rA(ctx->opcode)]); 23 24 /* spe_acc := tmp */ 25 tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc)); 26 27 /* rD := rA */ 28 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 29 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); 30} 31 32static inline void gen_load_gpr64(TCGv_i64 t, int reg) 33{ 34 tcg_gen_concat_tl_i64(t, cpu_gpr[reg], cpu_gprh[reg]); 35} 36 37static inline void gen_store_gpr64(int reg, TCGv_i64 t) 38{ 39 tcg_gen_extr_i64_tl(cpu_gpr[reg], cpu_gprh[reg], t); 40} 41 42#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ 43static void glue(gen_, name0##_##name1)(DisasContext *ctx) \ 44{ \ 45 if (Rc(ctx->opcode)) \ 46 gen_##name1(ctx); \ 47 else \ 48 gen_##name0(ctx); \ 49} 50 51/* Handler for undefined SPE opcodes */ 52static inline void gen_speundef(DisasContext *ctx) 53{ 54 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 55} 56 57/* SPE logic */ 58#define GEN_SPEOP_LOGIC2(name, tcg_op) \ 59static inline void gen_##name(DisasContext *ctx) \ 60{ \ 61 if (unlikely(!ctx->spe_enabled)) { \ 62 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 63 return; \ 64 } \ 65 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \ 66 cpu_gpr[rB(ctx->opcode)]); \ 67 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \ 68 cpu_gprh[rB(ctx->opcode)]); \ 69} 70 71GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl); 72GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl); 73GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl); 74GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl); 75GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl); 76GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl); 77GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl); 78GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl); 79 80/* SPE logic immediate */ 81#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \ 82static inline void gen_##name(DisasContext *ctx) \ 83{ \ 84 TCGv_i32 t0; \ 85 if (unlikely(!ctx->spe_enabled)) { \ 86 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 87 return; \ 88 } \ 89 t0 = tcg_temp_new_i32(); \ 90 \ 91 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ 92 tcg_opi(t0, t0, rB(ctx->opcode)); \ 93 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 94 \ 95 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \ 96 tcg_opi(t0, t0, rB(ctx->opcode)); \ 97 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \ 98} 99GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32); 100GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32); 101GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32); 102GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32); 103 104/* SPE arithmetic */ 105#define GEN_SPEOP_ARITH1(name, tcg_op) \ 106static inline void gen_##name(DisasContext *ctx) \ 107{ \ 108 TCGv_i32 t0; \ 109 if (unlikely(!ctx->spe_enabled)) { \ 110 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 111 return; \ 112 } \ 113 t0 = tcg_temp_new_i32(); \ 114 \ 115 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ 116 tcg_op(t0, t0); \ 117 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 118 \ 119 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \ 120 tcg_op(t0, t0); \ 121 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \ 122} 123 124GEN_SPEOP_ARITH1(evabs, tcg_gen_abs_i32); 125GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32); 126GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32); 127GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32); 128static inline void gen_op_evrndw(TCGv_i32 ret, TCGv_i32 arg1) 129{ 130 tcg_gen_addi_i32(ret, arg1, 0x8000); 131 tcg_gen_ext16u_i32(ret, ret); 132} 133GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw); 134GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32); 135GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32); 136 137#define GEN_SPEOP_ARITH2(name, tcg_op) \ 138static inline void gen_##name(DisasContext *ctx) \ 139{ \ 140 TCGv_i32 t0, t1; \ 141 if (unlikely(!ctx->spe_enabled)) { \ 142 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 143 return; \ 144 } \ 145 t0 = tcg_temp_new_i32(); \ 146 t1 = tcg_temp_new_i32(); \ 147 \ 148 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ 149 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ 150 tcg_op(t0, t0, t1); \ 151 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 152 \ 153 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \ 154 tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]); \ 155 tcg_op(t0, t0, t1); \ 156 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \ 157} 158 159static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 160{ 161 TCGLabel *l1 = gen_new_label(); 162 TCGLabel *l2 = gen_new_label(); 163 TCGv_i32 t0 = tcg_temp_new_i32(); 164 165 /* No error here: 6 bits are used */ 166 tcg_gen_andi_i32(t0, arg2, 0x3F); 167 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1); 168 tcg_gen_shr_i32(ret, arg1, t0); 169 tcg_gen_br(l2); 170 gen_set_label(l1); 171 tcg_gen_movi_i32(ret, 0); 172 gen_set_label(l2); 173} 174GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu); 175static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 176{ 177 TCGLabel *l1 = gen_new_label(); 178 TCGLabel *l2 = gen_new_label(); 179 TCGv_i32 t0 = tcg_temp_new_i32(); 180 181 /* No error here: 6 bits are used */ 182 tcg_gen_andi_i32(t0, arg2, 0x3F); 183 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1); 184 tcg_gen_sar_i32(ret, arg1, t0); 185 tcg_gen_br(l2); 186 gen_set_label(l1); 187 tcg_gen_movi_i32(ret, 0); 188 gen_set_label(l2); 189} 190GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws); 191static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 192{ 193 TCGLabel *l1 = gen_new_label(); 194 TCGLabel *l2 = gen_new_label(); 195 TCGv_i32 t0 = tcg_temp_new_i32(); 196 197 /* No error here: 6 bits are used */ 198 tcg_gen_andi_i32(t0, arg2, 0x3F); 199 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1); 200 tcg_gen_shl_i32(ret, arg1, t0); 201 tcg_gen_br(l2); 202 gen_set_label(l1); 203 tcg_gen_movi_i32(ret, 0); 204 gen_set_label(l2); 205} 206GEN_SPEOP_ARITH2(evslw, gen_op_evslw); 207static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 208{ 209 TCGv_i32 t0 = tcg_temp_new_i32(); 210 tcg_gen_andi_i32(t0, arg2, 0x1F); 211 tcg_gen_rotl_i32(ret, arg1, t0); 212} 213GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw); 214static inline void gen_evmergehi(DisasContext *ctx) 215{ 216 if (unlikely(!ctx->spe_enabled)) { 217 gen_exception(ctx, POWERPC_EXCP_SPEU); 218 return; 219 } 220 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); 221 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); 222} 223GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32); 224static inline void gen_op_evsubf(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) 225{ 226 tcg_gen_sub_i32(ret, arg2, arg1); 227} 228GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf); 229 230/* SPE arithmetic immediate */ 231#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \ 232static inline void gen_##name(DisasContext *ctx) \ 233{ \ 234 TCGv_i32 t0; \ 235 if (unlikely(!ctx->spe_enabled)) { \ 236 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 237 return; \ 238 } \ 239 t0 = tcg_temp_new_i32(); \ 240 \ 241 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \ 242 tcg_op(t0, t0, rA(ctx->opcode)); \ 243 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 244 \ 245 tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]); \ 246 tcg_op(t0, t0, rA(ctx->opcode)); \ 247 tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \ 248} 249GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32); 250GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32); 251 252/* SPE comparison */ 253#define GEN_SPEOP_COMP(name, tcg_cond) \ 254static inline void gen_##name(DisasContext *ctx) \ 255{ \ 256 if (unlikely(!ctx->spe_enabled)) { \ 257 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 258 return; \ 259 } \ 260 TCGLabel *l1 = gen_new_label(); \ 261 TCGLabel *l2 = gen_new_label(); \ 262 TCGLabel *l3 = gen_new_label(); \ 263 TCGLabel *l4 = gen_new_label(); \ 264 \ 265 tcg_gen_ext32s_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \ 266 tcg_gen_ext32s_tl(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \ 267 tcg_gen_ext32s_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \ 268 tcg_gen_ext32s_tl(cpu_gprh[rB(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); \ 269 \ 270 tcg_gen_brcond_tl(tcg_cond, cpu_gpr[rA(ctx->opcode)], \ 271 cpu_gpr[rB(ctx->opcode)], l1); \ 272 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \ 273 tcg_gen_br(l2); \ 274 gen_set_label(l1); \ 275 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \ 276 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \ 277 gen_set_label(l2); \ 278 tcg_gen_brcond_tl(tcg_cond, cpu_gprh[rA(ctx->opcode)], \ 279 cpu_gprh[rB(ctx->opcode)], l3); \ 280 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \ 281 ~(CRF_CH | CRF_CH_AND_CL)); \ 282 tcg_gen_br(l4); \ 283 gen_set_label(l3); \ 284 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \ 285 CRF_CH | CRF_CH_OR_CL); \ 286 gen_set_label(l4); \ 287} 288GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU); 289GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT); 290GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU); 291GEN_SPEOP_COMP(evcmplts, TCG_COND_LT); 292GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ); 293 294/* SPE misc */ 295static inline void gen_brinc(DisasContext *ctx) 296{ 297 /* Note: brinc is usable even if SPE is disabled */ 298 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)], 299 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 300} 301static inline void gen_evmergelo(DisasContext *ctx) 302{ 303 if (unlikely(!ctx->spe_enabled)) { 304 gen_exception(ctx, POWERPC_EXCP_SPEU); 305 return; 306 } 307 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 308 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 309} 310static inline void gen_evmergehilo(DisasContext *ctx) 311{ 312 if (unlikely(!ctx->spe_enabled)) { 313 gen_exception(ctx, POWERPC_EXCP_SPEU); 314 return; 315 } 316 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 317 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); 318} 319static inline void gen_evmergelohi(DisasContext *ctx) 320{ 321 if (unlikely(!ctx->spe_enabled)) { 322 gen_exception(ctx, POWERPC_EXCP_SPEU); 323 return; 324 } 325 if (rD(ctx->opcode) == rA(ctx->opcode)) { 326 TCGv tmp = tcg_temp_new(); 327 tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]); 328 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); 329 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp); 330 } else { 331 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); 332 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 333 } 334} 335static inline void gen_evsplati(DisasContext *ctx) 336{ 337 uint64_t imm; 338 if (unlikely(!ctx->spe_enabled)) { 339 gen_exception(ctx, POWERPC_EXCP_SPEU); 340 return; 341 } 342 imm = ((int32_t)(rA(ctx->opcode) << 27)) >> 27; 343 344 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm); 345 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm); 346} 347static inline void gen_evsplatfi(DisasContext *ctx) 348{ 349 uint64_t imm; 350 if (unlikely(!ctx->spe_enabled)) { 351 gen_exception(ctx, POWERPC_EXCP_SPEU); 352 return; 353 } 354 imm = rA(ctx->opcode) << 27; 355 356 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], imm); 357 tcg_gen_movi_tl(cpu_gprh[rD(ctx->opcode)], imm); 358} 359 360static inline void gen_evsel(DisasContext *ctx) 361{ 362 TCGLabel *l1 = gen_new_label(); 363 TCGLabel *l2 = gen_new_label(); 364 TCGLabel *l3 = gen_new_label(); 365 TCGLabel *l4 = gen_new_label(); 366 TCGv_i32 t0 = tcg_temp_new_i32(); 367 368 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3); 369 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); 370 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); 371 tcg_gen_br(l2); 372 gen_set_label(l1); 373 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); 374 gen_set_label(l2); 375 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2); 376 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3); 377 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 378 tcg_gen_br(l4); 379 gen_set_label(l3); 380 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); 381 gen_set_label(l4); 382} 383 384static void gen_evsel0(DisasContext *ctx) 385{ 386 if (unlikely(!ctx->spe_enabled)) { 387 gen_exception(ctx, POWERPC_EXCP_SPEU); 388 return; 389 } 390 gen_evsel(ctx); 391} 392 393static void gen_evsel1(DisasContext *ctx) 394{ 395 if (unlikely(!ctx->spe_enabled)) { 396 gen_exception(ctx, POWERPC_EXCP_SPEU); 397 return; 398 } 399 gen_evsel(ctx); 400} 401 402static void gen_evsel2(DisasContext *ctx) 403{ 404 if (unlikely(!ctx->spe_enabled)) { 405 gen_exception(ctx, POWERPC_EXCP_SPEU); 406 return; 407 } 408 gen_evsel(ctx); 409} 410 411static void gen_evsel3(DisasContext *ctx) 412{ 413 if (unlikely(!ctx->spe_enabled)) { 414 gen_exception(ctx, POWERPC_EXCP_SPEU); 415 return; 416 } 417 gen_evsel(ctx); 418} 419 420/* Multiply */ 421 422static inline void gen_evmwumi(DisasContext *ctx) 423{ 424 TCGv_i64 t0, t1; 425 426 if (unlikely(!ctx->spe_enabled)) { 427 gen_exception(ctx, POWERPC_EXCP_SPEU); 428 return; 429 } 430 431 t0 = tcg_temp_new_i64(); 432 t1 = tcg_temp_new_i64(); 433 434 /* t0 := rA; t1 := rB */ 435 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); 436 tcg_gen_ext32u_i64(t0, t0); 437 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); 438 tcg_gen_ext32u_i64(t1, t1); 439 440 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */ 441 442 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */ 443} 444 445static inline void gen_evmwumia(DisasContext *ctx) 446{ 447 TCGv_i64 tmp; 448 449 if (unlikely(!ctx->spe_enabled)) { 450 gen_exception(ctx, POWERPC_EXCP_SPEU); 451 return; 452 } 453 454 gen_evmwumi(ctx); /* rD := rA * rB */ 455 456 tmp = tcg_temp_new_i64(); 457 458 /* acc := rD */ 459 gen_load_gpr64(tmp, rD(ctx->opcode)); 460 tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc)); 461} 462 463static inline void gen_evmwumiaa(DisasContext *ctx) 464{ 465 TCGv_i64 acc; 466 TCGv_i64 tmp; 467 468 if (unlikely(!ctx->spe_enabled)) { 469 gen_exception(ctx, POWERPC_EXCP_SPEU); 470 return; 471 } 472 473 gen_evmwumi(ctx); /* rD := rA * rB */ 474 475 acc = tcg_temp_new_i64(); 476 tmp = tcg_temp_new_i64(); 477 478 /* tmp := rD */ 479 gen_load_gpr64(tmp, rD(ctx->opcode)); 480 481 /* Load acc */ 482 tcg_gen_ld_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc)); 483 484 /* acc := tmp + acc */ 485 tcg_gen_add_i64(acc, acc, tmp); 486 487 /* Store acc */ 488 tcg_gen_st_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc)); 489 490 /* rD := acc */ 491 gen_store_gpr64(rD(ctx->opcode), acc); 492} 493 494static inline void gen_evmwsmi(DisasContext *ctx) 495{ 496 TCGv_i64 t0, t1; 497 498 if (unlikely(!ctx->spe_enabled)) { 499 gen_exception(ctx, POWERPC_EXCP_SPEU); 500 return; 501 } 502 503 t0 = tcg_temp_new_i64(); 504 t1 = tcg_temp_new_i64(); 505 506 /* t0 := rA; t1 := rB */ 507 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]); 508 tcg_gen_ext32s_i64(t0, t0); 509 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]); 510 tcg_gen_ext32s_i64(t1, t1); 511 512 tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */ 513 514 gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */ 515} 516 517static inline void gen_evmwsmia(DisasContext *ctx) 518{ 519 TCGv_i64 tmp; 520 521 if (unlikely(!ctx->spe_enabled)) { 522 gen_exception(ctx, POWERPC_EXCP_SPEU); 523 return; 524 } 525 526 gen_evmwsmi(ctx); /* rD := rA * rB */ 527 528 tmp = tcg_temp_new_i64(); 529 530 /* acc := rD */ 531 gen_load_gpr64(tmp, rD(ctx->opcode)); 532 tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc)); 533} 534 535static inline void gen_evmwsmiaa(DisasContext *ctx) 536{ 537 TCGv_i64 acc; 538 TCGv_i64 tmp; 539 540 if (unlikely(!ctx->spe_enabled)) { 541 gen_exception(ctx, POWERPC_EXCP_SPEU); 542 return; 543 } 544 545 gen_evmwsmi(ctx); /* rD := rA * rB */ 546 547 acc = tcg_temp_new_i64(); 548 tmp = tcg_temp_new_i64(); 549 550 /* tmp := rD */ 551 gen_load_gpr64(tmp, rD(ctx->opcode)); 552 553 /* Load acc */ 554 tcg_gen_ld_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc)); 555 556 /* acc := tmp + acc */ 557 tcg_gen_add_i64(acc, acc, tmp); 558 559 /* Store acc */ 560 tcg_gen_st_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc)); 561 562 /* rD := acc */ 563 gen_store_gpr64(rD(ctx->opcode), acc); 564} 565 566GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); //// 567GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); 568GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); //// 569GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); 570GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); //// 571GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); //// 572GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, 0x0000F800, PPC_SPE); //// 573GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x0000F800, 0x00000000, PPC_SPE); // 574GEN_SPE(evmra, speundef, 0x02, 0x13, 0x0000F800, 0xFFFFFFFF, PPC_SPE); 575GEN_SPE(speundef, evand, 0x08, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); //// 576GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); //// 577GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, 0x00000000, PPC_SPE); //// 578GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, 0x00000000, PPC_SPE); //// 579GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, 0x00000000, PPC_SPE); 580GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, 0x00000000, PPC_SPE); 581GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, 0x00000000, PPC_SPE); 582GEN_SPE(speundef, evorc, 0x0D, 0x08, 0xFFFFFFFF, 0x00000000, PPC_SPE); //// 583GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); //// 584GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, 0x00000000, PPC_SPE); //// 585GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, 0x00000000, PPC_SPE); 586GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); //// 587GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); 588GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, 0x0000F800, PPC_SPE); // 589GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, 0x0000F800, PPC_SPE); 590GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, 0x00000000, PPC_SPE); //// 591GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, 0x00000000, PPC_SPE); //// 592GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, 0x00600000, PPC_SPE); //// 593GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, 0x00600000, PPC_SPE); //// 594GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, 0xFFFFFFFF, PPC_SPE); //// 595 596/* SPE load and stores */ 597static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh) 598{ 599 target_ulong uimm = rB(ctx->opcode); 600 601 if (rA(ctx->opcode) == 0) { 602 tcg_gen_movi_tl(EA, uimm << sh); 603 } else { 604 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh); 605 if (NARROW_MODE(ctx)) { 606 tcg_gen_ext32u_tl(EA, EA); 607 } 608 } 609} 610 611static inline void gen_op_evldd(DisasContext *ctx, TCGv addr) 612{ 613 TCGv_i64 t0 = tcg_temp_new_i64(); 614 gen_qemu_ld64_i64(ctx, t0, addr); 615 gen_store_gpr64(rD(ctx->opcode), t0); 616} 617 618static inline void gen_op_evldw(DisasContext *ctx, TCGv addr) 619{ 620 gen_qemu_ld32u(ctx, cpu_gprh[rD(ctx->opcode)], addr); 621 gen_addr_add(ctx, addr, addr, 4); 622 gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], addr); 623} 624 625static inline void gen_op_evldh(DisasContext *ctx, TCGv addr) 626{ 627 TCGv t0 = tcg_temp_new(); 628 gen_qemu_ld16u(ctx, t0, addr); 629 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); 630 gen_addr_add(ctx, addr, addr, 2); 631 gen_qemu_ld16u(ctx, t0, addr); 632 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); 633 gen_addr_add(ctx, addr, addr, 2); 634 gen_qemu_ld16u(ctx, t0, addr); 635 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); 636 gen_addr_add(ctx, addr, addr, 2); 637 gen_qemu_ld16u(ctx, t0, addr); 638 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0); 639} 640 641static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr) 642{ 643 TCGv t0 = tcg_temp_new(); 644 gen_qemu_ld16u(ctx, t0, addr); 645 tcg_gen_shli_tl(t0, t0, 16); 646 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0); 647 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); 648} 649 650static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr) 651{ 652 TCGv t0 = tcg_temp_new(); 653 gen_qemu_ld16u(ctx, t0, addr); 654 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0); 655 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); 656} 657 658static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr) 659{ 660 TCGv t0 = tcg_temp_new(); 661 gen_qemu_ld16s(ctx, t0, addr); 662 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0); 663 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); 664} 665 666static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr) 667{ 668 TCGv t0 = tcg_temp_new(); 669 gen_qemu_ld16u(ctx, t0, addr); 670 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); 671 gen_addr_add(ctx, addr, addr, 2); 672 gen_qemu_ld16u(ctx, t0, addr); 673 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16); 674} 675 676static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr) 677{ 678 gen_qemu_ld16u(ctx, cpu_gprh[rD(ctx->opcode)], addr); 679 gen_addr_add(ctx, addr, addr, 2); 680 gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], addr); 681} 682 683static inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr) 684{ 685 gen_qemu_ld16s(ctx, cpu_gprh[rD(ctx->opcode)], addr); 686 gen_addr_add(ctx, addr, addr, 2); 687 gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], addr); 688} 689 690static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr) 691{ 692 TCGv t0 = tcg_temp_new(); 693 gen_qemu_ld32u(ctx, t0, addr); 694 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0); 695 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0); 696} 697 698static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr) 699{ 700 TCGv t0 = tcg_temp_new(); 701 gen_qemu_ld16u(ctx, t0, addr); 702 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16); 703 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); 704 gen_addr_add(ctx, addr, addr, 2); 705 gen_qemu_ld16u(ctx, t0, addr); 706 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16); 707 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0); 708} 709 710static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr) 711{ 712 TCGv_i64 t0 = tcg_temp_new_i64(); 713 gen_load_gpr64(t0, rS(ctx->opcode)); 714 gen_qemu_st64_i64(ctx, t0, addr); 715} 716 717static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr) 718{ 719 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr); 720 gen_addr_add(ctx, addr, addr, 4); 721 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr); 722} 723 724static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr) 725{ 726 TCGv t0 = tcg_temp_new(); 727 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16); 728 gen_qemu_st16(ctx, t0, addr); 729 gen_addr_add(ctx, addr, addr, 2); 730 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr); 731 gen_addr_add(ctx, addr, addr, 2); 732 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16); 733 gen_qemu_st16(ctx, t0, addr); 734 gen_addr_add(ctx, addr, addr, 2); 735 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr); 736} 737 738static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr) 739{ 740 TCGv t0 = tcg_temp_new(); 741 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16); 742 gen_qemu_st16(ctx, t0, addr); 743 gen_addr_add(ctx, addr, addr, 2); 744 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16); 745 gen_qemu_st16(ctx, t0, addr); 746} 747 748static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr) 749{ 750 gen_qemu_st16(ctx, cpu_gprh[rS(ctx->opcode)], addr); 751 gen_addr_add(ctx, addr, addr, 2); 752 gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr); 753} 754 755static inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr) 756{ 757 gen_qemu_st32(ctx, cpu_gprh[rS(ctx->opcode)], addr); 758} 759 760static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr) 761{ 762 gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], addr); 763} 764 765#define GEN_SPEOP_LDST(name, opc2, sh) \ 766static void glue(gen_, name)(DisasContext *ctx) \ 767{ \ 768 TCGv t0; \ 769 if (unlikely(!ctx->spe_enabled)) { \ 770 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 771 return; \ 772 } \ 773 gen_set_access_type(ctx, ACCESS_INT); \ 774 t0 = tcg_temp_new(); \ 775 if (Rc(ctx->opcode)) { \ 776 gen_addr_spe_imm_index(ctx, t0, sh); \ 777 } else { \ 778 gen_addr_reg_index(ctx, t0); \ 779 } \ 780 gen_op_##name(ctx, t0); \ 781} 782 783GEN_SPEOP_LDST(evldd, 0x00, 3); 784GEN_SPEOP_LDST(evldw, 0x01, 3); 785GEN_SPEOP_LDST(evldh, 0x02, 3); 786GEN_SPEOP_LDST(evlhhesplat, 0x04, 1); 787GEN_SPEOP_LDST(evlhhousplat, 0x06, 1); 788GEN_SPEOP_LDST(evlhhossplat, 0x07, 1); 789GEN_SPEOP_LDST(evlwhe, 0x08, 2); 790GEN_SPEOP_LDST(evlwhou, 0x0A, 2); 791GEN_SPEOP_LDST(evlwhos, 0x0B, 2); 792GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2); 793GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2); 794 795GEN_SPEOP_LDST(evstdd, 0x10, 3); 796GEN_SPEOP_LDST(evstdw, 0x11, 3); 797GEN_SPEOP_LDST(evstdh, 0x12, 3); 798GEN_SPEOP_LDST(evstwhe, 0x18, 2); 799GEN_SPEOP_LDST(evstwho, 0x1A, 2); 800GEN_SPEOP_LDST(evstwwe, 0x1C, 2); 801GEN_SPEOP_LDST(evstwwo, 0x1E, 2); 802 803/* Multiply and add - TODO */ 804#if 0 805GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE);// 806GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 807GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, 0x00000000, PPC_SPE); 808GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 809GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, 0x00000000, PPC_SPE); 810GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 811GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 812GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 813GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, 0x00000000, PPC_SPE); 814GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 815GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, 0x00000000, PPC_SPE); 816GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0xFFFFFFFF, 0x00000000, PPC_SPE); 817 818GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 819GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE); 820GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, 0x00000000, PPC_SPE); 821GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 822GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 823GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 824GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 825GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, 0xFFFFFFFF, PPC_SPE); 826GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, 0x00000000, PPC_SPE); 827GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 828GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 829GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0xFFFFFFFF, 0x00000000, PPC_SPE); 830 831GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, 0x0000F800, PPC_SPE); 832GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, 0x0000F800, PPC_SPE); 833GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, 0x0000F800, PPC_SPE); 834GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, 0x0000F800, PPC_SPE); 835GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, 0x00000000, PPC_SPE); 836 837GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, 0x00000000, PPC_SPE); 838GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 839GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, 0x00000000, PPC_SPE); 840GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 841GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, 0x00000000, PPC_SPE); 842GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 843GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, 0x00000000, PPC_SPE); 844GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 845GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, 0x00000000, PPC_SPE); 846GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 847GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, 0x00000000, PPC_SPE); 848GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0xFFFFFFFF, 0x00000000, PPC_SPE); 849 850GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, 0x00000000, PPC_SPE); 851GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, 0x00000000, PPC_SPE); 852GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE); 853GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0xFFFFFFFF, 0x00000000, PPC_SPE); 854 855GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, 0x00000000, PPC_SPE); 856GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 857GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, 0x00000000, PPC_SPE); 858GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 859GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, 0x00000000, PPC_SPE); 860GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 861GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, 0x00000000, PPC_SPE); 862GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 863GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, 0x00000000, PPC_SPE); 864GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 865GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, 0x00000000, PPC_SPE); 866GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0xFFFFFFFF, 0x00000000, PPC_SPE); 867 868GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, 0x00000000, PPC_SPE); 869GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, 0x00000000, PPC_SPE); 870GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE); 871GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, 0x00000000, PPC_SPE); 872GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0xFFFFFFFF, 0x00000000, PPC_SPE); 873#endif 874 875/*** SPE floating-point extension ***/ 876#define GEN_SPEFPUOP_CONV_32_32(name) \ 877static inline void gen_##name(DisasContext *ctx) \ 878{ \ 879 TCGv_i32 t0 = tcg_temp_new_i32(); \ 880 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \ 881 gen_helper_##name(t0, tcg_env, t0); \ 882 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 883} 884#define GEN_SPEFPUOP_CONV_32_64(name) \ 885static inline void gen_##name(DisasContext *ctx) \ 886{ \ 887 TCGv_i64 t0; \ 888 TCGv_i32 t1; \ 889 if (unlikely(!ctx->spe_enabled)) { \ 890 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 891 return; \ 892 } \ 893 t0 = tcg_temp_new_i64(); \ 894 t1 = tcg_temp_new_i32(); \ 895 gen_load_gpr64(t0, rB(ctx->opcode)); \ 896 gen_helper_##name(t1, tcg_env, t0); \ 897 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \ 898} 899#define GEN_SPEFPUOP_CONV_64_32(name) \ 900static inline void gen_##name(DisasContext *ctx) \ 901{ \ 902 TCGv_i64 t0; \ 903 TCGv_i32 t1; \ 904 if (unlikely(!ctx->spe_enabled)) { \ 905 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 906 return; \ 907 } \ 908 t0 = tcg_temp_new_i64(); \ 909 t1 = tcg_temp_new_i32(); \ 910 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ 911 gen_helper_##name(t0, tcg_env, t1); \ 912 gen_store_gpr64(rD(ctx->opcode), t0); \ 913} 914#define GEN_SPEFPUOP_CONV_64_64(name) \ 915static inline void gen_##name(DisasContext *ctx) \ 916{ \ 917 TCGv_i64 t0; \ 918 if (unlikely(!ctx->spe_enabled)) { \ 919 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 920 return; \ 921 } \ 922 t0 = tcg_temp_new_i64(); \ 923 gen_load_gpr64(t0, rB(ctx->opcode)); \ 924 gen_helper_##name(t0, tcg_env, t0); \ 925 gen_store_gpr64(rD(ctx->opcode), t0); \ 926} 927#define GEN_SPEFPUOP_ARITH2_32_32(name) \ 928static inline void gen_##name(DisasContext *ctx) \ 929{ \ 930 TCGv_i32 t0 = tcg_temp_new_i32(); \ 931 TCGv_i32 t1 = tcg_temp_new_i32(); \ 932 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ 933 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ 934 gen_helper_##name(t0, tcg_env, t0, t1); \ 935 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \ 936} 937#define GEN_SPEFPUOP_ARITH2_64_64(name) \ 938static inline void gen_##name(DisasContext *ctx) \ 939{ \ 940 TCGv_i64 t0, t1; \ 941 if (unlikely(!ctx->spe_enabled)) { \ 942 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 943 return; \ 944 } \ 945 t0 = tcg_temp_new_i64(); \ 946 t1 = tcg_temp_new_i64(); \ 947 gen_load_gpr64(t0, rA(ctx->opcode)); \ 948 gen_load_gpr64(t1, rB(ctx->opcode)); \ 949 gen_helper_##name(t0, tcg_env, t0, t1); \ 950 gen_store_gpr64(rD(ctx->opcode), t0); \ 951} 952#define GEN_SPEFPUOP_COMP_32(name) \ 953static inline void gen_##name(DisasContext *ctx) \ 954{ \ 955 TCGv_i32 t0 = tcg_temp_new_i32(); \ 956 TCGv_i32 t1 = tcg_temp_new_i32(); \ 957 \ 958 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \ 959 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \ 960 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], tcg_env, t0, t1); \ 961} 962#define GEN_SPEFPUOP_COMP_64(name) \ 963static inline void gen_##name(DisasContext *ctx) \ 964{ \ 965 TCGv_i64 t0, t1; \ 966 if (unlikely(!ctx->spe_enabled)) { \ 967 gen_exception(ctx, POWERPC_EXCP_SPEU); \ 968 return; \ 969 } \ 970 t0 = tcg_temp_new_i64(); \ 971 t1 = tcg_temp_new_i64(); \ 972 gen_load_gpr64(t0, rA(ctx->opcode)); \ 973 gen_load_gpr64(t1, rB(ctx->opcode)); \ 974 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], tcg_env, t0, t1); \ 975} 976 977/* Single precision floating-point vectors operations */ 978/* Arithmetic */ 979GEN_SPEFPUOP_ARITH2_64_64(evfsadd); 980GEN_SPEFPUOP_ARITH2_64_64(evfssub); 981GEN_SPEFPUOP_ARITH2_64_64(evfsmul); 982GEN_SPEFPUOP_ARITH2_64_64(evfsdiv); 983static inline void gen_evfsabs(DisasContext *ctx) 984{ 985 if (unlikely(!ctx->spe_enabled)) { 986 gen_exception(ctx, POWERPC_EXCP_SPEU); 987 return; 988 } 989 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 990 ~0x80000000); 991 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 992 ~0x80000000); 993} 994static inline void gen_evfsnabs(DisasContext *ctx) 995{ 996 if (unlikely(!ctx->spe_enabled)) { 997 gen_exception(ctx, POWERPC_EXCP_SPEU); 998 return; 999 } 1000 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1001 0x80000000); 1002 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 1003 0x80000000); 1004} 1005static inline void gen_evfsneg(DisasContext *ctx) 1006{ 1007 if (unlikely(!ctx->spe_enabled)) { 1008 gen_exception(ctx, POWERPC_EXCP_SPEU); 1009 return; 1010 } 1011 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1012 0x80000000); 1013 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 1014 0x80000000); 1015} 1016 1017/* Conversion */ 1018GEN_SPEFPUOP_CONV_64_64(evfscfui); 1019GEN_SPEFPUOP_CONV_64_64(evfscfsi); 1020GEN_SPEFPUOP_CONV_64_64(evfscfuf); 1021GEN_SPEFPUOP_CONV_64_64(evfscfsf); 1022GEN_SPEFPUOP_CONV_64_64(evfsctui); 1023GEN_SPEFPUOP_CONV_64_64(evfsctsi); 1024GEN_SPEFPUOP_CONV_64_64(evfsctuf); 1025GEN_SPEFPUOP_CONV_64_64(evfsctsf); 1026GEN_SPEFPUOP_CONV_64_64(evfsctuiz); 1027GEN_SPEFPUOP_CONV_64_64(evfsctsiz); 1028 1029/* Comparison */ 1030GEN_SPEFPUOP_COMP_64(evfscmpgt); 1031GEN_SPEFPUOP_COMP_64(evfscmplt); 1032GEN_SPEFPUOP_COMP_64(evfscmpeq); 1033GEN_SPEFPUOP_COMP_64(evfststgt); 1034GEN_SPEFPUOP_COMP_64(evfststlt); 1035GEN_SPEFPUOP_COMP_64(evfststeq); 1036 1037/* Opcodes definitions */ 1038GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); // 1039GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); // 1040GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1041GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, 0x00000000, PPC_SPE_SINGLE); // 1042GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); // 1043GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1044GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1045GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1046GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1047GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1048GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1049GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1050GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, 0x00600000, PPC_SPE_SINGLE); // 1051GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1052 1053/* Single precision floating-point operations */ 1054/* Arithmetic */ 1055GEN_SPEFPUOP_ARITH2_32_32(efsadd); 1056GEN_SPEFPUOP_ARITH2_32_32(efssub); 1057GEN_SPEFPUOP_ARITH2_32_32(efsmul); 1058GEN_SPEFPUOP_ARITH2_32_32(efsdiv); 1059static inline void gen_efsabs(DisasContext *ctx) 1060{ 1061 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1062 (target_long)~0x80000000LL); 1063} 1064static inline void gen_efsnabs(DisasContext *ctx) 1065{ 1066 tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1067 0x80000000); 1068} 1069static inline void gen_efsneg(DisasContext *ctx) 1070{ 1071 tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1072 0x80000000); 1073} 1074 1075/* Conversion */ 1076GEN_SPEFPUOP_CONV_32_32(efscfui); 1077GEN_SPEFPUOP_CONV_32_32(efscfsi); 1078GEN_SPEFPUOP_CONV_32_32(efscfuf); 1079GEN_SPEFPUOP_CONV_32_32(efscfsf); 1080GEN_SPEFPUOP_CONV_32_32(efsctui); 1081GEN_SPEFPUOP_CONV_32_32(efsctsi); 1082GEN_SPEFPUOP_CONV_32_32(efsctuf); 1083GEN_SPEFPUOP_CONV_32_32(efsctsf); 1084GEN_SPEFPUOP_CONV_32_32(efsctuiz); 1085GEN_SPEFPUOP_CONV_32_32(efsctsiz); 1086GEN_SPEFPUOP_CONV_32_64(efscfd); 1087 1088/* Comparison */ 1089GEN_SPEFPUOP_COMP_32(efscmpgt); 1090GEN_SPEFPUOP_COMP_32(efscmplt); 1091GEN_SPEFPUOP_COMP_32(efscmpeq); 1092GEN_SPEFPUOP_COMP_32(efststgt); 1093GEN_SPEFPUOP_COMP_32(efststlt); 1094GEN_SPEFPUOP_COMP_32(efststeq); 1095 1096/* Opcodes definitions */ 1097GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); // 1098GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_SINGLE); // 1099GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1100GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, 0x00000000, PPC_SPE_SINGLE); // 1101GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); // 1102GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, 0x00180000, PPC_SPE_SINGLE); // 1103GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1104GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1105GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1106GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_SINGLE); // 1107GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1108GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1109GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_SINGLE); // 1110GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_SINGLE); // 1111 1112/* Double precision floating-point operations */ 1113/* Arithmetic */ 1114GEN_SPEFPUOP_ARITH2_64_64(efdadd); 1115GEN_SPEFPUOP_ARITH2_64_64(efdsub); 1116GEN_SPEFPUOP_ARITH2_64_64(efdmul); 1117GEN_SPEFPUOP_ARITH2_64_64(efddiv); 1118static inline void gen_efdabs(DisasContext *ctx) 1119{ 1120 if (unlikely(!ctx->spe_enabled)) { 1121 gen_exception(ctx, POWERPC_EXCP_SPEU); 1122 return; 1123 } 1124 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 1125 tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 1126 ~0x80000000); 1127} 1128static inline void gen_efdnabs(DisasContext *ctx) 1129{ 1130 if (unlikely(!ctx->spe_enabled)) { 1131 gen_exception(ctx, POWERPC_EXCP_SPEU); 1132 return; 1133 } 1134 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 1135 tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 1136 0x80000000); 1137} 1138static inline void gen_efdneg(DisasContext *ctx) 1139{ 1140 if (unlikely(!ctx->spe_enabled)) { 1141 gen_exception(ctx, POWERPC_EXCP_SPEU); 1142 return; 1143 } 1144 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); 1145 tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 1146 0x80000000); 1147} 1148 1149/* Conversion */ 1150GEN_SPEFPUOP_CONV_64_32(efdcfui); 1151GEN_SPEFPUOP_CONV_64_32(efdcfsi); 1152GEN_SPEFPUOP_CONV_64_32(efdcfuf); 1153GEN_SPEFPUOP_CONV_64_32(efdcfsf); 1154GEN_SPEFPUOP_CONV_32_64(efdctui); 1155GEN_SPEFPUOP_CONV_32_64(efdctsi); 1156GEN_SPEFPUOP_CONV_32_64(efdctuf); 1157GEN_SPEFPUOP_CONV_32_64(efdctsf); 1158GEN_SPEFPUOP_CONV_32_64(efdctuiz); 1159GEN_SPEFPUOP_CONV_32_64(efdctsiz); 1160GEN_SPEFPUOP_CONV_64_32(efdcfs); 1161GEN_SPEFPUOP_CONV_64_64(efdcfuid); 1162GEN_SPEFPUOP_CONV_64_64(efdcfsid); 1163GEN_SPEFPUOP_CONV_64_64(efdctuidz); 1164GEN_SPEFPUOP_CONV_64_64(efdctsidz); 1165 1166/* Comparison */ 1167GEN_SPEFPUOP_COMP_64(efdcmpgt); 1168GEN_SPEFPUOP_COMP_64(efdcmplt); 1169GEN_SPEFPUOP_COMP_64(efdcmpeq); 1170GEN_SPEFPUOP_COMP_64(efdtstgt); 1171GEN_SPEFPUOP_COMP_64(efdtstlt); 1172GEN_SPEFPUOP_COMP_64(efdtsteq); 1173 1174/* Opcodes definitions */ 1175GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); // 1176GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1177GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, 0x0000F800, PPC_SPE_DOUBLE); // 1178GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, 0xFFFFFFFF, PPC_SPE_DOUBLE); // 1179GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, 0x00000000, PPC_SPE_DOUBLE); // 1180GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1181GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); // 1182GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, 0x00180000, PPC_SPE_DOUBLE); // 1183GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1184GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1185GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1186GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, 0x00180000, PPC_SPE_DOUBLE); // 1187GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); // 1188GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, 0xFFFFFFFF, PPC_SPE_DOUBLE); // 1189GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, 0x00600000, PPC_SPE_DOUBLE); // 1190GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, 0xFFFFFFFF, PPC_SPE_DOUBLE); // 1191 1192#undef GEN_SPE 1193#undef GEN_SPEOP_LDST 1194