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 257/* fsqrt */ 258static void gen_fsqrt(DisasContext *ctx) 259{ 260 TCGv_i64 t0; 261 TCGv_i64 t1; 262 if (unlikely(!ctx->fpu_enabled)) { 263 gen_exception(ctx, POWERPC_EXCP_FPU); 264 return; 265 } 266 t0 = tcg_temp_new_i64(); 267 t1 = tcg_temp_new_i64(); 268 gen_reset_fpstatus(); 269 get_fpr(t0, rB(ctx->opcode)); 270 gen_helper_fsqrt(t1, cpu_env, t0); 271 set_fpr(rD(ctx->opcode), t1); 272 gen_compute_fprf_float64(t1); 273 if (unlikely(Rc(ctx->opcode) != 0)) { 274 gen_set_cr1_from_fpscr(ctx); 275 } 276 tcg_temp_free_i64(t0); 277 tcg_temp_free_i64(t1); 278} 279 280static void gen_fsqrts(DisasContext *ctx) 281{ 282 TCGv_i64 t0; 283 TCGv_i64 t1; 284 if (unlikely(!ctx->fpu_enabled)) { 285 gen_exception(ctx, POWERPC_EXCP_FPU); 286 return; 287 } 288 t0 = tcg_temp_new_i64(); 289 t1 = tcg_temp_new_i64(); 290 gen_reset_fpstatus(); 291 get_fpr(t0, rB(ctx->opcode)); 292 gen_helper_fsqrts(t1, cpu_env, t0); 293 set_fpr(rD(ctx->opcode), t1); 294 gen_compute_fprf_float64(t1); 295 if (unlikely(Rc(ctx->opcode) != 0)) { 296 gen_set_cr1_from_fpscr(ctx); 297 } 298 tcg_temp_free_i64(t0); 299 tcg_temp_free_i64(t1); 300} 301 302/*** Floating-Point multiply-and-add ***/ 303/* fmadd - fmadds */ 304GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT); 305/* fmsub - fmsubs */ 306GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT); 307/* fnmadd - fnmadds */ 308GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT); 309/* fnmsub - fnmsubs */ 310GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT); 311 312/*** Floating-Point round & convert ***/ 313/* fctiw */ 314GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT); 315/* fctiwu */ 316GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206); 317/* fctiwz */ 318GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT); 319/* fctiwuz */ 320GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206); 321/* frsp */ 322GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT); 323/* fcfid */ 324GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64); 325/* fcfids */ 326GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206); 327/* fcfidu */ 328GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206); 329/* fcfidus */ 330GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206); 331/* fctid */ 332GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64); 333/* fctidu */ 334GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206); 335/* fctidz */ 336GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64); 337/* fctidu */ 338GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206); 339 340/* frin */ 341GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT); 342/* friz */ 343GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT); 344/* frip */ 345GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT); 346/* frim */ 347GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT); 348 349static void gen_ftdiv(DisasContext *ctx) 350{ 351 TCGv_i64 t0; 352 TCGv_i64 t1; 353 if (unlikely(!ctx->fpu_enabled)) { 354 gen_exception(ctx, POWERPC_EXCP_FPU); 355 return; 356 } 357 t0 = tcg_temp_new_i64(); 358 t1 = tcg_temp_new_i64(); 359 get_fpr(t0, rA(ctx->opcode)); 360 get_fpr(t1, rB(ctx->opcode)); 361 gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1); 362 tcg_temp_free_i64(t0); 363 tcg_temp_free_i64(t1); 364} 365 366static void gen_ftsqrt(DisasContext *ctx) 367{ 368 TCGv_i64 t0; 369 if (unlikely(!ctx->fpu_enabled)) { 370 gen_exception(ctx, POWERPC_EXCP_FPU); 371 return; 372 } 373 t0 = tcg_temp_new_i64(); 374 get_fpr(t0, rB(ctx->opcode)); 375 gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0); 376 tcg_temp_free_i64(t0); 377} 378 379 380 381/*** Floating-Point compare ***/ 382 383/* fcmpo */ 384static void gen_fcmpo(DisasContext *ctx) 385{ 386 TCGv_i32 crf; 387 TCGv_i64 t0; 388 TCGv_i64 t1; 389 if (unlikely(!ctx->fpu_enabled)) { 390 gen_exception(ctx, POWERPC_EXCP_FPU); 391 return; 392 } 393 t0 = tcg_temp_new_i64(); 394 t1 = tcg_temp_new_i64(); 395 gen_reset_fpstatus(); 396 crf = tcg_const_i32(crfD(ctx->opcode)); 397 get_fpr(t0, rA(ctx->opcode)); 398 get_fpr(t1, rB(ctx->opcode)); 399 gen_helper_fcmpo(cpu_env, t0, t1, crf); 400 tcg_temp_free_i32(crf); 401 gen_helper_float_check_status(cpu_env); 402 tcg_temp_free_i64(t0); 403 tcg_temp_free_i64(t1); 404} 405 406/* fcmpu */ 407static void gen_fcmpu(DisasContext *ctx) 408{ 409 TCGv_i32 crf; 410 TCGv_i64 t0; 411 TCGv_i64 t1; 412 if (unlikely(!ctx->fpu_enabled)) { 413 gen_exception(ctx, POWERPC_EXCP_FPU); 414 return; 415 } 416 t0 = tcg_temp_new_i64(); 417 t1 = tcg_temp_new_i64(); 418 gen_reset_fpstatus(); 419 crf = tcg_const_i32(crfD(ctx->opcode)); 420 get_fpr(t0, rA(ctx->opcode)); 421 get_fpr(t1, rB(ctx->opcode)); 422 gen_helper_fcmpu(cpu_env, t0, t1, crf); 423 tcg_temp_free_i32(crf); 424 gen_helper_float_check_status(cpu_env); 425 tcg_temp_free_i64(t0); 426 tcg_temp_free_i64(t1); 427} 428 429/*** Floating-point move ***/ 430/* fabs */ 431/* XXX: beware that fabs never checks for NaNs nor update FPSCR */ 432static void gen_fabs(DisasContext *ctx) 433{ 434 TCGv_i64 t0; 435 TCGv_i64 t1; 436 if (unlikely(!ctx->fpu_enabled)) { 437 gen_exception(ctx, POWERPC_EXCP_FPU); 438 return; 439 } 440 t0 = tcg_temp_new_i64(); 441 t1 = tcg_temp_new_i64(); 442 get_fpr(t0, rB(ctx->opcode)); 443 tcg_gen_andi_i64(t1, t0, ~(1ULL << 63)); 444 set_fpr(rD(ctx->opcode), t1); 445 if (unlikely(Rc(ctx->opcode))) { 446 gen_set_cr1_from_fpscr(ctx); 447 } 448 tcg_temp_free_i64(t0); 449 tcg_temp_free_i64(t1); 450} 451 452/* fmr - fmr. */ 453/* XXX: beware that fmr never checks for NaNs nor update FPSCR */ 454static void gen_fmr(DisasContext *ctx) 455{ 456 TCGv_i64 t0; 457 if (unlikely(!ctx->fpu_enabled)) { 458 gen_exception(ctx, POWERPC_EXCP_FPU); 459 return; 460 } 461 t0 = tcg_temp_new_i64(); 462 get_fpr(t0, rB(ctx->opcode)); 463 set_fpr(rD(ctx->opcode), t0); 464 if (unlikely(Rc(ctx->opcode))) { 465 gen_set_cr1_from_fpscr(ctx); 466 } 467 tcg_temp_free_i64(t0); 468} 469 470/* fnabs */ 471/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */ 472static void gen_fnabs(DisasContext *ctx) 473{ 474 TCGv_i64 t0; 475 TCGv_i64 t1; 476 if (unlikely(!ctx->fpu_enabled)) { 477 gen_exception(ctx, POWERPC_EXCP_FPU); 478 return; 479 } 480 t0 = tcg_temp_new_i64(); 481 t1 = tcg_temp_new_i64(); 482 get_fpr(t0, rB(ctx->opcode)); 483 tcg_gen_ori_i64(t1, t0, 1ULL << 63); 484 set_fpr(rD(ctx->opcode), t1); 485 if (unlikely(Rc(ctx->opcode))) { 486 gen_set_cr1_from_fpscr(ctx); 487 } 488 tcg_temp_free_i64(t0); 489 tcg_temp_free_i64(t1); 490} 491 492/* fneg */ 493/* XXX: beware that fneg never checks for NaNs nor update FPSCR */ 494static void gen_fneg(DisasContext *ctx) 495{ 496 TCGv_i64 t0; 497 TCGv_i64 t1; 498 if (unlikely(!ctx->fpu_enabled)) { 499 gen_exception(ctx, POWERPC_EXCP_FPU); 500 return; 501 } 502 t0 = tcg_temp_new_i64(); 503 t1 = tcg_temp_new_i64(); 504 get_fpr(t0, rB(ctx->opcode)); 505 tcg_gen_xori_i64(t1, t0, 1ULL << 63); 506 set_fpr(rD(ctx->opcode), t1); 507 if (unlikely(Rc(ctx->opcode))) { 508 gen_set_cr1_from_fpscr(ctx); 509 } 510 tcg_temp_free_i64(t0); 511 tcg_temp_free_i64(t1); 512} 513 514/* fcpsgn: PowerPC 2.05 specification */ 515/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */ 516static void gen_fcpsgn(DisasContext *ctx) 517{ 518 TCGv_i64 t0; 519 TCGv_i64 t1; 520 TCGv_i64 t2; 521 if (unlikely(!ctx->fpu_enabled)) { 522 gen_exception(ctx, POWERPC_EXCP_FPU); 523 return; 524 } 525 t0 = tcg_temp_new_i64(); 526 t1 = tcg_temp_new_i64(); 527 t2 = tcg_temp_new_i64(); 528 get_fpr(t0, rA(ctx->opcode)); 529 get_fpr(t1, rB(ctx->opcode)); 530 tcg_gen_deposit_i64(t2, t0, t1, 0, 63); 531 set_fpr(rD(ctx->opcode), t2); 532 if (unlikely(Rc(ctx->opcode))) { 533 gen_set_cr1_from_fpscr(ctx); 534 } 535 tcg_temp_free_i64(t0); 536 tcg_temp_free_i64(t1); 537 tcg_temp_free_i64(t2); 538} 539 540static void gen_fmrgew(DisasContext *ctx) 541{ 542 TCGv_i64 b0; 543 TCGv_i64 t0; 544 TCGv_i64 t1; 545 if (unlikely(!ctx->fpu_enabled)) { 546 gen_exception(ctx, POWERPC_EXCP_FPU); 547 return; 548 } 549 b0 = tcg_temp_new_i64(); 550 t0 = tcg_temp_new_i64(); 551 t1 = tcg_temp_new_i64(); 552 get_fpr(t0, rB(ctx->opcode)); 553 tcg_gen_shri_i64(b0, t0, 32); 554 get_fpr(t0, rA(ctx->opcode)); 555 tcg_gen_deposit_i64(t1, t0, b0, 0, 32); 556 set_fpr(rD(ctx->opcode), t1); 557 tcg_temp_free_i64(b0); 558 tcg_temp_free_i64(t0); 559 tcg_temp_free_i64(t1); 560} 561 562static void gen_fmrgow(DisasContext *ctx) 563{ 564 TCGv_i64 t0; 565 TCGv_i64 t1; 566 TCGv_i64 t2; 567 if (unlikely(!ctx->fpu_enabled)) { 568 gen_exception(ctx, POWERPC_EXCP_FPU); 569 return; 570 } 571 t0 = tcg_temp_new_i64(); 572 t1 = tcg_temp_new_i64(); 573 t2 = tcg_temp_new_i64(); 574 get_fpr(t0, rB(ctx->opcode)); 575 get_fpr(t1, rA(ctx->opcode)); 576 tcg_gen_deposit_i64(t2, t0, t1, 32, 32); 577 set_fpr(rD(ctx->opcode), t2); 578 tcg_temp_free_i64(t0); 579 tcg_temp_free_i64(t1); 580 tcg_temp_free_i64(t2); 581} 582 583/*** Floating-Point status & ctrl register ***/ 584 585/* mcrfs */ 586static void gen_mcrfs(DisasContext *ctx) 587{ 588 TCGv tmp = tcg_temp_new(); 589 TCGv_i32 tmask; 590 TCGv_i64 tnew_fpscr = tcg_temp_new_i64(); 591 int bfa; 592 int nibble; 593 int shift; 594 595 if (unlikely(!ctx->fpu_enabled)) { 596 gen_exception(ctx, POWERPC_EXCP_FPU); 597 return; 598 } 599 bfa = crfS(ctx->opcode); 600 nibble = 7 - bfa; 601 shift = 4 * nibble; 602 tcg_gen_shri_tl(tmp, cpu_fpscr, shift); 603 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); 604 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 605 0xf); 606 tcg_temp_free(tmp); 607 tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr); 608 /* Only the exception bits (including FX) should be cleared if read */ 609 tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, 610 ~((0xF << shift) & FP_EX_CLEAR_BITS)); 611 /* FEX and VX need to be updated, so don't set fpscr directly */ 612 tmask = tcg_const_i32(1 << nibble); 613 gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask); 614 tcg_temp_free_i32(tmask); 615 tcg_temp_free_i64(tnew_fpscr); 616} 617 618/* mffs */ 619static void gen_mffs(DisasContext *ctx) 620{ 621 TCGv_i64 t0; 622 if (unlikely(!ctx->fpu_enabled)) { 623 gen_exception(ctx, POWERPC_EXCP_FPU); 624 return; 625 } 626 t0 = tcg_temp_new_i64(); 627 gen_reset_fpstatus(); 628 tcg_gen_extu_tl_i64(t0, cpu_fpscr); 629 set_fpr(rD(ctx->opcode), t0); 630 if (unlikely(Rc(ctx->opcode))) { 631 gen_set_cr1_from_fpscr(ctx); 632 } 633 tcg_temp_free_i64(t0); 634} 635 636/* mffsl */ 637static void gen_mffsl(DisasContext *ctx) 638{ 639 TCGv_i64 t0; 640 641 if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { 642 return gen_mffs(ctx); 643 } 644 645 if (unlikely(!ctx->fpu_enabled)) { 646 gen_exception(ctx, POWERPC_EXCP_FPU); 647 return; 648 } 649 t0 = tcg_temp_new_i64(); 650 gen_reset_fpstatus(); 651 tcg_gen_extu_tl_i64(t0, cpu_fpscr); 652 /* Mask everything except mode, status, and enables. */ 653 tcg_gen_andi_i64(t0, t0, FP_DRN | FP_STATUS | FP_ENABLES | FP_RN); 654 set_fpr(rD(ctx->opcode), t0); 655 tcg_temp_free_i64(t0); 656} 657 658/* mffsce */ 659static void gen_mffsce(DisasContext *ctx) 660{ 661 TCGv_i64 t0; 662 TCGv_i32 mask; 663 664 if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { 665 return gen_mffs(ctx); 666 } 667 668 if (unlikely(!ctx->fpu_enabled)) { 669 gen_exception(ctx, POWERPC_EXCP_FPU); 670 return; 671 } 672 673 t0 = tcg_temp_new_i64(); 674 675 gen_reset_fpstatus(); 676 tcg_gen_extu_tl_i64(t0, cpu_fpscr); 677 set_fpr(rD(ctx->opcode), t0); 678 679 /* Clear exception enable bits in the FPSCR. */ 680 tcg_gen_andi_i64(t0, t0, ~FP_ENABLES); 681 mask = tcg_const_i32(0x0003); 682 gen_helper_store_fpscr(cpu_env, t0, mask); 683 684 tcg_temp_free_i32(mask); 685 tcg_temp_free_i64(t0); 686} 687 688static TCGv_i64 place_from_fpscr(int rt, uint64_t mask) 689{ 690 TCGv_i64 fpscr = tcg_temp_new_i64(); 691 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 692 693 tcg_gen_extu_tl_i64(fpscr, cpu_fpscr); 694 tcg_gen_andi_i64(fpscr_masked, fpscr, mask); 695 set_fpr(rt, fpscr_masked); 696 697 tcg_temp_free_i64(fpscr_masked); 698 699 return fpscr; 700} 701 702static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask, 703 TCGv_i64 set_mask, uint32_t store_mask) 704{ 705 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 706 TCGv_i32 st_mask = tcg_constant_i32(store_mask); 707 708 tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask); 709 tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask); 710 gen_helper_store_fpscr(cpu_env, fpscr_masked, st_mask); 711 712 tcg_temp_free_i64(fpscr_masked); 713} 714 715static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a) 716{ 717 TCGv_i64 t1, fpscr; 718 719 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 720 REQUIRE_FPU(ctx); 721 722 t1 = tcg_temp_new_i64(); 723 get_fpr(t1, a->rb); 724 tcg_gen_andi_i64(t1, t1, FP_RN); 725 726 gen_reset_fpstatus(); 727 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 728 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 729 730 tcg_temp_free_i64(t1); 731 tcg_temp_free_i64(fpscr); 732 733 return true; 734} 735 736static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a) 737{ 738 TCGv_i64 t1, fpscr; 739 740 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 741 REQUIRE_FPU(ctx); 742 743 t1 = tcg_temp_new_i64(); 744 tcg_gen_movi_i64(t1, a->imm); 745 746 gen_reset_fpstatus(); 747 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 748 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 749 750 tcg_temp_free_i64(t1); 751 tcg_temp_free_i64(fpscr); 752 753 return true; 754} 755 756/* mtfsb0 */ 757static void gen_mtfsb0(DisasContext *ctx) 758{ 759 uint8_t crb; 760 761 if (unlikely(!ctx->fpu_enabled)) { 762 gen_exception(ctx, POWERPC_EXCP_FPU); 763 return; 764 } 765 crb = 31 - crbD(ctx->opcode); 766 gen_reset_fpstatus(); 767 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { 768 TCGv_i32 t0; 769 t0 = tcg_const_i32(crb); 770 gen_helper_fpscr_clrbit(cpu_env, t0); 771 tcg_temp_free_i32(t0); 772 } 773 if (unlikely(Rc(ctx->opcode) != 0)) { 774 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 775 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 776 } 777} 778 779/* mtfsb1 */ 780static void gen_mtfsb1(DisasContext *ctx) 781{ 782 uint8_t crb; 783 784 if (unlikely(!ctx->fpu_enabled)) { 785 gen_exception(ctx, POWERPC_EXCP_FPU); 786 return; 787 } 788 crb = 31 - crbD(ctx->opcode); 789 /* XXX: we pretend we can only do IEEE floating-point computations */ 790 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { 791 TCGv_i32 t0; 792 t0 = tcg_const_i32(crb); 793 gen_helper_fpscr_setbit(cpu_env, t0); 794 tcg_temp_free_i32(t0); 795 } 796 if (unlikely(Rc(ctx->opcode) != 0)) { 797 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 798 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 799 } 800 /* We can raise a deferred exception */ 801 gen_helper_fpscr_check_status(cpu_env); 802} 803 804/* mtfsf */ 805static void gen_mtfsf(DisasContext *ctx) 806{ 807 TCGv_i32 t0; 808 TCGv_i64 t1; 809 int flm, l, w; 810 811 if (unlikely(!ctx->fpu_enabled)) { 812 gen_exception(ctx, POWERPC_EXCP_FPU); 813 return; 814 } 815 flm = FPFLM(ctx->opcode); 816 l = FPL(ctx->opcode); 817 w = FPW(ctx->opcode); 818 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 819 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 820 return; 821 } 822 if (l) { 823 t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff); 824 } else { 825 t0 = tcg_const_i32(flm << (w * 8)); 826 } 827 t1 = tcg_temp_new_i64(); 828 get_fpr(t1, rB(ctx->opcode)); 829 gen_helper_store_fpscr(cpu_env, t1, t0); 830 tcg_temp_free_i32(t0); 831 if (unlikely(Rc(ctx->opcode) != 0)) { 832 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 833 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 834 } 835 /* We can raise a deferred exception */ 836 gen_helper_fpscr_check_status(cpu_env); 837 tcg_temp_free_i64(t1); 838} 839 840/* mtfsfi */ 841static void gen_mtfsfi(DisasContext *ctx) 842{ 843 int bf, sh, w; 844 TCGv_i64 t0; 845 TCGv_i32 t1; 846 847 if (unlikely(!ctx->fpu_enabled)) { 848 gen_exception(ctx, POWERPC_EXCP_FPU); 849 return; 850 } 851 w = FPW(ctx->opcode); 852 bf = FPBF(ctx->opcode); 853 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 854 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 855 return; 856 } 857 sh = (8 * w) + 7 - bf; 858 t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh)); 859 t1 = tcg_const_i32(1 << sh); 860 gen_helper_store_fpscr(cpu_env, t0, t1); 861 tcg_temp_free_i64(t0); 862 tcg_temp_free_i32(t1); 863 if (unlikely(Rc(ctx->opcode) != 0)) { 864 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 865 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 866 } 867 /* We can raise a deferred exception */ 868 gen_helper_fpscr_check_status(cpu_env); 869} 870 871static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr) 872{ 873 TCGv_i32 tmp = tcg_temp_new_i32(); 874 tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 875 gen_helper_todouble(dest, tmp); 876 tcg_temp_free_i32(tmp); 877} 878 879/* lfdepx (external PID lfdx) */ 880static void gen_lfdepx(DisasContext *ctx) 881{ 882 TCGv EA; 883 TCGv_i64 t0; 884 CHK_SV; 885 if (unlikely(!ctx->fpu_enabled)) { 886 gen_exception(ctx, POWERPC_EXCP_FPU); 887 return; 888 } 889 gen_set_access_type(ctx, ACCESS_FLOAT); 890 EA = tcg_temp_new(); 891 t0 = tcg_temp_new_i64(); 892 gen_addr_reg_index(ctx, EA); 893 tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ)); 894 set_fpr(rD(ctx->opcode), t0); 895 tcg_temp_free(EA); 896 tcg_temp_free_i64(t0); 897} 898 899/* lfdp */ 900static void gen_lfdp(DisasContext *ctx) 901{ 902 TCGv EA; 903 TCGv_i64 t0; 904 if (unlikely(!ctx->fpu_enabled)) { 905 gen_exception(ctx, POWERPC_EXCP_FPU); 906 return; 907 } 908 gen_set_access_type(ctx, ACCESS_FLOAT); 909 EA = tcg_temp_new(); 910 gen_addr_imm_index(ctx, EA, 0); 911 t0 = tcg_temp_new_i64(); 912 /* 913 * We only need to swap high and low halves. gen_qemu_ld64_i64 914 * does necessary 64-bit byteswap already. 915 */ 916 if (unlikely(ctx->le_mode)) { 917 gen_qemu_ld64_i64(ctx, t0, EA); 918 set_fpr(rD(ctx->opcode) + 1, t0); 919 tcg_gen_addi_tl(EA, EA, 8); 920 gen_qemu_ld64_i64(ctx, t0, EA); 921 set_fpr(rD(ctx->opcode), t0); 922 } else { 923 gen_qemu_ld64_i64(ctx, t0, EA); 924 set_fpr(rD(ctx->opcode), t0); 925 tcg_gen_addi_tl(EA, EA, 8); 926 gen_qemu_ld64_i64(ctx, t0, EA); 927 set_fpr(rD(ctx->opcode) + 1, t0); 928 } 929 tcg_temp_free(EA); 930 tcg_temp_free_i64(t0); 931} 932 933/* lfdpx */ 934static void gen_lfdpx(DisasContext *ctx) 935{ 936 TCGv EA; 937 TCGv_i64 t0; 938 if (unlikely(!ctx->fpu_enabled)) { 939 gen_exception(ctx, POWERPC_EXCP_FPU); 940 return; 941 } 942 gen_set_access_type(ctx, ACCESS_FLOAT); 943 EA = tcg_temp_new(); 944 gen_addr_reg_index(ctx, EA); 945 t0 = tcg_temp_new_i64(); 946 /* 947 * We only need to swap high and low halves. gen_qemu_ld64_i64 948 * does necessary 64-bit byteswap already. 949 */ 950 if (unlikely(ctx->le_mode)) { 951 gen_qemu_ld64_i64(ctx, t0, EA); 952 set_fpr(rD(ctx->opcode) + 1, t0); 953 tcg_gen_addi_tl(EA, EA, 8); 954 gen_qemu_ld64_i64(ctx, t0, EA); 955 set_fpr(rD(ctx->opcode), t0); 956 } else { 957 gen_qemu_ld64_i64(ctx, t0, EA); 958 set_fpr(rD(ctx->opcode), t0); 959 tcg_gen_addi_tl(EA, EA, 8); 960 gen_qemu_ld64_i64(ctx, t0, EA); 961 set_fpr(rD(ctx->opcode) + 1, t0); 962 } 963 tcg_temp_free(EA); 964 tcg_temp_free_i64(t0); 965} 966 967/* lfiwax */ 968static void gen_lfiwax(DisasContext *ctx) 969{ 970 TCGv EA; 971 TCGv t0; 972 TCGv_i64 t1; 973 if (unlikely(!ctx->fpu_enabled)) { 974 gen_exception(ctx, POWERPC_EXCP_FPU); 975 return; 976 } 977 gen_set_access_type(ctx, ACCESS_FLOAT); 978 EA = tcg_temp_new(); 979 t0 = tcg_temp_new(); 980 t1 = tcg_temp_new_i64(); 981 gen_addr_reg_index(ctx, EA); 982 gen_qemu_ld32s(ctx, t0, EA); 983 tcg_gen_ext_tl_i64(t1, t0); 984 set_fpr(rD(ctx->opcode), t1); 985 tcg_temp_free(EA); 986 tcg_temp_free(t0); 987 tcg_temp_free_i64(t1); 988} 989 990/* lfiwzx */ 991static void gen_lfiwzx(DisasContext *ctx) 992{ 993 TCGv EA; 994 TCGv_i64 t0; 995 if (unlikely(!ctx->fpu_enabled)) { 996 gen_exception(ctx, POWERPC_EXCP_FPU); 997 return; 998 } 999 gen_set_access_type(ctx, ACCESS_FLOAT); 1000 EA = tcg_temp_new(); 1001 t0 = tcg_temp_new_i64(); 1002 gen_addr_reg_index(ctx, EA); 1003 gen_qemu_ld32u_i64(ctx, t0, EA); 1004 set_fpr(rD(ctx->opcode), t0); 1005 tcg_temp_free(EA); 1006 tcg_temp_free_i64(t0); 1007} 1008 1009#define GEN_STXF(name, stop, opc2, opc3, type) \ 1010static void glue(gen_, name##x)(DisasContext *ctx) \ 1011{ \ 1012 TCGv EA; \ 1013 TCGv_i64 t0; \ 1014 if (unlikely(!ctx->fpu_enabled)) { \ 1015 gen_exception(ctx, POWERPC_EXCP_FPU); \ 1016 return; \ 1017 } \ 1018 gen_set_access_type(ctx, ACCESS_FLOAT); \ 1019 EA = tcg_temp_new(); \ 1020 t0 = tcg_temp_new_i64(); \ 1021 gen_addr_reg_index(ctx, EA); \ 1022 get_fpr(t0, rS(ctx->opcode)); \ 1023 gen_qemu_##stop(ctx, t0, EA); \ 1024 tcg_temp_free(EA); \ 1025 tcg_temp_free_i64(t0); \ 1026} 1027 1028static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr) 1029{ 1030 TCGv_i32 tmp = tcg_temp_new_i32(); 1031 gen_helper_tosingle(tmp, src); 1032 tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 1033 tcg_temp_free_i32(tmp); 1034} 1035 1036/* stfdepx (external PID lfdx) */ 1037static void gen_stfdepx(DisasContext *ctx) 1038{ 1039 TCGv EA; 1040 TCGv_i64 t0; 1041 CHK_SV; 1042 if (unlikely(!ctx->fpu_enabled)) { 1043 gen_exception(ctx, POWERPC_EXCP_FPU); 1044 return; 1045 } 1046 gen_set_access_type(ctx, ACCESS_FLOAT); 1047 EA = tcg_temp_new(); 1048 t0 = tcg_temp_new_i64(); 1049 gen_addr_reg_index(ctx, EA); 1050 get_fpr(t0, rD(ctx->opcode)); 1051 tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ)); 1052 tcg_temp_free(EA); 1053 tcg_temp_free_i64(t0); 1054} 1055 1056/* stfdp */ 1057static void gen_stfdp(DisasContext *ctx) 1058{ 1059 TCGv EA; 1060 TCGv_i64 t0; 1061 if (unlikely(!ctx->fpu_enabled)) { 1062 gen_exception(ctx, POWERPC_EXCP_FPU); 1063 return; 1064 } 1065 gen_set_access_type(ctx, ACCESS_FLOAT); 1066 EA = tcg_temp_new(); 1067 t0 = tcg_temp_new_i64(); 1068 gen_addr_imm_index(ctx, EA, 0); 1069 /* 1070 * We only need to swap high and low halves. gen_qemu_st64_i64 1071 * does necessary 64-bit byteswap already. 1072 */ 1073 if (unlikely(ctx->le_mode)) { 1074 get_fpr(t0, rD(ctx->opcode) + 1); 1075 gen_qemu_st64_i64(ctx, t0, EA); 1076 tcg_gen_addi_tl(EA, EA, 8); 1077 get_fpr(t0, rD(ctx->opcode)); 1078 gen_qemu_st64_i64(ctx, t0, EA); 1079 } else { 1080 get_fpr(t0, rD(ctx->opcode)); 1081 gen_qemu_st64_i64(ctx, t0, EA); 1082 tcg_gen_addi_tl(EA, EA, 8); 1083 get_fpr(t0, rD(ctx->opcode) + 1); 1084 gen_qemu_st64_i64(ctx, t0, EA); 1085 } 1086 tcg_temp_free(EA); 1087 tcg_temp_free_i64(t0); 1088} 1089 1090/* stfdpx */ 1091static void gen_stfdpx(DisasContext *ctx) 1092{ 1093 TCGv EA; 1094 TCGv_i64 t0; 1095 if (unlikely(!ctx->fpu_enabled)) { 1096 gen_exception(ctx, POWERPC_EXCP_FPU); 1097 return; 1098 } 1099 gen_set_access_type(ctx, ACCESS_FLOAT); 1100 EA = tcg_temp_new(); 1101 t0 = tcg_temp_new_i64(); 1102 gen_addr_reg_index(ctx, EA); 1103 /* 1104 * We only need to swap high and low halves. gen_qemu_st64_i64 1105 * does necessary 64-bit byteswap already. 1106 */ 1107 if (unlikely(ctx->le_mode)) { 1108 get_fpr(t0, rD(ctx->opcode) + 1); 1109 gen_qemu_st64_i64(ctx, t0, EA); 1110 tcg_gen_addi_tl(EA, EA, 8); 1111 get_fpr(t0, rD(ctx->opcode)); 1112 gen_qemu_st64_i64(ctx, t0, EA); 1113 } else { 1114 get_fpr(t0, rD(ctx->opcode)); 1115 gen_qemu_st64_i64(ctx, t0, EA); 1116 tcg_gen_addi_tl(EA, EA, 8); 1117 get_fpr(t0, rD(ctx->opcode) + 1); 1118 gen_qemu_st64_i64(ctx, t0, EA); 1119 } 1120 tcg_temp_free(EA); 1121 tcg_temp_free_i64(t0); 1122} 1123 1124/* Optional: */ 1125static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) 1126{ 1127 TCGv t0 = tcg_temp_new(); 1128 tcg_gen_trunc_i64_tl(t0, arg1), 1129 gen_qemu_st32(ctx, t0, arg2); 1130 tcg_temp_free(t0); 1131} 1132/* stfiwx */ 1133GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX); 1134 1135/* Floating-point Load/Store Instructions */ 1136static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ, 1137 bool update, bool store, bool single) 1138{ 1139 TCGv ea; 1140 TCGv_i64 t0; 1141 REQUIRE_INSNS_FLAGS(ctx, FLOAT); 1142 REQUIRE_FPU(ctx); 1143 if (update && ra == 0) { 1144 gen_invalid(ctx); 1145 return true; 1146 } 1147 gen_set_access_type(ctx, ACCESS_FLOAT); 1148 t0 = tcg_temp_new_i64(); 1149 ea = do_ea_calc(ctx, ra, displ); 1150 if (store) { 1151 get_fpr(t0, rt); 1152 if (single) { 1153 gen_qemu_st32fs(ctx, t0, ea); 1154 } else { 1155 gen_qemu_st64_i64(ctx, t0, ea); 1156 } 1157 } else { 1158 if (single) { 1159 gen_qemu_ld32fs(ctx, t0, ea); 1160 } else { 1161 gen_qemu_ld64_i64(ctx, t0, ea); 1162 } 1163 set_fpr(rt, t0); 1164 } 1165 if (update) { 1166 tcg_gen_mov_tl(cpu_gpr[ra], ea); 1167 } 1168 tcg_temp_free_i64(t0); 1169 tcg_temp_free(ea); 1170 return true; 1171} 1172 1173static bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store, 1174 bool single) 1175{ 1176 return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, 1177 single); 1178} 1179 1180static bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update, 1181 bool store, bool single) 1182{ 1183 arg_D d; 1184 if (!resolve_PLS_D(ctx, &d, a)) { 1185 return true; 1186 } 1187 return do_lsfp_D(ctx, &d, update, store, single); 1188} 1189 1190static bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update, 1191 bool store, bool single) 1192{ 1193 return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single); 1194} 1195 1196TRANS(LFS, do_lsfp_D, false, false, true) 1197TRANS(LFSU, do_lsfp_D, true, false, true) 1198TRANS(LFSX, do_lsfp_X, false, false, true) 1199TRANS(LFSUX, do_lsfp_X, true, false, true) 1200TRANS(PLFS, do_lsfp_PLS_D, false, false, true) 1201 1202TRANS(LFD, do_lsfp_D, false, false, false) 1203TRANS(LFDU, do_lsfp_D, true, false, false) 1204TRANS(LFDX, do_lsfp_X, false, false, false) 1205TRANS(LFDUX, do_lsfp_X, true, false, false) 1206TRANS(PLFD, do_lsfp_PLS_D, false, false, false) 1207 1208TRANS(STFS, do_lsfp_D, false, true, true) 1209TRANS(STFSU, do_lsfp_D, true, true, true) 1210TRANS(STFSX, do_lsfp_X, false, true, true) 1211TRANS(STFSUX, do_lsfp_X, true, true, true) 1212TRANS(PSTFS, do_lsfp_PLS_D, false, true, true) 1213 1214TRANS(STFD, do_lsfp_D, false, true, false) 1215TRANS(STFDU, do_lsfp_D, true, true, false) 1216TRANS(STFDX, do_lsfp_X, false, true, false) 1217TRANS(STFDUX, do_lsfp_X, true, true, false) 1218TRANS(PSTFD, do_lsfp_PLS_D, false, true, false) 1219 1220#undef _GEN_FLOAT_ACB 1221#undef GEN_FLOAT_ACB 1222#undef _GEN_FLOAT_AB 1223#undef GEN_FLOAT_AB 1224#undef _GEN_FLOAT_AC 1225#undef GEN_FLOAT_AC 1226#undef GEN_FLOAT_B 1227#undef GEN_FLOAT_BS 1228 1229#undef GEN_LDF 1230#undef GEN_LDUF 1231#undef GEN_LDUXF 1232#undef GEN_LDXF 1233#undef GEN_LDFS 1234 1235#undef GEN_STF 1236#undef GEN_STUF 1237#undef GEN_STUXF 1238#undef GEN_STXF 1239#undef GEN_STFS 1240