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