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 618static TCGv_i64 place_from_fpscr(int rt, uint64_t mask) 619{ 620 TCGv_i64 fpscr = tcg_temp_new_i64(); 621 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 622 623 tcg_gen_extu_tl_i64(fpscr, cpu_fpscr); 624 tcg_gen_andi_i64(fpscr_masked, fpscr, mask); 625 set_fpr(rt, fpscr_masked); 626 627 tcg_temp_free_i64(fpscr_masked); 628 629 return fpscr; 630} 631 632static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask, 633 TCGv_i64 set_mask, uint32_t store_mask) 634{ 635 TCGv_i64 fpscr_masked = tcg_temp_new_i64(); 636 TCGv_i32 st_mask = tcg_constant_i32(store_mask); 637 638 tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask); 639 tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask); 640 gen_helper_store_fpscr(cpu_env, fpscr_masked, st_mask); 641 642 tcg_temp_free_i64(fpscr_masked); 643} 644 645static bool trans_MFFS(DisasContext *ctx, arg_X_t_rc *a) 646{ 647 TCGv_i64 fpscr; 648 649 REQUIRE_FPU(ctx); 650 651 gen_reset_fpstatus(); 652 fpscr = place_from_fpscr(a->rt, UINT64_MAX); 653 if (a->rc) { 654 gen_set_cr1_from_fpscr(ctx); 655 } 656 657 tcg_temp_free_i64(fpscr); 658 659 return true; 660} 661 662static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a) 663{ 664 TCGv_i64 fpscr; 665 666 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 667 REQUIRE_FPU(ctx); 668 669 gen_reset_fpstatus(); 670 fpscr = place_from_fpscr(a->rt, UINT64_MAX); 671 store_fpscr_masked(fpscr, FP_ENABLES, tcg_constant_i64(0), 0x0003); 672 673 tcg_temp_free_i64(fpscr); 674 675 return true; 676} 677 678static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a) 679{ 680 TCGv_i64 t1, fpscr; 681 682 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 683 REQUIRE_FPU(ctx); 684 685 t1 = tcg_temp_new_i64(); 686 get_fpr(t1, a->rb); 687 tcg_gen_andi_i64(t1, t1, FP_RN); 688 689 gen_reset_fpstatus(); 690 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 691 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 692 693 tcg_temp_free_i64(t1); 694 tcg_temp_free_i64(fpscr); 695 696 return true; 697} 698 699static bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a) 700{ 701 TCGv_i64 t1, fpscr; 702 703 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 704 REQUIRE_FPU(ctx); 705 706 t1 = tcg_temp_new_i64(); 707 get_fpr(t1, a->rb); 708 tcg_gen_andi_i64(t1, t1, FP_DRN); 709 710 gen_reset_fpstatus(); 711 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 712 store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100); 713 714 tcg_temp_free_i64(t1); 715 tcg_temp_free_i64(fpscr); 716 717 return true; 718} 719 720static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a) 721{ 722 TCGv_i64 t1, fpscr; 723 724 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 725 REQUIRE_FPU(ctx); 726 727 t1 = tcg_temp_new_i64(); 728 tcg_gen_movi_i64(t1, a->imm); 729 730 gen_reset_fpstatus(); 731 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 732 store_fpscr_masked(fpscr, FP_RN, t1, 0x0001); 733 734 tcg_temp_free_i64(t1); 735 tcg_temp_free_i64(fpscr); 736 737 return true; 738} 739 740static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 *a) 741{ 742 TCGv_i64 t1, fpscr; 743 744 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 745 REQUIRE_FPU(ctx); 746 747 t1 = tcg_temp_new_i64(); 748 tcg_gen_movi_i64(t1, (uint64_t)a->imm << FPSCR_DRN0); 749 750 gen_reset_fpstatus(); 751 fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN); 752 store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100); 753 754 tcg_temp_free_i64(t1); 755 tcg_temp_free_i64(fpscr); 756 757 return true; 758} 759 760static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a) 761{ 762 TCGv_i64 fpscr; 763 764 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 765 REQUIRE_FPU(ctx); 766 767 gen_reset_fpstatus(); 768 fpscr = place_from_fpscr(a->rt, 769 FP_DRN | FP_STATUS | FP_ENABLES | FP_NI | FP_RN); 770 771 tcg_temp_free_i64(fpscr); 772 773 return true; 774} 775 776/* mtfsb0 */ 777static void gen_mtfsb0(DisasContext *ctx) 778{ 779 uint8_t crb; 780 781 if (unlikely(!ctx->fpu_enabled)) { 782 gen_exception(ctx, POWERPC_EXCP_FPU); 783 return; 784 } 785 crb = 31 - crbD(ctx->opcode); 786 gen_reset_fpstatus(); 787 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { 788 TCGv_i32 t0; 789 t0 = tcg_const_i32(crb); 790 gen_helper_fpscr_clrbit(cpu_env, t0); 791 tcg_temp_free_i32(t0); 792 } 793 if (unlikely(Rc(ctx->opcode) != 0)) { 794 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 795 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 796 } 797} 798 799/* mtfsb1 */ 800static void gen_mtfsb1(DisasContext *ctx) 801{ 802 uint8_t crb; 803 804 if (unlikely(!ctx->fpu_enabled)) { 805 gen_exception(ctx, POWERPC_EXCP_FPU); 806 return; 807 } 808 crb = 31 - crbD(ctx->opcode); 809 /* XXX: we pretend we can only do IEEE floating-point computations */ 810 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { 811 TCGv_i32 t0; 812 t0 = tcg_const_i32(crb); 813 gen_helper_fpscr_setbit(cpu_env, t0); 814 tcg_temp_free_i32(t0); 815 } 816 if (unlikely(Rc(ctx->opcode) != 0)) { 817 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 818 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 819 } 820 /* We can raise a deferred exception */ 821 gen_helper_fpscr_check_status(cpu_env); 822} 823 824/* mtfsf */ 825static void gen_mtfsf(DisasContext *ctx) 826{ 827 TCGv_i32 t0; 828 TCGv_i64 t1; 829 int flm, l, w; 830 831 if (unlikely(!ctx->fpu_enabled)) { 832 gen_exception(ctx, POWERPC_EXCP_FPU); 833 return; 834 } 835 flm = FPFLM(ctx->opcode); 836 l = FPL(ctx->opcode); 837 w = FPW(ctx->opcode); 838 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 839 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 840 return; 841 } 842 if (l) { 843 t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff); 844 } else { 845 t0 = tcg_const_i32(flm << (w * 8)); 846 } 847 t1 = tcg_temp_new_i64(); 848 get_fpr(t1, rB(ctx->opcode)); 849 gen_helper_store_fpscr(cpu_env, t1, t0); 850 tcg_temp_free_i32(t0); 851 if (unlikely(Rc(ctx->opcode) != 0)) { 852 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 853 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 854 } 855 /* We can raise a deferred exception */ 856 gen_helper_fpscr_check_status(cpu_env); 857 tcg_temp_free_i64(t1); 858} 859 860/* mtfsfi */ 861static void gen_mtfsfi(DisasContext *ctx) 862{ 863 int bf, sh, w; 864 TCGv_i64 t0; 865 TCGv_i32 t1; 866 867 if (unlikely(!ctx->fpu_enabled)) { 868 gen_exception(ctx, POWERPC_EXCP_FPU); 869 return; 870 } 871 w = FPW(ctx->opcode); 872 bf = FPBF(ctx->opcode); 873 if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) { 874 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); 875 return; 876 } 877 sh = (8 * w) + 7 - bf; 878 t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh)); 879 t1 = tcg_const_i32(1 << sh); 880 gen_helper_store_fpscr(cpu_env, t0, t1); 881 tcg_temp_free_i64(t0); 882 tcg_temp_free_i32(t1); 883 if (unlikely(Rc(ctx->opcode) != 0)) { 884 tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); 885 tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); 886 } 887 /* We can raise a deferred exception */ 888 gen_helper_fpscr_check_status(cpu_env); 889} 890 891static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr) 892{ 893 TCGv_i32 tmp = tcg_temp_new_i32(); 894 tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 895 gen_helper_todouble(dest, tmp); 896 tcg_temp_free_i32(tmp); 897} 898 899/* lfdepx (external PID lfdx) */ 900static void gen_lfdepx(DisasContext *ctx) 901{ 902 TCGv EA; 903 TCGv_i64 t0; 904 CHK_SV; 905 if (unlikely(!ctx->fpu_enabled)) { 906 gen_exception(ctx, POWERPC_EXCP_FPU); 907 return; 908 } 909 gen_set_access_type(ctx, ACCESS_FLOAT); 910 EA = tcg_temp_new(); 911 t0 = tcg_temp_new_i64(); 912 gen_addr_reg_index(ctx, EA); 913 tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ)); 914 set_fpr(rD(ctx->opcode), t0); 915 tcg_temp_free(EA); 916 tcg_temp_free_i64(t0); 917} 918 919/* lfdp */ 920static void gen_lfdp(DisasContext *ctx) 921{ 922 TCGv EA; 923 TCGv_i64 t0; 924 if (unlikely(!ctx->fpu_enabled)) { 925 gen_exception(ctx, POWERPC_EXCP_FPU); 926 return; 927 } 928 gen_set_access_type(ctx, ACCESS_FLOAT); 929 EA = tcg_temp_new(); 930 gen_addr_imm_index(ctx, EA, 0); 931 t0 = tcg_temp_new_i64(); 932 /* 933 * We only need to swap high and low halves. gen_qemu_ld64_i64 934 * does necessary 64-bit byteswap already. 935 */ 936 if (unlikely(ctx->le_mode)) { 937 gen_qemu_ld64_i64(ctx, t0, EA); 938 set_fpr(rD(ctx->opcode) + 1, t0); 939 tcg_gen_addi_tl(EA, EA, 8); 940 gen_qemu_ld64_i64(ctx, t0, EA); 941 set_fpr(rD(ctx->opcode), t0); 942 } else { 943 gen_qemu_ld64_i64(ctx, t0, EA); 944 set_fpr(rD(ctx->opcode), t0); 945 tcg_gen_addi_tl(EA, EA, 8); 946 gen_qemu_ld64_i64(ctx, t0, EA); 947 set_fpr(rD(ctx->opcode) + 1, t0); 948 } 949 tcg_temp_free(EA); 950 tcg_temp_free_i64(t0); 951} 952 953/* lfdpx */ 954static void gen_lfdpx(DisasContext *ctx) 955{ 956 TCGv EA; 957 TCGv_i64 t0; 958 if (unlikely(!ctx->fpu_enabled)) { 959 gen_exception(ctx, POWERPC_EXCP_FPU); 960 return; 961 } 962 gen_set_access_type(ctx, ACCESS_FLOAT); 963 EA = tcg_temp_new(); 964 gen_addr_reg_index(ctx, EA); 965 t0 = tcg_temp_new_i64(); 966 /* 967 * We only need to swap high and low halves. gen_qemu_ld64_i64 968 * does necessary 64-bit byteswap already. 969 */ 970 if (unlikely(ctx->le_mode)) { 971 gen_qemu_ld64_i64(ctx, t0, EA); 972 set_fpr(rD(ctx->opcode) + 1, t0); 973 tcg_gen_addi_tl(EA, EA, 8); 974 gen_qemu_ld64_i64(ctx, t0, EA); 975 set_fpr(rD(ctx->opcode), t0); 976 } else { 977 gen_qemu_ld64_i64(ctx, t0, EA); 978 set_fpr(rD(ctx->opcode), t0); 979 tcg_gen_addi_tl(EA, EA, 8); 980 gen_qemu_ld64_i64(ctx, t0, EA); 981 set_fpr(rD(ctx->opcode) + 1, t0); 982 } 983 tcg_temp_free(EA); 984 tcg_temp_free_i64(t0); 985} 986 987/* lfiwax */ 988static void gen_lfiwax(DisasContext *ctx) 989{ 990 TCGv EA; 991 TCGv t0; 992 TCGv_i64 t1; 993 if (unlikely(!ctx->fpu_enabled)) { 994 gen_exception(ctx, POWERPC_EXCP_FPU); 995 return; 996 } 997 gen_set_access_type(ctx, ACCESS_FLOAT); 998 EA = tcg_temp_new(); 999 t0 = tcg_temp_new(); 1000 t1 = tcg_temp_new_i64(); 1001 gen_addr_reg_index(ctx, EA); 1002 gen_qemu_ld32s(ctx, t0, EA); 1003 tcg_gen_ext_tl_i64(t1, t0); 1004 set_fpr(rD(ctx->opcode), t1); 1005 tcg_temp_free(EA); 1006 tcg_temp_free(t0); 1007 tcg_temp_free_i64(t1); 1008} 1009 1010/* lfiwzx */ 1011static void gen_lfiwzx(DisasContext *ctx) 1012{ 1013 TCGv EA; 1014 TCGv_i64 t0; 1015 if (unlikely(!ctx->fpu_enabled)) { 1016 gen_exception(ctx, POWERPC_EXCP_FPU); 1017 return; 1018 } 1019 gen_set_access_type(ctx, ACCESS_FLOAT); 1020 EA = tcg_temp_new(); 1021 t0 = tcg_temp_new_i64(); 1022 gen_addr_reg_index(ctx, EA); 1023 gen_qemu_ld32u_i64(ctx, t0, EA); 1024 set_fpr(rD(ctx->opcode), t0); 1025 tcg_temp_free(EA); 1026 tcg_temp_free_i64(t0); 1027} 1028 1029#define GEN_STXF(name, stop, opc2, opc3, type) \ 1030static void glue(gen_, name##x)(DisasContext *ctx) \ 1031{ \ 1032 TCGv EA; \ 1033 TCGv_i64 t0; \ 1034 if (unlikely(!ctx->fpu_enabled)) { \ 1035 gen_exception(ctx, POWERPC_EXCP_FPU); \ 1036 return; \ 1037 } \ 1038 gen_set_access_type(ctx, ACCESS_FLOAT); \ 1039 EA = tcg_temp_new(); \ 1040 t0 = tcg_temp_new_i64(); \ 1041 gen_addr_reg_index(ctx, EA); \ 1042 get_fpr(t0, rS(ctx->opcode)); \ 1043 gen_qemu_##stop(ctx, t0, EA); \ 1044 tcg_temp_free(EA); \ 1045 tcg_temp_free_i64(t0); \ 1046} 1047 1048static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr) 1049{ 1050 TCGv_i32 tmp = tcg_temp_new_i32(); 1051 gen_helper_tosingle(tmp, src); 1052 tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); 1053 tcg_temp_free_i32(tmp); 1054} 1055 1056/* stfdepx (external PID lfdx) */ 1057static void gen_stfdepx(DisasContext *ctx) 1058{ 1059 TCGv EA; 1060 TCGv_i64 t0; 1061 CHK_SV; 1062 if (unlikely(!ctx->fpu_enabled)) { 1063 gen_exception(ctx, POWERPC_EXCP_FPU); 1064 return; 1065 } 1066 gen_set_access_type(ctx, ACCESS_FLOAT); 1067 EA = tcg_temp_new(); 1068 t0 = tcg_temp_new_i64(); 1069 gen_addr_reg_index(ctx, EA); 1070 get_fpr(t0, rD(ctx->opcode)); 1071 tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ)); 1072 tcg_temp_free(EA); 1073 tcg_temp_free_i64(t0); 1074} 1075 1076/* stfdp */ 1077static void gen_stfdp(DisasContext *ctx) 1078{ 1079 TCGv EA; 1080 TCGv_i64 t0; 1081 if (unlikely(!ctx->fpu_enabled)) { 1082 gen_exception(ctx, POWERPC_EXCP_FPU); 1083 return; 1084 } 1085 gen_set_access_type(ctx, ACCESS_FLOAT); 1086 EA = tcg_temp_new(); 1087 t0 = tcg_temp_new_i64(); 1088 gen_addr_imm_index(ctx, EA, 0); 1089 /* 1090 * We only need to swap high and low halves. gen_qemu_st64_i64 1091 * does necessary 64-bit byteswap already. 1092 */ 1093 if (unlikely(ctx->le_mode)) { 1094 get_fpr(t0, rD(ctx->opcode) + 1); 1095 gen_qemu_st64_i64(ctx, t0, EA); 1096 tcg_gen_addi_tl(EA, EA, 8); 1097 get_fpr(t0, rD(ctx->opcode)); 1098 gen_qemu_st64_i64(ctx, t0, EA); 1099 } else { 1100 get_fpr(t0, rD(ctx->opcode)); 1101 gen_qemu_st64_i64(ctx, t0, EA); 1102 tcg_gen_addi_tl(EA, EA, 8); 1103 get_fpr(t0, rD(ctx->opcode) + 1); 1104 gen_qemu_st64_i64(ctx, t0, EA); 1105 } 1106 tcg_temp_free(EA); 1107 tcg_temp_free_i64(t0); 1108} 1109 1110/* stfdpx */ 1111static void gen_stfdpx(DisasContext *ctx) 1112{ 1113 TCGv EA; 1114 TCGv_i64 t0; 1115 if (unlikely(!ctx->fpu_enabled)) { 1116 gen_exception(ctx, POWERPC_EXCP_FPU); 1117 return; 1118 } 1119 gen_set_access_type(ctx, ACCESS_FLOAT); 1120 EA = tcg_temp_new(); 1121 t0 = tcg_temp_new_i64(); 1122 gen_addr_reg_index(ctx, EA); 1123 /* 1124 * We only need to swap high and low halves. gen_qemu_st64_i64 1125 * does necessary 64-bit byteswap already. 1126 */ 1127 if (unlikely(ctx->le_mode)) { 1128 get_fpr(t0, rD(ctx->opcode) + 1); 1129 gen_qemu_st64_i64(ctx, t0, EA); 1130 tcg_gen_addi_tl(EA, EA, 8); 1131 get_fpr(t0, rD(ctx->opcode)); 1132 gen_qemu_st64_i64(ctx, t0, EA); 1133 } else { 1134 get_fpr(t0, rD(ctx->opcode)); 1135 gen_qemu_st64_i64(ctx, t0, EA); 1136 tcg_gen_addi_tl(EA, EA, 8); 1137 get_fpr(t0, rD(ctx->opcode) + 1); 1138 gen_qemu_st64_i64(ctx, t0, EA); 1139 } 1140 tcg_temp_free(EA); 1141 tcg_temp_free_i64(t0); 1142} 1143 1144/* Optional: */ 1145static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2) 1146{ 1147 TCGv t0 = tcg_temp_new(); 1148 tcg_gen_trunc_i64_tl(t0, arg1), 1149 gen_qemu_st32(ctx, t0, arg2); 1150 tcg_temp_free(t0); 1151} 1152/* stfiwx */ 1153GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX); 1154 1155/* Floating-point Load/Store Instructions */ 1156static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ, 1157 bool update, bool store, bool single) 1158{ 1159 TCGv ea; 1160 TCGv_i64 t0; 1161 REQUIRE_INSNS_FLAGS(ctx, FLOAT); 1162 REQUIRE_FPU(ctx); 1163 if (update && ra == 0) { 1164 gen_invalid(ctx); 1165 return true; 1166 } 1167 gen_set_access_type(ctx, ACCESS_FLOAT); 1168 t0 = tcg_temp_new_i64(); 1169 ea = do_ea_calc(ctx, ra, displ); 1170 if (store) { 1171 get_fpr(t0, rt); 1172 if (single) { 1173 gen_qemu_st32fs(ctx, t0, ea); 1174 } else { 1175 gen_qemu_st64_i64(ctx, t0, ea); 1176 } 1177 } else { 1178 if (single) { 1179 gen_qemu_ld32fs(ctx, t0, ea); 1180 } else { 1181 gen_qemu_ld64_i64(ctx, t0, ea); 1182 } 1183 set_fpr(rt, t0); 1184 } 1185 if (update) { 1186 tcg_gen_mov_tl(cpu_gpr[ra], ea); 1187 } 1188 tcg_temp_free_i64(t0); 1189 tcg_temp_free(ea); 1190 return true; 1191} 1192 1193static bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store, 1194 bool single) 1195{ 1196 return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, 1197 single); 1198} 1199 1200static bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update, 1201 bool store, bool single) 1202{ 1203 arg_D d; 1204 if (!resolve_PLS_D(ctx, &d, a)) { 1205 return true; 1206 } 1207 return do_lsfp_D(ctx, &d, update, store, single); 1208} 1209 1210static bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update, 1211 bool store, bool single) 1212{ 1213 return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single); 1214} 1215 1216TRANS(LFS, do_lsfp_D, false, false, true) 1217TRANS(LFSU, do_lsfp_D, true, false, true) 1218TRANS(LFSX, do_lsfp_X, false, false, true) 1219TRANS(LFSUX, do_lsfp_X, true, false, true) 1220TRANS(PLFS, do_lsfp_PLS_D, false, false, true) 1221 1222TRANS(LFD, do_lsfp_D, false, false, false) 1223TRANS(LFDU, do_lsfp_D, true, false, false) 1224TRANS(LFDX, do_lsfp_X, false, false, false) 1225TRANS(LFDUX, do_lsfp_X, true, false, false) 1226TRANS(PLFD, do_lsfp_PLS_D, false, false, false) 1227 1228TRANS(STFS, do_lsfp_D, false, true, true) 1229TRANS(STFSU, do_lsfp_D, true, true, true) 1230TRANS(STFSX, do_lsfp_X, false, true, true) 1231TRANS(STFSUX, do_lsfp_X, true, true, true) 1232TRANS(PSTFS, do_lsfp_PLS_D, false, true, true) 1233 1234TRANS(STFD, do_lsfp_D, false, true, false) 1235TRANS(STFDU, do_lsfp_D, true, true, false) 1236TRANS(STFDX, do_lsfp_X, false, true, false) 1237TRANS(STFDUX, do_lsfp_X, true, true, false) 1238TRANS(PSTFD, do_lsfp_PLS_D, false, true, false) 1239 1240#undef _GEN_FLOAT_ACB 1241#undef GEN_FLOAT_ACB 1242#undef _GEN_FLOAT_AB 1243#undef GEN_FLOAT_AB 1244#undef _GEN_FLOAT_AC 1245#undef GEN_FLOAT_AC 1246#undef GEN_FLOAT_B 1247#undef GEN_FLOAT_BS 1248 1249#undef GEN_LDF 1250#undef GEN_LDUF 1251#undef GEN_LDUXF 1252#undef GEN_LDXF 1253#undef GEN_LDFS 1254 1255#undef GEN_STF 1256#undef GEN_STUF 1257#undef GEN_STUXF 1258#undef GEN_STXF 1259#undef GEN_STFS 1260