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