1/* 2 * translate-fp.c 3 * 4 * Standard FPU translation 5 */ 6 7static inline void gen_reset_fpstatus(void) 8{ 9 gen_helper_reset_fpstatus(cpu_env); 10} 11 12static inline void gen_compute_fprf_float64(TCGv_i64 arg) 13{ 14 gen_helper_compute_fprf_float64(cpu_env, arg); 15 gen_helper_float_check_status(cpu_env); 16} 17 18#if defined(TARGET_PPC64) 19static void gen_set_cr1_from_fpscr(DisasContext *ctx) 20{ 21 TCGv_i32 tmp = tcg_temp_new_i32(); 22 tcg_gen_trunc_tl_i32(tmp, cpu_fpscr); 23 tcg_gen_shri_i32(cpu_crf[1], tmp, 28); 24 tcg_temp_free_i32(tmp); 25} 26#else 27static void gen_set_cr1_from_fpscr(DisasContext *ctx) 28{ 29 tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28); 30} 31#endif 32 33/*** Floating-Point arithmetic ***/ 34#define _GEN_FLOAT_ACB(name, op1, op2, set_fprf, type) \ 35static void gen_f##name(DisasContext *ctx) \ 36{ \ 37 TCGv_i64 t0; \ 38 TCGv_i64 t1; \ 39 TCGv_i64 t2; \ 40 TCGv_i64 t3; \ 41 if (unlikely(!ctx->fpu_enabled)) { \ 42 gen_exception(ctx, POWERPC_EXCP_FPU); \ 43 return; \ 44 } \ 45 t0 = tcg_temp_new_i64(); \ 46 t1 = tcg_temp_new_i64(); \ 47 t2 = tcg_temp_new_i64(); \ 48 t3 = tcg_temp_new_i64(); \ 49 gen_reset_fpstatus(); \ 50 get_fpr(t0, rA(ctx->opcode)); \ 51 get_fpr(t1, rC(ctx->opcode)); \ 52 get_fpr(t2, rB(ctx->opcode)); \ 53 gen_helper_f##name(t3, cpu_env, t0, t1, t2); \ 54 set_fpr(rD(ctx->opcode), t3); \ 55 if (set_fprf) { \ 56 gen_compute_fprf_float64(t3); \ 57 } \ 58 if (unlikely(Rc(ctx->opcode) != 0)) { \ 59 gen_set_cr1_from_fpscr(ctx); \ 60 } \ 61 tcg_temp_free_i64(t0); \ 62 tcg_temp_free_i64(t1); \ 63 tcg_temp_free_i64(t2); \ 64 tcg_temp_free_i64(t3); \ 65} 66 67#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \ 68_GEN_FLOAT_ACB(name, 0x3F, op2, set_fprf, type); \ 69_GEN_FLOAT_ACB(name##s, 0x3B, op2, set_fprf, type); 70 71#define _GEN_FLOAT_AB(name, op1, op2, inval, set_fprf, type) \ 72static void gen_f##name(DisasContext *ctx) \ 73{ \ 74 TCGv_i64 t0; \ 75 TCGv_i64 t1; \ 76 TCGv_i64 t2; \ 77 if (unlikely(!ctx->fpu_enabled)) { \ 78 gen_exception(ctx, POWERPC_EXCP_FPU); \ 79 return; \ 80 } \ 81 t0 = tcg_temp_new_i64(); \ 82 t1 = tcg_temp_new_i64(); \ 83 t2 = tcg_temp_new_i64(); \ 84 gen_reset_fpstatus(); \ 85 get_fpr(t0, rA(ctx->opcode)); \ 86 get_fpr(t1, rB(ctx->opcode)); \ 87 gen_helper_f##name(t2, cpu_env, t0, t1); \ 88 set_fpr(rD(ctx->opcode), t2); \ 89 if (set_fprf) { \ 90 gen_compute_fprf_float64(t2); \ 91 } \ 92 if (unlikely(Rc(ctx->opcode) != 0)) { \ 93 gen_set_cr1_from_fpscr(ctx); \ 94 } \ 95 tcg_temp_free_i64(t0); \ 96 tcg_temp_free_i64(t1); \ 97 tcg_temp_free_i64(t2); \ 98} 99#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \ 100_GEN_FLOAT_AB(name, 0x3F, op2, inval, set_fprf, type); \ 101_GEN_FLOAT_AB(name##s, 0x3B, op2, inval, set_fprf, type); 102 103#define _GEN_FLOAT_AC(name, op1, op2, inval, set_fprf, type) \ 104static void gen_f##name(DisasContext *ctx) \ 105{ \ 106 TCGv_i64 t0; \ 107 TCGv_i64 t1; \ 108 TCGv_i64 t2; \ 109 if (unlikely(!ctx->fpu_enabled)) { \ 110 gen_exception(ctx, POWERPC_EXCP_FPU); \ 111 return; \ 112 } \ 113 t0 = tcg_temp_new_i64(); \ 114 t1 = tcg_temp_new_i64(); \ 115 t2 = tcg_temp_new_i64(); \ 116 gen_reset_fpstatus(); \ 117 get_fpr(t0, rA(ctx->opcode)); \ 118 get_fpr(t1, rC(ctx->opcode)); \ 119 gen_helper_f##name(t2, cpu_env, t0, t1); \ 120 set_fpr(rD(ctx->opcode), t2); \ 121 if (set_fprf) { \ 122 gen_compute_fprf_float64(t2); \ 123 } \ 124 if (unlikely(Rc(ctx->opcode) != 0)) { \ 125 gen_set_cr1_from_fpscr(ctx); \ 126 } \ 127 tcg_temp_free_i64(t0); \ 128 tcg_temp_free_i64(t1); \ 129 tcg_temp_free_i64(t2); \ 130} 131#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \ 132_GEN_FLOAT_AC(name, 0x3F, op2, inval, set_fprf, type); \ 133_GEN_FLOAT_AC(name##s, 0x3B, op2, inval, set_fprf, type); 134 135#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \ 136static void gen_f##name(DisasContext *ctx) \ 137{ \ 138 TCGv_i64 t0; \ 139 TCGv_i64 t1; \ 140 if (unlikely(!ctx->fpu_enabled)) { \ 141 gen_exception(ctx, POWERPC_EXCP_FPU); \ 142 return; \ 143 } \ 144 t0 = tcg_temp_new_i64(); \ 145 t1 = tcg_temp_new_i64(); \ 146 gen_reset_fpstatus(); \ 147 get_fpr(t0, rB(ctx->opcode)); \ 148 gen_helper_f##name(t1, cpu_env, t0); \ 149 set_fpr(rD(ctx->opcode), t1); \ 150 if (set_fprf) { \ 151 gen_helper_compute_fprf_float64(cpu_env, t1); \ 152 } \ 153 gen_helper_float_check_status(cpu_env); \ 154 if (unlikely(Rc(ctx->opcode) != 0)) { \ 155 gen_set_cr1_from_fpscr(ctx); \ 156 } \ 157 tcg_temp_free_i64(t0); \ 158 tcg_temp_free_i64(t1); \ 159} 160 161#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \ 162static void gen_f##name(DisasContext *ctx) \ 163{ \ 164 TCGv_i64 t0; \ 165 TCGv_i64 t1; \ 166 if (unlikely(!ctx->fpu_enabled)) { \ 167 gen_exception(ctx, POWERPC_EXCP_FPU); \ 168 return; \ 169 } \ 170 t0 = tcg_temp_new_i64(); \ 171 t1 = tcg_temp_new_i64(); \ 172 gen_reset_fpstatus(); \ 173 get_fpr(t0, rB(ctx->opcode)); \ 174 gen_helper_f##name(t1, cpu_env, t0); \ 175 set_fpr(rD(ctx->opcode), t1); \ 176 if (set_fprf) { \ 177 gen_compute_fprf_float64(t1); \ 178 } \ 179 if (unlikely(Rc(ctx->opcode) != 0)) { \ 180 gen_set_cr1_from_fpscr(ctx); \ 181 } \ 182 tcg_temp_free_i64(t0); \ 183 tcg_temp_free_i64(t1); \ 184} 185 186/* fadd - fadds */ 187GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT); 188/* fdiv - fdivs */ 189GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT); 190/* fmul - fmuls */ 191GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT); 192 193/* fre */ 194GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT); 195 196/* fres */ 197GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES); 198 199/* frsqrte */ 200GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE); 201 202/* frsqrtes */ 203static void gen_frsqrtes(DisasContext *ctx) 204{ 205 TCGv_i64 t0; 206 TCGv_i64 t1; 207 if (unlikely(!ctx->fpu_enabled)) { 208 gen_exception(ctx, POWERPC_EXCP_FPU); 209 return; 210 } 211 t0 = tcg_temp_new_i64(); 212 t1 = tcg_temp_new_i64(); 213 gen_reset_fpstatus(); 214 get_fpr(t0, rB(ctx->opcode)); 215 gen_helper_frsqrtes(t1, cpu_env, t0); 216 set_fpr(rD(ctx->opcode), t1); 217 gen_compute_fprf_float64(t1); 218 if (unlikely(Rc(ctx->opcode) != 0)) { 219 gen_set_cr1_from_fpscr(ctx); 220 } 221 tcg_temp_free_i64(t0); 222 tcg_temp_free_i64(t1); 223} 224 225static bool trans_FSEL(DisasContext *ctx, arg_A *a) 226{ 227 TCGv_i64 t0, t1, t2; 228 229 REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSEL); 230 REQUIRE_FPU(ctx); 231 232 t0 = tcg_temp_new_i64(); 233 t1 = tcg_temp_new_i64(); 234 t2 = tcg_temp_new_i64(); 235 236 get_fpr(t0, a->fra); 237 get_fpr(t1, a->frb); 238 get_fpr(t2, a->frc); 239 240 gen_helper_FSEL(t0, t0, t1, t2); 241 set_fpr(a->frt, t0); 242 if (a->rc) { 243 gen_set_cr1_from_fpscr(ctx); 244 } 245 246 tcg_temp_free_i64(t0); 247 tcg_temp_free_i64(t1); 248 tcg_temp_free_i64(t2); 249 250 return true; 251} 252 253/* fsub - fsubs */ 254GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT); 255/* Optional: */ 256 257static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a, 258 void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64)) 259{ 260 TCGv_i64 t0, t1; 261 262 REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSQRT); 263 REQUIRE_FPU(ctx); 264 265 t0 = tcg_temp_new_i64(); 266 t1 = tcg_temp_new_i64(); 267 268 gen_reset_fpstatus(); 269 get_fpr(t0, a->frb); 270 helper(t1, cpu_env, t0); 271 set_fpr(a->frt, t1); 272 gen_compute_fprf_float64(t1); 273 if (unlikely(a->rc != 0)) { 274 gen_set_cr1_from_fpscr(ctx); 275 } 276 277 tcg_temp_free_i64(t0); 278 tcg_temp_free_i64(t1); 279 280 return true; 281} 282 283TRANS(FSQRT, do_helper_fsqrt, gen_helper_fsqrt); 284 285static void gen_fsqrts(DisasContext *ctx) 286{ 287 TCGv_i64 t0; 288 TCGv_i64 t1; 289 if (unlikely(!ctx->fpu_enabled)) { 290 gen_exception(ctx, POWERPC_EXCP_FPU); 291 return; 292 } 293 t0 = tcg_temp_new_i64(); 294 t1 = tcg_temp_new_i64(); 295 gen_reset_fpstatus(); 296 get_fpr(t0, rB(ctx->opcode)); 297 gen_helper_fsqrts(t1, cpu_env, t0); 298 set_fpr(rD(ctx->opcode), t1); 299 gen_compute_fprf_float64(t1); 300 if (unlikely(Rc(ctx->opcode) != 0)) { 301 gen_set_cr1_from_fpscr(ctx); 302 } 303 tcg_temp_free_i64(t0); 304 tcg_temp_free_i64(t1); 305} 306 307/*** Floating-Point multiply-and-add ***/ 308/* fmadd - fmadds */ 309GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT); 310/* fmsub - fmsubs */ 311GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT); 312/* fnmadd - fnmadds */ 313GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT); 314/* fnmsub - fnmsubs */ 315GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT); 316 317/*** Floating-Point round & convert ***/ 318/* fctiw */ 319GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT); 320/* fctiwu */ 321GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206); 322/* fctiwz */ 323GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT); 324/* fctiwuz */ 325GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206); 326/* frsp */ 327GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT); 328/* fcfid */ 329GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64); 330/* fcfids */ 331GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206); 332/* fcfidu */ 333GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206); 334/* fcfidus */ 335GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206); 336/* fctid */ 337GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64); 338/* fctidu */ 339GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206); 340/* fctidz */ 341GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64); 342/* fctidu */ 343GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206); 344 345/* frin */ 346GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT); 347/* friz */ 348GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT); 349/* frip */ 350GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT); 351/* frim */ 352GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT); 353 354static void gen_ftdiv(DisasContext *ctx) 355{ 356 TCGv_i64 t0; 357 TCGv_i64 t1; 358 if (unlikely(!ctx->fpu_enabled)) { 359 gen_exception(ctx, POWERPC_EXCP_FPU); 360 return; 361 } 362 t0 = tcg_temp_new_i64(); 363 t1 = tcg_temp_new_i64(); 364 get_fpr(t0, rA(ctx->opcode)); 365 get_fpr(t1, rB(ctx->opcode)); 366 gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1); 367 tcg_temp_free_i64(t0); 368 tcg_temp_free_i64(t1); 369} 370 371static void gen_ftsqrt(DisasContext *ctx) 372{ 373 TCGv_i64 t0; 374 if (unlikely(!ctx->fpu_enabled)) { 375 gen_exception(ctx, POWERPC_EXCP_FPU); 376 return; 377 } 378 t0 = tcg_temp_new_i64(); 379 get_fpr(t0, rB(ctx->opcode)); 380 gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0); 381 tcg_temp_free_i64(t0); 382} 383 384 385 386/*** Floating-Point compare ***/ 387 388/* fcmpo */ 389static void gen_fcmpo(DisasContext *ctx) 390{ 391 TCGv_i32 crf; 392 TCGv_i64 t0; 393 TCGv_i64 t1; 394 if (unlikely(!ctx->fpu_enabled)) { 395 gen_exception(ctx, POWERPC_EXCP_FPU); 396 return; 397 } 398 t0 = tcg_temp_new_i64(); 399 t1 = tcg_temp_new_i64(); 400 gen_reset_fpstatus(); 401 crf = tcg_const_i32(crfD(ctx->opcode)); 402 get_fpr(t0, rA(ctx->opcode)); 403 get_fpr(t1, rB(ctx->opcode)); 404 gen_helper_fcmpo(cpu_env, t0, t1, crf); 405 tcg_temp_free_i32(crf); 406 gen_helper_float_check_status(cpu_env); 407 tcg_temp_free_i64(t0); 408 tcg_temp_free_i64(t1); 409} 410 411/* fcmpu */ 412static void gen_fcmpu(DisasContext *ctx) 413{ 414 TCGv_i32 crf; 415 TCGv_i64 t0; 416 TCGv_i64 t1; 417 if (unlikely(!ctx->fpu_enabled)) { 418 gen_exception(ctx, POWERPC_EXCP_FPU); 419 return; 420 } 421 t0 = tcg_temp_new_i64(); 422 t1 = tcg_temp_new_i64(); 423 gen_reset_fpstatus(); 424 crf = tcg_const_i32(crfD(ctx->opcode)); 425 get_fpr(t0, rA(ctx->opcode)); 426 get_fpr(t1, rB(ctx->opcode)); 427 gen_helper_fcmpu(cpu_env, t0, t1, crf); 428 tcg_temp_free_i32(crf); 429 gen_helper_float_check_status(cpu_env); 430 tcg_temp_free_i64(t0); 431 tcg_temp_free_i64(t1); 432} 433 434/*** Floating-point move ***/ 435/* fabs */ 436/* XXX: beware that fabs never checks for NaNs nor update FPSCR */ 437static void gen_fabs(DisasContext *ctx) 438{ 439 TCGv_i64 t0; 440 TCGv_i64 t1; 441 if (unlikely(!ctx->fpu_enabled)) { 442 gen_exception(ctx, POWERPC_EXCP_FPU); 443 return; 444 } 445 t0 = tcg_temp_new_i64(); 446 t1 = tcg_temp_new_i64(); 447 get_fpr(t0, rB(ctx->opcode)); 448 tcg_gen_andi_i64(t1, t0, ~(1ULL << 63)); 449 set_fpr(rD(ctx->opcode), t1); 450 if (unlikely(Rc(ctx->opcode))) { 451 gen_set_cr1_from_fpscr(ctx); 452 } 453 tcg_temp_free_i64(t0); 454 tcg_temp_free_i64(t1); 455} 456 457/* fmr - fmr. */ 458/* XXX: beware that fmr never checks for NaNs nor update FPSCR */ 459static void gen_fmr(DisasContext *ctx) 460{ 461 TCGv_i64 t0; 462 if (unlikely(!ctx->fpu_enabled)) { 463 gen_exception(ctx, POWERPC_EXCP_FPU); 464 return; 465 } 466 t0 = tcg_temp_new_i64(); 467 get_fpr(t0, rB(ctx->opcode)); 468 set_fpr(rD(ctx->opcode), t0); 469 if (unlikely(Rc(ctx->opcode))) { 470 gen_set_cr1_from_fpscr(ctx); 471 } 472 tcg_temp_free_i64(t0); 473} 474 475/* fnabs */ 476/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */ 477static void gen_fnabs(DisasContext *ctx) 478{ 479 TCGv_i64 t0; 480 TCGv_i64 t1; 481 if (unlikely(!ctx->fpu_enabled)) { 482 gen_exception(ctx, POWERPC_EXCP_FPU); 483 return; 484 } 485 t0 = tcg_temp_new_i64(); 486 t1 = tcg_temp_new_i64(); 487 get_fpr(t0, rB(ctx->opcode)); 488 tcg_gen_ori_i64(t1, t0, 1ULL << 63); 489 set_fpr(rD(ctx->opcode), t1); 490 if (unlikely(Rc(ctx->opcode))) { 491 gen_set_cr1_from_fpscr(ctx); 492 } 493 tcg_temp_free_i64(t0); 494 tcg_temp_free_i64(t1); 495} 496 497/* fneg */ 498/* XXX: beware that fneg never checks for NaNs nor update FPSCR */ 499static void gen_fneg(DisasContext *ctx) 500{ 501 TCGv_i64 t0; 502 TCGv_i64 t1; 503 if (unlikely(!ctx->fpu_enabled)) { 504 gen_exception(ctx, POWERPC_EXCP_FPU); 505 return; 506 } 507 t0 = tcg_temp_new_i64(); 508 t1 = tcg_temp_new_i64(); 509 get_fpr(t0, rB(ctx->opcode)); 510 tcg_gen_xori_i64(t1, t0, 1ULL << 63); 511 set_fpr(rD(ctx->opcode), t1); 512 if (unlikely(Rc(ctx->opcode))) { 513 gen_set_cr1_from_fpscr(ctx); 514 } 515 tcg_temp_free_i64(t0); 516 tcg_temp_free_i64(t1); 517} 518 519/* fcpsgn: PowerPC 2.05 specification */ 520/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */ 521static void gen_fcpsgn(DisasContext *ctx) 522{ 523 TCGv_i64 t0; 524 TCGv_i64 t1; 525 TCGv_i64 t2; 526 if (unlikely(!ctx->fpu_enabled)) { 527 gen_exception(ctx, POWERPC_EXCP_FPU); 528 return; 529 } 530 t0 = tcg_temp_new_i64(); 531 t1 = tcg_temp_new_i64(); 532 t2 = tcg_temp_new_i64(); 533 get_fpr(t0, rA(ctx->opcode)); 534 get_fpr(t1, rB(ctx->opcode)); 535 tcg_gen_deposit_i64(t2, t0, t1, 0, 63); 536 set_fpr(rD(ctx->opcode), t2); 537 if (unlikely(Rc(ctx->opcode))) { 538 gen_set_cr1_from_fpscr(ctx); 539 } 540 tcg_temp_free_i64(t0); 541 tcg_temp_free_i64(t1); 542 tcg_temp_free_i64(t2); 543} 544 545static void gen_fmrgew(DisasContext *ctx) 546{ 547 TCGv_i64 b0; 548 TCGv_i64 t0; 549 TCGv_i64 t1; 550 if (unlikely(!ctx->fpu_enabled)) { 551 gen_exception(ctx, POWERPC_EXCP_FPU); 552 return; 553 } 554 b0 = tcg_temp_new_i64(); 555 t0 = tcg_temp_new_i64(); 556 t1 = tcg_temp_new_i64(); 557 get_fpr(t0, rB(ctx->opcode)); 558 tcg_gen_shri_i64(b0, t0, 32); 559 get_fpr(t0, rA(ctx->opcode)); 560 tcg_gen_deposit_i64(t1, t0, b0, 0, 32); 561 set_fpr(rD(ctx->opcode), t1); 562 tcg_temp_free_i64(b0); 563 tcg_temp_free_i64(t0); 564 tcg_temp_free_i64(t1); 565} 566 567static void gen_fmrgow(DisasContext *ctx) 568{ 569 TCGv_i64 t0; 570 TCGv_i64 t1; 571 TCGv_i64 t2; 572 if (unlikely(!ctx->fpu_enabled)) { 573 gen_exception(ctx, POWERPC_EXCP_FPU); 574 return; 575 } 576 t0 = tcg_temp_new_i64(); 577 t1 = tcg_temp_new_i64(); 578 t2 = tcg_temp_new_i64(); 579 get_fpr(t0, rB(ctx->opcode)); 580 get_fpr(t1, rA(ctx->opcode)); 581 tcg_gen_deposit_i64(t2, t0, t1, 32, 32); 582 set_fpr(rD(ctx->opcode), t2); 583 tcg_temp_free_i64(t0); 584 tcg_temp_free_i64(t1); 585 tcg_temp_free_i64(t2); 586} 587 588/*** Floating-Point status & ctrl register ***/ 589 590/* mcrfs */ 591static void gen_mcrfs(DisasContext *ctx) 592{ 593 TCGv tmp = tcg_temp_new(); 594 TCGv_i32 tmask; 595 TCGv_i64 tnew_fpscr = tcg_temp_new_i64(); 596 int bfa; 597 int nibble; 598 int shift; 599 600 if (unlikely(!ctx->fpu_enabled)) { 601 gen_exception(ctx, POWERPC_EXCP_FPU); 602 return; 603 } 604 bfa = crfS(ctx->opcode); 605 nibble = 7 - bfa; 606 shift = 4 * nibble; 607 tcg_gen_shri_tl(tmp, cpu_fpscr, shift); 608 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); 609 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 610 0xf); 611 tcg_temp_free(tmp); 612 tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr); 613 /* Only the exception bits (including FX) should be cleared if read */ 614 tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, 615 ~((0xF << shift) & FP_EX_CLEAR_BITS)); 616 /* FEX and VX need to be updated, so don't set fpscr directly */ 617 tmask = tcg_const_i32(1 << nibble); 618 gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask); 619 tcg_temp_free_i32(tmask); 620 tcg_temp_free_i64(tnew_fpscr); 621} 622 623static TCGv_i64 place_from_fpscr(int rt, uint64_t mask) 624{ 625 TCGv_i64 fpscr = tcg_temp_new_i64(); 626 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 627 628 tcg_gen_extu_tl_i64(fpscr, cpu_fpscr); 629 tcg_gen_andi_i64(fpscr_masked, fpscr, mask); 630 set_fpr(rt, fpscr_masked); 631 632 tcg_temp_free_i64(fpscr_masked); 633 634 return fpscr; 635} 636 637static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask, 638 TCGv_i64 set_mask, uint32_t store_mask) 639{ 640 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 641 TCGv_i32 st_mask = tcg_constant_i32(store_mask); 642 643 tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask); 644 tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask); 645 gen_helper_store_fpscr(cpu_env, fpscr_masked, st_mask); 646 647 tcg_temp_free_i64(fpscr_masked); 648} 649 650static bool trans_MFFS(DisasContext *ctx, arg_X_t_rc *a) 651{ 652 TCGv_i64 fpscr; 653 654 REQUIRE_FPU(ctx); 655 656 gen_reset_fpstatus(); 657 fpscr = place_from_fpscr(a->rt, UINT64_MAX); 658 if (a->rc) { 659 gen_set_cr1_from_fpscr(ctx); 660 } 661 662 tcg_temp_free_i64(fpscr); 663 664 return true; 665} 666 667static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a) 668{ 669 TCGv_i64 fpscr; 670 671 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 672 REQUIRE_FPU(ctx); 673 674 gen_reset_fpstatus(); 675 fpscr = place_from_fpscr(a->rt, UINT64_MAX); 676 store_fpscr_masked(fpscr, FP_ENABLES, tcg_constant_i64(0), 0x0003); 677 678 tcg_temp_free_i64(fpscr); 679 680 return true; 681} 682 683static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a) 684{ 685 TCGv_i64 t1, fpscr; 686 687 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 688 REQUIRE_FPU(ctx); 689 690 t1 = tcg_temp_new_i64(); 691 get_fpr(t1, a->rb); 692 tcg_gen_andi_i64(t1, t1, FP_RN); 693 694 gen_reset_fpstatus(); 695 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 696 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 697 698 tcg_temp_free_i64(t1); 699 tcg_temp_free_i64(fpscr); 700 701 return true; 702} 703 704static bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a) 705{ 706 TCGv_i64 t1, fpscr; 707 708 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 709 REQUIRE_FPU(ctx); 710 711 t1 = tcg_temp_new_i64(); 712 get_fpr(t1, a->rb); 713 tcg_gen_andi_i64(t1, t1, FP_DRN); 714 715 gen_reset_fpstatus(); 716 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 717 store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100); 718 719 tcg_temp_free_i64(t1); 720 tcg_temp_free_i64(fpscr); 721 722 return true; 723} 724 725static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a) 726{ 727 TCGv_i64 t1, fpscr; 728 729 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 730 REQUIRE_FPU(ctx); 731 732 t1 = tcg_temp_new_i64(); 733 tcg_gen_movi_i64(t1, a->imm); 734 735 gen_reset_fpstatus(); 736 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 737 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 738 739 tcg_temp_free_i64(t1); 740 tcg_temp_free_i64(fpscr); 741 742 return true; 743} 744 745static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 *a) 746{ 747 TCGv_i64 t1, fpscr; 748 749 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 750 REQUIRE_FPU(ctx); 751 752 t1 = tcg_temp_new_i64(); 753 tcg_gen_movi_i64(t1, (uint64_t)a->imm << FPSCR_DRN0); 754 755 gen_reset_fpstatus(); 756 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 757 store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100); 758 759 tcg_temp_free_i64(t1); 760 tcg_temp_free_i64(fpscr); 761 762 return true; 763} 764 765static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a) 766{ 767 TCGv_i64 fpscr; 768 769 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 770 REQUIRE_FPU(ctx); 771 772 gen_reset_fpstatus(); 773 fpscr = place_from_fpscr(a->rt, 774 FP_DRN | FP_STATUS | FP_ENABLES | FP_NI | FP_RN); 775 776 tcg_temp_free_i64(fpscr); 777 778 return true; 779} 780 781/* mtfsb0 */ 782static void gen_mtfsb0(DisasContext *ctx) 783{ 784 uint8_t crb; 785 786 if (unlikely(!ctx->fpu_enabled)) { 787 gen_exception(ctx, POWERPC_EXCP_FPU); 788 return; 789 } 790 crb = 31 - crbD(ctx->opcode); 791 gen_reset_fpstatus(); 792 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { 793 TCGv_i32 t0; 794 t0 = tcg_const_i32(crb); 795 gen_helper_fpscr_clrbit(cpu_env, t0); 796 tcg_temp_free_i32(t0); 797 } 798 if (unlikely(Rc(ctx->opcode) != 0)) { 799 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 800 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 801 } 802} 803 804/* mtfsb1 */ 805static void gen_mtfsb1(DisasContext *ctx) 806{ 807 uint8_t crb; 808 809 if (unlikely(!ctx->fpu_enabled)) { 810 gen_exception(ctx, POWERPC_EXCP_FPU); 811 return; 812 } 813 crb = 31 - crbD(ctx->opcode); 814 /* XXX: we pretend we can only do IEEE floating-point computations */ 815 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { 816 TCGv_i32 t0; 817 t0 = tcg_const_i32(crb); 818 gen_helper_fpscr_setbit(cpu_env, t0); 819 tcg_temp_free_i32(t0); 820 } 821 if (unlikely(Rc(ctx->opcode) != 0)) { 822 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 823 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 824 } 825 /* We can raise a deferred exception */ 826 gen_helper_fpscr_check_status(cpu_env); 827} 828 829/* mtfsf */ 830static void gen_mtfsf(DisasContext *ctx) 831{ 832 TCGv_i32 t0; 833 TCGv_i64 t1; 834 int flm, l, w; 835 836 if (unlikely(!ctx->fpu_enabled)) { 837 gen_exception(ctx, POWERPC_EXCP_FPU); 838 return; 839 } 840 flm = FPFLM(ctx->opcode); 841 l = FPL(ctx->opcode); 842 w = FPW(ctx->opcode); 843 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 844 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 845 return; 846 } 847 if (l) { 848 t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff); 849 } else { 850 t0 = tcg_const_i32(flm << (w * 8)); 851 } 852 t1 = tcg_temp_new_i64(); 853 get_fpr(t1, rB(ctx->opcode)); 854 gen_helper_store_fpscr(cpu_env, t1, t0); 855 tcg_temp_free_i32(t0); 856 if (unlikely(Rc(ctx->opcode) != 0)) { 857 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 858 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 859 } 860 /* We can raise a deferred exception */ 861 gen_helper_fpscr_check_status(cpu_env); 862 tcg_temp_free_i64(t1); 863} 864 865/* mtfsfi */ 866static void gen_mtfsfi(DisasContext *ctx) 867{ 868 int bf, sh, w; 869 TCGv_i64 t0; 870 TCGv_i32 t1; 871 872 if (unlikely(!ctx->fpu_enabled)) { 873 gen_exception(ctx, POWERPC_EXCP_FPU); 874 return; 875 } 876 w = FPW(ctx->opcode); 877 bf = FPBF(ctx->opcode); 878 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 879 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 880 return; 881 } 882 sh = (8 * w) + 7 - bf; 883 t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh)); 884 t1 = tcg_const_i32(1 << sh); 885 gen_helper_store_fpscr(cpu_env, t0, t1); 886 tcg_temp_free_i64(t0); 887 tcg_temp_free_i32(t1); 888 if (unlikely(Rc(ctx->opcode) != 0)) { 889 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 890 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 891 } 892 /* We can raise a deferred exception */ 893 gen_helper_fpscr_check_status(cpu_env); 894} 895 896static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr) 897{ 898 TCGv_i32 tmp = tcg_temp_new_i32(); 899 tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 900 gen_helper_todouble(dest, tmp); 901 tcg_temp_free_i32(tmp); 902} 903 904/* lfdepx (external PID lfdx) */ 905static void gen_lfdepx(DisasContext *ctx) 906{ 907 TCGv EA; 908 TCGv_i64 t0; 909 CHK_SV(ctx); 910 if (unlikely(!ctx->fpu_enabled)) { 911 gen_exception(ctx, POWERPC_EXCP_FPU); 912 return; 913 } 914 gen_set_access_type(ctx, ACCESS_FLOAT); 915 EA = tcg_temp_new(); 916 t0 = tcg_temp_new_i64(); 917 gen_addr_reg_index(ctx, EA); 918 tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ)); 919 set_fpr(rD(ctx->opcode), t0); 920 tcg_temp_free(EA); 921 tcg_temp_free_i64(t0); 922} 923 924/* lfdp */ 925static void gen_lfdp(DisasContext *ctx) 926{ 927 TCGv EA; 928 TCGv_i64 t0; 929 if (unlikely(!ctx->fpu_enabled)) { 930 gen_exception(ctx, POWERPC_EXCP_FPU); 931 return; 932 } 933 gen_set_access_type(ctx, ACCESS_FLOAT); 934 EA = tcg_temp_new(); 935 gen_addr_imm_index(ctx, EA, 0); 936 t0 = tcg_temp_new_i64(); 937 /* 938 * We only need to swap high and low halves. gen_qemu_ld64_i64 939 * does necessary 64-bit byteswap already. 940 */ 941 if (unlikely(ctx->le_mode)) { 942 gen_qemu_ld64_i64(ctx, t0, EA); 943 set_fpr(rD(ctx->opcode) + 1, t0); 944 tcg_gen_addi_tl(EA, EA, 8); 945 gen_qemu_ld64_i64(ctx, t0, EA); 946 set_fpr(rD(ctx->opcode), t0); 947 } else { 948 gen_qemu_ld64_i64(ctx, t0, EA); 949 set_fpr(rD(ctx->opcode), t0); 950 tcg_gen_addi_tl(EA, EA, 8); 951 gen_qemu_ld64_i64(ctx, t0, EA); 952 set_fpr(rD(ctx->opcode) + 1, t0); 953 } 954 tcg_temp_free(EA); 955 tcg_temp_free_i64(t0); 956} 957 958/* lfdpx */ 959static void gen_lfdpx(DisasContext *ctx) 960{ 961 TCGv EA; 962 TCGv_i64 t0; 963 if (unlikely(!ctx->fpu_enabled)) { 964 gen_exception(ctx, POWERPC_EXCP_FPU); 965 return; 966 } 967 gen_set_access_type(ctx, ACCESS_FLOAT); 968 EA = tcg_temp_new(); 969 gen_addr_reg_index(ctx, EA); 970 t0 = tcg_temp_new_i64(); 971 /* 972 * We only need to swap high and low halves. gen_qemu_ld64_i64 973 * does necessary 64-bit byteswap already. 974 */ 975 if (unlikely(ctx->le_mode)) { 976 gen_qemu_ld64_i64(ctx, t0, EA); 977 set_fpr(rD(ctx->opcode) + 1, t0); 978 tcg_gen_addi_tl(EA, EA, 8); 979 gen_qemu_ld64_i64(ctx, t0, EA); 980 set_fpr(rD(ctx->opcode), t0); 981 } else { 982 gen_qemu_ld64_i64(ctx, t0, EA); 983 set_fpr(rD(ctx->opcode), t0); 984 tcg_gen_addi_tl(EA, EA, 8); 985 gen_qemu_ld64_i64(ctx, t0, EA); 986 set_fpr(rD(ctx->opcode) + 1, t0); 987 } 988 tcg_temp_free(EA); 989 tcg_temp_free_i64(t0); 990} 991 992/* lfiwax */ 993static void gen_lfiwax(DisasContext *ctx) 994{ 995 TCGv EA; 996 TCGv t0; 997 TCGv_i64 t1; 998 if (unlikely(!ctx->fpu_enabled)) { 999 gen_exception(ctx, POWERPC_EXCP_FPU); 1000 return; 1001 } 1002 gen_set_access_type(ctx, ACCESS_FLOAT); 1003 EA = tcg_temp_new(); 1004 t0 = tcg_temp_new(); 1005 t1 = tcg_temp_new_i64(); 1006 gen_addr_reg_index(ctx, EA); 1007 gen_qemu_ld32s(ctx, t0, EA); 1008 tcg_gen_ext_tl_i64(t1, t0); 1009 set_fpr(rD(ctx->opcode), t1); 1010 tcg_temp_free(EA); 1011 tcg_temp_free(t0); 1012 tcg_temp_free_i64(t1); 1013} 1014 1015/* lfiwzx */ 1016static void gen_lfiwzx(DisasContext *ctx) 1017{ 1018 TCGv EA; 1019 TCGv_i64 t0; 1020 if (unlikely(!ctx->fpu_enabled)) { 1021 gen_exception(ctx, POWERPC_EXCP_FPU); 1022 return; 1023 } 1024 gen_set_access_type(ctx, ACCESS_FLOAT); 1025 EA = tcg_temp_new(); 1026 t0 = tcg_temp_new_i64(); 1027 gen_addr_reg_index(ctx, EA); 1028 gen_qemu_ld32u_i64(ctx, t0, EA); 1029 set_fpr(rD(ctx->opcode), t0); 1030 tcg_temp_free(EA); 1031 tcg_temp_free_i64(t0); 1032} 1033 1034#define GEN_STXF(name, stop, opc2, opc3, type) \ 1035static void glue(gen_, name##x)(DisasContext *ctx) \ 1036{ \ 1037 TCGv EA; \ 1038 TCGv_i64 t0; \ 1039 if (unlikely(!ctx->fpu_enabled)) { \ 1040 gen_exception(ctx, POWERPC_EXCP_FPU); \ 1041 return; \ 1042 } \ 1043 gen_set_access_type(ctx, ACCESS_FLOAT); \ 1044 EA = tcg_temp_new(); \ 1045 t0 = tcg_temp_new_i64(); \ 1046 gen_addr_reg_index(ctx, EA); \ 1047 get_fpr(t0, rS(ctx->opcode)); \ 1048 gen_qemu_##stop(ctx, t0, EA); \ 1049 tcg_temp_free(EA); \ 1050 tcg_temp_free_i64(t0); \ 1051} 1052 1053static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr) 1054{ 1055 TCGv_i32 tmp = tcg_temp_new_i32(); 1056 gen_helper_tosingle(tmp, src); 1057 tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 1058 tcg_temp_free_i32(tmp); 1059} 1060 1061/* stfdepx (external PID lfdx) */ 1062static void gen_stfdepx(DisasContext *ctx) 1063{ 1064 TCGv EA; 1065 TCGv_i64 t0; 1066 CHK_SV(ctx); 1067 if (unlikely(!ctx->fpu_enabled)) { 1068 gen_exception(ctx, POWERPC_EXCP_FPU); 1069 return; 1070 } 1071 gen_set_access_type(ctx, ACCESS_FLOAT); 1072 EA = tcg_temp_new(); 1073 t0 = tcg_temp_new_i64(); 1074 gen_addr_reg_index(ctx, EA); 1075 get_fpr(t0, rD(ctx->opcode)); 1076 tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ)); 1077 tcg_temp_free(EA); 1078 tcg_temp_free_i64(t0); 1079} 1080 1081/* stfdp */ 1082static void gen_stfdp(DisasContext *ctx) 1083{ 1084 TCGv EA; 1085 TCGv_i64 t0; 1086 if (unlikely(!ctx->fpu_enabled)) { 1087 gen_exception(ctx, POWERPC_EXCP_FPU); 1088 return; 1089 } 1090 gen_set_access_type(ctx, ACCESS_FLOAT); 1091 EA = tcg_temp_new(); 1092 t0 = tcg_temp_new_i64(); 1093 gen_addr_imm_index(ctx, EA, 0); 1094 /* 1095 * We only need to swap high and low halves. gen_qemu_st64_i64 1096 * does necessary 64-bit byteswap already. 1097 */ 1098 if (unlikely(ctx->le_mode)) { 1099 get_fpr(t0, rD(ctx->opcode) + 1); 1100 gen_qemu_st64_i64(ctx, t0, EA); 1101 tcg_gen_addi_tl(EA, EA, 8); 1102 get_fpr(t0, rD(ctx->opcode)); 1103 gen_qemu_st64_i64(ctx, t0, EA); 1104 } else { 1105 get_fpr(t0, rD(ctx->opcode)); 1106 gen_qemu_st64_i64(ctx, t0, EA); 1107 tcg_gen_addi_tl(EA, EA, 8); 1108 get_fpr(t0, rD(ctx->opcode) + 1); 1109 gen_qemu_st64_i64(ctx, t0, EA); 1110 } 1111 tcg_temp_free(EA); 1112 tcg_temp_free_i64(t0); 1113} 1114 1115/* stfdpx */ 1116static void gen_stfdpx(DisasContext *ctx) 1117{ 1118 TCGv EA; 1119 TCGv_i64 t0; 1120 if (unlikely(!ctx->fpu_enabled)) { 1121 gen_exception(ctx, POWERPC_EXCP_FPU); 1122 return; 1123 } 1124 gen_set_access_type(ctx, ACCESS_FLOAT); 1125 EA = tcg_temp_new(); 1126 t0 = tcg_temp_new_i64(); 1127 gen_addr_reg_index(ctx, EA); 1128 /* 1129 * We only need to swap high and low halves. gen_qemu_st64_i64 1130 * does necessary 64-bit byteswap already. 1131 */ 1132 if (unlikely(ctx->le_mode)) { 1133 get_fpr(t0, rD(ctx->opcode) + 1); 1134 gen_qemu_st64_i64(ctx, t0, EA); 1135 tcg_gen_addi_tl(EA, EA, 8); 1136 get_fpr(t0, rD(ctx->opcode)); 1137 gen_qemu_st64_i64(ctx, t0, EA); 1138 } else { 1139 get_fpr(t0, rD(ctx->opcode)); 1140 gen_qemu_st64_i64(ctx, t0, EA); 1141 tcg_gen_addi_tl(EA, EA, 8); 1142 get_fpr(t0, rD(ctx->opcode) + 1); 1143 gen_qemu_st64_i64(ctx, t0, EA); 1144 } 1145 tcg_temp_free(EA); 1146 tcg_temp_free_i64(t0); 1147} 1148 1149/* Optional: */ 1150static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) 1151{ 1152 TCGv t0 = tcg_temp_new(); 1153 tcg_gen_trunc_i64_tl(t0, arg1), 1154 gen_qemu_st32(ctx, t0, arg2); 1155 tcg_temp_free(t0); 1156} 1157/* stfiwx */ 1158GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX); 1159 1160/* Floating-point Load/Store Instructions */ 1161static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ, 1162 bool update, bool store, bool single) 1163{ 1164 TCGv ea; 1165 TCGv_i64 t0; 1166 REQUIRE_INSNS_FLAGS(ctx, FLOAT); 1167 REQUIRE_FPU(ctx); 1168 if (update && ra == 0) { 1169 gen_invalid(ctx); 1170 return true; 1171 } 1172 gen_set_access_type(ctx, ACCESS_FLOAT); 1173 t0 = tcg_temp_new_i64(); 1174 ea = do_ea_calc(ctx, ra, displ); 1175 if (store) { 1176 get_fpr(t0, rt); 1177 if (single) { 1178 gen_qemu_st32fs(ctx, t0, ea); 1179 } else { 1180 gen_qemu_st64_i64(ctx, t0, ea); 1181 } 1182 } else { 1183 if (single) { 1184 gen_qemu_ld32fs(ctx, t0, ea); 1185 } else { 1186 gen_qemu_ld64_i64(ctx, t0, ea); 1187 } 1188 set_fpr(rt, t0); 1189 } 1190 if (update) { 1191 tcg_gen_mov_tl(cpu_gpr[ra], ea); 1192 } 1193 tcg_temp_free_i64(t0); 1194 tcg_temp_free(ea); 1195 return true; 1196} 1197 1198static bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store, 1199 bool single) 1200{ 1201 return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, 1202 single); 1203} 1204 1205static bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update, 1206 bool store, bool single) 1207{ 1208 arg_D d; 1209 if (!resolve_PLS_D(ctx, &d, a)) { 1210 return true; 1211 } 1212 return do_lsfp_D(ctx, &d, update, store, single); 1213} 1214 1215static bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update, 1216 bool store, bool single) 1217{ 1218 return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single); 1219} 1220 1221TRANS(LFS, do_lsfp_D, false, false, true) 1222TRANS(LFSU, do_lsfp_D, true, false, true) 1223TRANS(LFSX, do_lsfp_X, false, false, true) 1224TRANS(LFSUX, do_lsfp_X, true, false, true) 1225TRANS(PLFS, do_lsfp_PLS_D, false, false, true) 1226 1227TRANS(LFD, do_lsfp_D, false, false, false) 1228TRANS(LFDU, do_lsfp_D, true, false, false) 1229TRANS(LFDX, do_lsfp_X, false, false, false) 1230TRANS(LFDUX, do_lsfp_X, true, false, false) 1231TRANS(PLFD, do_lsfp_PLS_D, false, false, false) 1232 1233TRANS(STFS, do_lsfp_D, false, true, true) 1234TRANS(STFSU, do_lsfp_D, true, true, true) 1235TRANS(STFSX, do_lsfp_X, false, true, true) 1236TRANS(STFSUX, do_lsfp_X, true, true, true) 1237TRANS(PSTFS, do_lsfp_PLS_D, false, true, true) 1238 1239TRANS(STFD, do_lsfp_D, false, true, false) 1240TRANS(STFDU, do_lsfp_D, true, true, false) 1241TRANS(STFDX, do_lsfp_X, false, true, false) 1242TRANS(STFDUX, do_lsfp_X, true, true, false) 1243TRANS(PSTFD, do_lsfp_PLS_D, false, true, false) 1244 1245#undef _GEN_FLOAT_ACB 1246#undef GEN_FLOAT_ACB 1247#undef _GEN_FLOAT_AB 1248#undef GEN_FLOAT_AB 1249#undef _GEN_FLOAT_AC 1250#undef GEN_FLOAT_AC 1251#undef GEN_FLOAT_B 1252#undef GEN_FLOAT_BS 1253 1254#undef GEN_LDF 1255#undef GEN_LDUF 1256#undef GEN_LDUXF 1257#undef GEN_LDXF 1258#undef GEN_LDFS 1259 1260#undef GEN_STF 1261#undef GEN_STUF 1262#undef GEN_STUXF 1263#undef GEN_STXF 1264#undef GEN_STFS 1265