qemu/target/ppc/translate/fp-impl.inc.c
<<
>>
Prefs
   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    if (unlikely(!ctx->fpu_enabled)) {                                        \
  38        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
  39        return;                                                               \
  40    }                                                                         \
  41    gen_reset_fpstatus();                                                     \
  42    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
  43                     cpu_fpr[rA(ctx->opcode)],                                \
  44                     cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);     \
  45    if (isfloat) {                                                            \
  46        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
  47                        cpu_fpr[rD(ctx->opcode)]);                            \
  48    }                                                                         \
  49    if (set_fprf) {                                                           \
  50        gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);                   \
  51    }                                                                         \
  52    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
  53        gen_set_cr1_from_fpscr(ctx);                                          \
  54    }                                                                         \
  55}
  56
  57#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
  58_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
  59_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
  60
  61#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
  62static void gen_f##name(DisasContext *ctx)                                    \
  63{                                                                             \
  64    if (unlikely(!ctx->fpu_enabled)) {                                        \
  65        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
  66        return;                                                               \
  67    }                                                                         \
  68    gen_reset_fpstatus();                                                     \
  69    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
  70                     cpu_fpr[rA(ctx->opcode)],                                \
  71                     cpu_fpr[rB(ctx->opcode)]);                               \
  72    if (isfloat) {                                                            \
  73        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
  74                        cpu_fpr[rD(ctx->opcode)]);                            \
  75    }                                                                         \
  76    if (set_fprf) {                                                           \
  77        gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);                   \
  78    }                                                                         \
  79    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
  80        gen_set_cr1_from_fpscr(ctx);                                          \
  81    }                                                                         \
  82}
  83#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
  84_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
  85_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
  86
  87#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
  88static void gen_f##name(DisasContext *ctx)                                    \
  89{                                                                             \
  90    if (unlikely(!ctx->fpu_enabled)) {                                        \
  91        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
  92        return;                                                               \
  93    }                                                                         \
  94    gen_reset_fpstatus();                                                     \
  95    gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_env,                       \
  96                     cpu_fpr[rA(ctx->opcode)],                                \
  97                     cpu_fpr[rC(ctx->opcode)]);                               \
  98    if (isfloat) {                                                            \
  99        gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,                    \
 100                        cpu_fpr[rD(ctx->opcode)]);                            \
 101    }                                                                         \
 102    if (set_fprf) {                                                           \
 103        gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);                   \
 104    }                                                                         \
 105    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
 106        gen_set_cr1_from_fpscr(ctx);                                          \
 107    }                                                                         \
 108}
 109#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
 110_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
 111_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
 112
 113#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
 114static void gen_f##name(DisasContext *ctx)                                    \
 115{                                                                             \
 116    if (unlikely(!ctx->fpu_enabled)) {                                        \
 117        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 118        return;                                                               \
 119    }                                                                         \
 120    gen_reset_fpstatus();                                                     \
 121    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
 122                       cpu_fpr[rB(ctx->opcode)]);                             \
 123    if (set_fprf) {                                                           \
 124        gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);                   \
 125    }                                                                         \
 126    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
 127        gen_set_cr1_from_fpscr(ctx);                                          \
 128    }                                                                         \
 129}
 130
 131#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
 132static void gen_f##name(DisasContext *ctx)                                    \
 133{                                                                             \
 134    if (unlikely(!ctx->fpu_enabled)) {                                        \
 135        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 136        return;                                                               \
 137    }                                                                         \
 138    gen_reset_fpstatus();                                                     \
 139    gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_env,                     \
 140                       cpu_fpr[rB(ctx->opcode)]);                             \
 141    if (set_fprf) {                                                           \
 142        gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);                   \
 143    }                                                                         \
 144    if (unlikely(Rc(ctx->opcode) != 0)) {                                     \
 145        gen_set_cr1_from_fpscr(ctx);                                          \
 146    }                                                                         \
 147}
 148
 149/* fadd - fadds */
 150GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
 151/* fdiv - fdivs */
 152GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
 153/* fmul - fmuls */
 154GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
 155
 156/* fre */
 157GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
 158
 159/* fres */
 160GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
 161
 162/* frsqrte */
 163GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
 164
 165/* frsqrtes */
 166static void gen_frsqrtes(DisasContext *ctx)
 167{
 168    if (unlikely(!ctx->fpu_enabled)) {
 169        gen_exception(ctx, POWERPC_EXCP_FPU);
 170        return;
 171    }
 172    gen_reset_fpstatus();
 173    gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_env,
 174                       cpu_fpr[rB(ctx->opcode)]);
 175    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
 176                    cpu_fpr[rD(ctx->opcode)]);
 177    gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
 178    if (unlikely(Rc(ctx->opcode) != 0)) {
 179        gen_set_cr1_from_fpscr(ctx);
 180    }
 181}
 182
 183/* fsel */
 184_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
 185/* fsub - fsubs */
 186GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
 187/* Optional: */
 188
 189/* fsqrt */
 190static void gen_fsqrt(DisasContext *ctx)
 191{
 192    if (unlikely(!ctx->fpu_enabled)) {
 193        gen_exception(ctx, POWERPC_EXCP_FPU);
 194        return;
 195    }
 196    gen_reset_fpstatus();
 197    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
 198                     cpu_fpr[rB(ctx->opcode)]);
 199    gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
 200    if (unlikely(Rc(ctx->opcode) != 0)) {
 201        gen_set_cr1_from_fpscr(ctx);
 202    }
 203}
 204
 205static void gen_fsqrts(DisasContext *ctx)
 206{
 207    if (unlikely(!ctx->fpu_enabled)) {
 208        gen_exception(ctx, POWERPC_EXCP_FPU);
 209        return;
 210    }
 211    gen_reset_fpstatus();
 212    gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_env,
 213                     cpu_fpr[rB(ctx->opcode)]);
 214    gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_env,
 215                    cpu_fpr[rD(ctx->opcode)]);
 216    gen_compute_fprf_float64(cpu_fpr[rD(ctx->opcode)]);
 217    if (unlikely(Rc(ctx->opcode) != 0)) {
 218        gen_set_cr1_from_fpscr(ctx);
 219    }
 220}
 221
 222/***                     Floating-Point multiply-and-add                   ***/
 223/* fmadd - fmadds */
 224GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
 225/* fmsub - fmsubs */
 226GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
 227/* fnmadd - fnmadds */
 228GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
 229/* fnmsub - fnmsubs */
 230GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
 231
 232/***                     Floating-Point round & convert                    ***/
 233/* fctiw */
 234GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
 235/* fctiwu */
 236GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_FP_CVT_ISA206);
 237/* fctiwz */
 238GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
 239/* fctiwuz */
 240GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_FP_CVT_ISA206);
 241/* frsp */
 242GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
 243/* fcfid */
 244GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC2_FP_CVT_S64);
 245/* fcfids */
 246GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_FP_CVT_ISA206);
 247/* fcfidu */
 248GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
 249/* fcfidus */
 250GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_FP_CVT_ISA206);
 251/* fctid */
 252GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC2_FP_CVT_S64);
 253/* fctidu */
 254GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_FP_CVT_ISA206);
 255/* fctidz */
 256GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC2_FP_CVT_S64);
 257/* fctidu */
 258GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_FP_CVT_ISA206);
 259
 260/* frin */
 261GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
 262/* friz */
 263GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
 264/* frip */
 265GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
 266/* frim */
 267GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
 268
 269static void gen_ftdiv(DisasContext *ctx)
 270{
 271    if (unlikely(!ctx->fpu_enabled)) {
 272        gen_exception(ctx, POWERPC_EXCP_FPU);
 273        return;
 274    }
 275    gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
 276                     cpu_fpr[rB(ctx->opcode)]);
 277}
 278
 279static void gen_ftsqrt(DisasContext *ctx)
 280{
 281    if (unlikely(!ctx->fpu_enabled)) {
 282        gen_exception(ctx, POWERPC_EXCP_FPU);
 283        return;
 284    }
 285    gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
 286}
 287
 288
 289
 290/***                         Floating-Point compare                        ***/
 291
 292/* fcmpo */
 293static void gen_fcmpo(DisasContext *ctx)
 294{
 295    TCGv_i32 crf;
 296    if (unlikely(!ctx->fpu_enabled)) {
 297        gen_exception(ctx, POWERPC_EXCP_FPU);
 298        return;
 299    }
 300    gen_reset_fpstatus();
 301    crf = tcg_const_i32(crfD(ctx->opcode));
 302    gen_helper_fcmpo(cpu_env, cpu_fpr[rA(ctx->opcode)],
 303                     cpu_fpr[rB(ctx->opcode)], crf);
 304    tcg_temp_free_i32(crf);
 305    gen_helper_float_check_status(cpu_env);
 306}
 307
 308/* fcmpu */
 309static void gen_fcmpu(DisasContext *ctx)
 310{
 311    TCGv_i32 crf;
 312    if (unlikely(!ctx->fpu_enabled)) {
 313        gen_exception(ctx, POWERPC_EXCP_FPU);
 314        return;
 315    }
 316    gen_reset_fpstatus();
 317    crf = tcg_const_i32(crfD(ctx->opcode));
 318    gen_helper_fcmpu(cpu_env, cpu_fpr[rA(ctx->opcode)],
 319                     cpu_fpr[rB(ctx->opcode)], crf);
 320    tcg_temp_free_i32(crf);
 321    gen_helper_float_check_status(cpu_env);
 322}
 323
 324/***                         Floating-point move                           ***/
 325/* fabs */
 326/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
 327static void gen_fabs(DisasContext *ctx)
 328{
 329    if (unlikely(!ctx->fpu_enabled)) {
 330        gen_exception(ctx, POWERPC_EXCP_FPU);
 331        return;
 332    }
 333    tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
 334                     ~(1ULL << 63));
 335    if (unlikely(Rc(ctx->opcode))) {
 336        gen_set_cr1_from_fpscr(ctx);
 337    }
 338}
 339
 340/* fmr  - fmr. */
 341/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
 342static void gen_fmr(DisasContext *ctx)
 343{
 344    if (unlikely(!ctx->fpu_enabled)) {
 345        gen_exception(ctx, POWERPC_EXCP_FPU);
 346        return;
 347    }
 348    tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
 349    if (unlikely(Rc(ctx->opcode))) {
 350        gen_set_cr1_from_fpscr(ctx);
 351    }
 352}
 353
 354/* fnabs */
 355/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
 356static void gen_fnabs(DisasContext *ctx)
 357{
 358    if (unlikely(!ctx->fpu_enabled)) {
 359        gen_exception(ctx, POWERPC_EXCP_FPU);
 360        return;
 361    }
 362    tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
 363                    1ULL << 63);
 364    if (unlikely(Rc(ctx->opcode))) {
 365        gen_set_cr1_from_fpscr(ctx);
 366    }
 367}
 368
 369/* fneg */
 370/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
 371static void gen_fneg(DisasContext *ctx)
 372{
 373    if (unlikely(!ctx->fpu_enabled)) {
 374        gen_exception(ctx, POWERPC_EXCP_FPU);
 375        return;
 376    }
 377    tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
 378                     1ULL << 63);
 379    if (unlikely(Rc(ctx->opcode))) {
 380        gen_set_cr1_from_fpscr(ctx);
 381    }
 382}
 383
 384/* fcpsgn: PowerPC 2.05 specification */
 385/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
 386static void gen_fcpsgn(DisasContext *ctx)
 387{
 388    if (unlikely(!ctx->fpu_enabled)) {
 389        gen_exception(ctx, POWERPC_EXCP_FPU);
 390        return;
 391    }
 392    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
 393                        cpu_fpr[rB(ctx->opcode)], 0, 63);
 394    if (unlikely(Rc(ctx->opcode))) {
 395        gen_set_cr1_from_fpscr(ctx);
 396    }
 397}
 398
 399static void gen_fmrgew(DisasContext *ctx)
 400{
 401    TCGv_i64 b0;
 402    if (unlikely(!ctx->fpu_enabled)) {
 403        gen_exception(ctx, POWERPC_EXCP_FPU);
 404        return;
 405    }
 406    b0 = tcg_temp_new_i64();
 407    tcg_gen_shri_i64(b0, cpu_fpr[rB(ctx->opcode)], 32);
 408    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
 409                        b0, 0, 32);
 410    tcg_temp_free_i64(b0);
 411}
 412
 413static void gen_fmrgow(DisasContext *ctx)
 414{
 415    if (unlikely(!ctx->fpu_enabled)) {
 416        gen_exception(ctx, POWERPC_EXCP_FPU);
 417        return;
 418    }
 419    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)],
 420                        cpu_fpr[rB(ctx->opcode)],
 421                        cpu_fpr[rA(ctx->opcode)],
 422                        32, 32);
 423}
 424
 425/***                  Floating-Point status & ctrl register                ***/
 426
 427/* mcrfs */
 428static void gen_mcrfs(DisasContext *ctx)
 429{
 430    TCGv tmp = tcg_temp_new();
 431    TCGv_i32 tmask;
 432    TCGv_i64 tnew_fpscr = tcg_temp_new_i64();
 433    int bfa;
 434    int nibble;
 435    int shift;
 436
 437    if (unlikely(!ctx->fpu_enabled)) {
 438        gen_exception(ctx, POWERPC_EXCP_FPU);
 439        return;
 440    }
 441    bfa = crfS(ctx->opcode);
 442    nibble = 7 - bfa;
 443    shift = 4 * nibble;
 444    tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
 445    tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
 446    tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
 447    tcg_temp_free(tmp);
 448    tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
 449    /* Only the exception bits (including FX) should be cleared if read */
 450    tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS));
 451    /* FEX and VX need to be updated, so don't set fpscr directly */
 452    tmask = tcg_const_i32(1 << nibble);
 453    gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
 454    tcg_temp_free_i32(tmask);
 455    tcg_temp_free_i64(tnew_fpscr);
 456}
 457
 458/* mffs */
 459static void gen_mffs(DisasContext *ctx)
 460{
 461    if (unlikely(!ctx->fpu_enabled)) {
 462        gen_exception(ctx, POWERPC_EXCP_FPU);
 463        return;
 464    }
 465    gen_reset_fpstatus();
 466    tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
 467    if (unlikely(Rc(ctx->opcode))) {
 468        gen_set_cr1_from_fpscr(ctx);
 469    }
 470}
 471
 472/* mtfsb0 */
 473static void gen_mtfsb0(DisasContext *ctx)
 474{
 475    uint8_t crb;
 476
 477    if (unlikely(!ctx->fpu_enabled)) {
 478        gen_exception(ctx, POWERPC_EXCP_FPU);
 479        return;
 480    }
 481    crb = 31 - crbD(ctx->opcode);
 482    gen_reset_fpstatus();
 483    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
 484        TCGv_i32 t0;
 485        t0 = tcg_const_i32(crb);
 486        gen_helper_fpscr_clrbit(cpu_env, t0);
 487        tcg_temp_free_i32(t0);
 488    }
 489    if (unlikely(Rc(ctx->opcode) != 0)) {
 490        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
 491        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
 492    }
 493}
 494
 495/* mtfsb1 */
 496static void gen_mtfsb1(DisasContext *ctx)
 497{
 498    uint8_t crb;
 499
 500    if (unlikely(!ctx->fpu_enabled)) {
 501        gen_exception(ctx, POWERPC_EXCP_FPU);
 502        return;
 503    }
 504    crb = 31 - crbD(ctx->opcode);
 505    gen_reset_fpstatus();
 506    /* XXX: we pretend we can only do IEEE floating-point computations */
 507    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
 508        TCGv_i32 t0;
 509        t0 = tcg_const_i32(crb);
 510        gen_helper_fpscr_setbit(cpu_env, t0);
 511        tcg_temp_free_i32(t0);
 512    }
 513    if (unlikely(Rc(ctx->opcode) != 0)) {
 514        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
 515        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
 516    }
 517    /* We can raise a differed exception */
 518    gen_helper_float_check_status(cpu_env);
 519}
 520
 521/* mtfsf */
 522static void gen_mtfsf(DisasContext *ctx)
 523{
 524    TCGv_i32 t0;
 525    int flm, l, w;
 526
 527    if (unlikely(!ctx->fpu_enabled)) {
 528        gen_exception(ctx, POWERPC_EXCP_FPU);
 529        return;
 530    }
 531    flm = FPFLM(ctx->opcode);
 532    l = FPL(ctx->opcode);
 533    w = FPW(ctx->opcode);
 534    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
 535        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
 536        return;
 537    }
 538    gen_reset_fpstatus();
 539    if (l) {
 540        t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
 541    } else {
 542        t0 = tcg_const_i32(flm << (w * 8));
 543    }
 544    gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
 545    tcg_temp_free_i32(t0);
 546    if (unlikely(Rc(ctx->opcode) != 0)) {
 547        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
 548        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
 549    }
 550    /* We can raise a differed exception */
 551    gen_helper_float_check_status(cpu_env);
 552}
 553
 554/* mtfsfi */
 555static void gen_mtfsfi(DisasContext *ctx)
 556{
 557    int bf, sh, w;
 558    TCGv_i64 t0;
 559    TCGv_i32 t1;
 560
 561    if (unlikely(!ctx->fpu_enabled)) {
 562        gen_exception(ctx, POWERPC_EXCP_FPU);
 563        return;
 564    }
 565    w = FPW(ctx->opcode);
 566    bf = FPBF(ctx->opcode);
 567    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
 568        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
 569        return;
 570    }
 571    sh = (8 * w) + 7 - bf;
 572    gen_reset_fpstatus();
 573    t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
 574    t1 = tcg_const_i32(1 << sh);
 575    gen_helper_store_fpscr(cpu_env, t0, t1);
 576    tcg_temp_free_i64(t0);
 577    tcg_temp_free_i32(t1);
 578    if (unlikely(Rc(ctx->opcode) != 0)) {
 579        tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
 580        tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
 581    }
 582    /* We can raise a differed exception */
 583    gen_helper_float_check_status(cpu_env);
 584}
 585
 586/***                         Floating-point load                           ***/
 587#define GEN_LDF(name, ldop, opc, type)                                        \
 588static void glue(gen_, name)(DisasContext *ctx)                                       \
 589{                                                                             \
 590    TCGv EA;                                                                  \
 591    if (unlikely(!ctx->fpu_enabled)) {                                        \
 592        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 593        return;                                                               \
 594    }                                                                         \
 595    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 596    EA = tcg_temp_new();                                                      \
 597    gen_addr_imm_index(ctx, EA, 0);                                           \
 598    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
 599    tcg_temp_free(EA);                                                        \
 600}
 601
 602#define GEN_LDUF(name, ldop, opc, type)                                       \
 603static void glue(gen_, name##u)(DisasContext *ctx)                                    \
 604{                                                                             \
 605    TCGv EA;                                                                  \
 606    if (unlikely(!ctx->fpu_enabled)) {                                        \
 607        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 608        return;                                                               \
 609    }                                                                         \
 610    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
 611        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
 612        return;                                                               \
 613    }                                                                         \
 614    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 615    EA = tcg_temp_new();                                                      \
 616    gen_addr_imm_index(ctx, EA, 0);                                           \
 617    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
 618    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
 619    tcg_temp_free(EA);                                                        \
 620}
 621
 622#define GEN_LDUXF(name, ldop, opc, type)                                      \
 623static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
 624{                                                                             \
 625    TCGv EA;                                                                  \
 626    if (unlikely(!ctx->fpu_enabled)) {                                        \
 627        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 628        return;                                                               \
 629    }                                                                         \
 630    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
 631        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
 632        return;                                                               \
 633    }                                                                         \
 634    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 635    EA = tcg_temp_new();                                                      \
 636    gen_addr_reg_index(ctx, EA);                                              \
 637    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
 638    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
 639    tcg_temp_free(EA);                                                        \
 640}
 641
 642#define GEN_LDXF(name, ldop, opc2, opc3, type)                                \
 643static void glue(gen_, name##x)(DisasContext *ctx)                                    \
 644{                                                                             \
 645    TCGv EA;                                                                  \
 646    if (unlikely(!ctx->fpu_enabled)) {                                        \
 647        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 648        return;                                                               \
 649    }                                                                         \
 650    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 651    EA = tcg_temp_new();                                                      \
 652    gen_addr_reg_index(ctx, EA);                                              \
 653    gen_qemu_##ldop(ctx, cpu_fpr[rD(ctx->opcode)], EA);                       \
 654    tcg_temp_free(EA);                                                        \
 655}
 656
 657#define GEN_LDFS(name, ldop, op, type)                                        \
 658GEN_LDF(name, ldop, op | 0x20, type);                                         \
 659GEN_LDUF(name, ldop, op | 0x21, type);                                        \
 660GEN_LDUXF(name, ldop, op | 0x01, type);                                       \
 661GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
 662
 663static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 664{
 665    TCGv t0 = tcg_temp_new();
 666    TCGv_i32 t1 = tcg_temp_new_i32();
 667    gen_qemu_ld32u(ctx, t0, arg2);
 668    tcg_gen_trunc_tl_i32(t1, t0);
 669    tcg_temp_free(t0);
 670    gen_helper_float32_to_float64(arg1, cpu_env, t1);
 671    tcg_temp_free_i32(t1);
 672}
 673
 674 /* lfd lfdu lfdux lfdx */
 675GEN_LDFS(lfd, ld64_i64, 0x12, PPC_FLOAT);
 676 /* lfs lfsu lfsux lfsx */
 677GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
 678
 679/* lfdp */
 680static void gen_lfdp(DisasContext *ctx)
 681{
 682    TCGv EA;
 683    if (unlikely(!ctx->fpu_enabled)) {
 684        gen_exception(ctx, POWERPC_EXCP_FPU);
 685        return;
 686    }
 687    gen_set_access_type(ctx, ACCESS_FLOAT);
 688    EA = tcg_temp_new();
 689    gen_addr_imm_index(ctx, EA, 0);
 690    /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
 691       necessary 64-bit byteswap already. */
 692    if (unlikely(ctx->le_mode)) {
 693        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 694        tcg_gen_addi_tl(EA, EA, 8);
 695        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 696    } else {
 697        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 698        tcg_gen_addi_tl(EA, EA, 8);
 699        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 700    }
 701    tcg_temp_free(EA);
 702}
 703
 704/* lfdpx */
 705static void gen_lfdpx(DisasContext *ctx)
 706{
 707    TCGv EA;
 708    if (unlikely(!ctx->fpu_enabled)) {
 709        gen_exception(ctx, POWERPC_EXCP_FPU);
 710        return;
 711    }
 712    gen_set_access_type(ctx, ACCESS_FLOAT);
 713    EA = tcg_temp_new();
 714    gen_addr_reg_index(ctx, EA);
 715    /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
 716       necessary 64-bit byteswap already. */
 717    if (unlikely(ctx->le_mode)) {
 718        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 719        tcg_gen_addi_tl(EA, EA, 8);
 720        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 721    } else {
 722        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 723        tcg_gen_addi_tl(EA, EA, 8);
 724        gen_qemu_ld64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 725    }
 726    tcg_temp_free(EA);
 727}
 728
 729/* lfiwax */
 730static void gen_lfiwax(DisasContext *ctx)
 731{
 732    TCGv EA;
 733    TCGv t0;
 734    if (unlikely(!ctx->fpu_enabled)) {
 735        gen_exception(ctx, POWERPC_EXCP_FPU);
 736        return;
 737    }
 738    gen_set_access_type(ctx, ACCESS_FLOAT);
 739    EA = tcg_temp_new();
 740    t0 = tcg_temp_new();
 741    gen_addr_reg_index(ctx, EA);
 742    gen_qemu_ld32s(ctx, t0, EA);
 743    tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
 744    tcg_temp_free(EA);
 745    tcg_temp_free(t0);
 746}
 747
 748/* lfiwzx */
 749static void gen_lfiwzx(DisasContext *ctx)
 750{
 751    TCGv EA;
 752    if (unlikely(!ctx->fpu_enabled)) {
 753        gen_exception(ctx, POWERPC_EXCP_FPU);
 754        return;
 755    }
 756    gen_set_access_type(ctx, ACCESS_FLOAT);
 757    EA = tcg_temp_new();
 758    gen_addr_reg_index(ctx, EA);
 759    gen_qemu_ld32u_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 760    tcg_temp_free(EA);
 761}
 762/***                         Floating-point store                          ***/
 763#define GEN_STF(name, stop, opc, type)                                        \
 764static void glue(gen_, name)(DisasContext *ctx)                                       \
 765{                                                                             \
 766    TCGv EA;                                                                  \
 767    if (unlikely(!ctx->fpu_enabled)) {                                        \
 768        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 769        return;                                                               \
 770    }                                                                         \
 771    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 772    EA = tcg_temp_new();                                                      \
 773    gen_addr_imm_index(ctx, EA, 0);                                           \
 774    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
 775    tcg_temp_free(EA);                                                        \
 776}
 777
 778#define GEN_STUF(name, stop, opc, type)                                       \
 779static void glue(gen_, name##u)(DisasContext *ctx)                                    \
 780{                                                                             \
 781    TCGv EA;                                                                  \
 782    if (unlikely(!ctx->fpu_enabled)) {                                        \
 783        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 784        return;                                                               \
 785    }                                                                         \
 786    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
 787        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
 788        return;                                                               \
 789    }                                                                         \
 790    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 791    EA = tcg_temp_new();                                                      \
 792    gen_addr_imm_index(ctx, EA, 0);                                           \
 793    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
 794    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
 795    tcg_temp_free(EA);                                                        \
 796}
 797
 798#define GEN_STUXF(name, stop, opc, type)                                      \
 799static void glue(gen_, name##ux)(DisasContext *ctx)                                   \
 800{                                                                             \
 801    TCGv EA;                                                                  \
 802    if (unlikely(!ctx->fpu_enabled)) {                                        \
 803        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 804        return;                                                               \
 805    }                                                                         \
 806    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
 807        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);                   \
 808        return;                                                               \
 809    }                                                                         \
 810    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 811    EA = tcg_temp_new();                                                      \
 812    gen_addr_reg_index(ctx, EA);                                              \
 813    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
 814    tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);                             \
 815    tcg_temp_free(EA);                                                        \
 816}
 817
 818#define GEN_STXF(name, stop, opc2, opc3, type)                                \
 819static void glue(gen_, name##x)(DisasContext *ctx)                                    \
 820{                                                                             \
 821    TCGv EA;                                                                  \
 822    if (unlikely(!ctx->fpu_enabled)) {                                        \
 823        gen_exception(ctx, POWERPC_EXCP_FPU);                                 \
 824        return;                                                               \
 825    }                                                                         \
 826    gen_set_access_type(ctx, ACCESS_FLOAT);                                   \
 827    EA = tcg_temp_new();                                                      \
 828    gen_addr_reg_index(ctx, EA);                                              \
 829    gen_qemu_##stop(ctx, cpu_fpr[rS(ctx->opcode)], EA);                       \
 830    tcg_temp_free(EA);                                                        \
 831}
 832
 833#define GEN_STFS(name, stop, op, type)                                        \
 834GEN_STF(name, stop, op | 0x20, type);                                         \
 835GEN_STUF(name, stop, op | 0x21, type);                                        \
 836GEN_STUXF(name, stop, op | 0x01, type);                                       \
 837GEN_STXF(name, stop, 0x17, op | 0x00, type)
 838
 839static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 840{
 841    TCGv_i32 t0 = tcg_temp_new_i32();
 842    TCGv t1 = tcg_temp_new();
 843    gen_helper_float64_to_float32(t0, cpu_env, arg1);
 844    tcg_gen_extu_i32_tl(t1, t0);
 845    tcg_temp_free_i32(t0);
 846    gen_qemu_st32(ctx, t1, arg2);
 847    tcg_temp_free(t1);
 848}
 849
 850/* stfd stfdu stfdux stfdx */
 851GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT);
 852/* stfs stfsu stfsux stfsx */
 853GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
 854
 855/* stfdp */
 856static void gen_stfdp(DisasContext *ctx)
 857{
 858    TCGv EA;
 859    if (unlikely(!ctx->fpu_enabled)) {
 860        gen_exception(ctx, POWERPC_EXCP_FPU);
 861        return;
 862    }
 863    gen_set_access_type(ctx, ACCESS_FLOAT);
 864    EA = tcg_temp_new();
 865    gen_addr_imm_index(ctx, EA, 0);
 866    /* We only need to swap high and low halves. gen_qemu_st64_i64 does
 867       necessary 64-bit byteswap already. */
 868    if (unlikely(ctx->le_mode)) {
 869        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 870        tcg_gen_addi_tl(EA, EA, 8);
 871        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 872    } else {
 873        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 874        tcg_gen_addi_tl(EA, EA, 8);
 875        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 876    }
 877    tcg_temp_free(EA);
 878}
 879
 880/* stfdpx */
 881static void gen_stfdpx(DisasContext *ctx)
 882{
 883    TCGv EA;
 884    if (unlikely(!ctx->fpu_enabled)) {
 885        gen_exception(ctx, POWERPC_EXCP_FPU);
 886        return;
 887    }
 888    gen_set_access_type(ctx, ACCESS_FLOAT);
 889    EA = tcg_temp_new();
 890    gen_addr_reg_index(ctx, EA);
 891    /* We only need to swap high and low halves. gen_qemu_st64_i64 does
 892       necessary 64-bit byteswap already. */
 893    if (unlikely(ctx->le_mode)) {
 894        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 895        tcg_gen_addi_tl(EA, EA, 8);
 896        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 897    } else {
 898        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
 899        tcg_gen_addi_tl(EA, EA, 8);
 900        gen_qemu_st64_i64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
 901    }
 902    tcg_temp_free(EA);
 903}
 904
 905/* Optional: */
 906static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 907{
 908    TCGv t0 = tcg_temp_new();
 909    tcg_gen_trunc_i64_tl(t0, arg1),
 910    gen_qemu_st32(ctx, t0, arg2);
 911    tcg_temp_free(t0);
 912}
 913/* stfiwx */
 914GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
 915
 916/* POWER2 specific instructions */
 917/* Quad manipulation (load/store two floats at a time) */
 918
 919/* lfq */
 920static void gen_lfq(DisasContext *ctx)
 921{
 922    int rd = rD(ctx->opcode);
 923    TCGv t0;
 924    gen_set_access_type(ctx, ACCESS_FLOAT);
 925    t0 = tcg_temp_new();
 926    gen_addr_imm_index(ctx, t0, 0);
 927    gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
 928    gen_addr_add(ctx, t0, t0, 8);
 929    gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
 930    tcg_temp_free(t0);
 931}
 932
 933/* lfqu */
 934static void gen_lfqu(DisasContext *ctx)
 935{
 936    int ra = rA(ctx->opcode);
 937    int rd = rD(ctx->opcode);
 938    TCGv t0, t1;
 939    gen_set_access_type(ctx, ACCESS_FLOAT);
 940    t0 = tcg_temp_new();
 941    t1 = tcg_temp_new();
 942    gen_addr_imm_index(ctx, t0, 0);
 943    gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
 944    gen_addr_add(ctx, t1, t0, 8);
 945    gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
 946    if (ra != 0)
 947        tcg_gen_mov_tl(cpu_gpr[ra], t0);
 948    tcg_temp_free(t0);
 949    tcg_temp_free(t1);
 950}
 951
 952/* lfqux */
 953static void gen_lfqux(DisasContext *ctx)
 954{
 955    int ra = rA(ctx->opcode);
 956    int rd = rD(ctx->opcode);
 957    gen_set_access_type(ctx, ACCESS_FLOAT);
 958    TCGv t0, t1;
 959    t0 = tcg_temp_new();
 960    gen_addr_reg_index(ctx, t0);
 961    gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
 962    t1 = tcg_temp_new();
 963    gen_addr_add(ctx, t1, t0, 8);
 964    gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
 965    tcg_temp_free(t1);
 966    if (ra != 0)
 967        tcg_gen_mov_tl(cpu_gpr[ra], t0);
 968    tcg_temp_free(t0);
 969}
 970
 971/* lfqx */
 972static void gen_lfqx(DisasContext *ctx)
 973{
 974    int rd = rD(ctx->opcode);
 975    TCGv t0;
 976    gen_set_access_type(ctx, ACCESS_FLOAT);
 977    t0 = tcg_temp_new();
 978    gen_addr_reg_index(ctx, t0);
 979    gen_qemu_ld64_i64(ctx, cpu_fpr[rd], t0);
 980    gen_addr_add(ctx, t0, t0, 8);
 981    gen_qemu_ld64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
 982    tcg_temp_free(t0);
 983}
 984
 985/* stfq */
 986static void gen_stfq(DisasContext *ctx)
 987{
 988    int rd = rD(ctx->opcode);
 989    TCGv t0;
 990    gen_set_access_type(ctx, ACCESS_FLOAT);
 991    t0 = tcg_temp_new();
 992    gen_addr_imm_index(ctx, t0, 0);
 993    gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
 994    gen_addr_add(ctx, t0, t0, 8);
 995    gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
 996    tcg_temp_free(t0);
 997}
 998
 999/* stfqu */
1000static void gen_stfqu(DisasContext *ctx)
1001{
1002    int ra = rA(ctx->opcode);
1003    int rd = rD(ctx->opcode);
1004    TCGv t0, t1;
1005    gen_set_access_type(ctx, ACCESS_FLOAT);
1006    t0 = tcg_temp_new();
1007    gen_addr_imm_index(ctx, t0, 0);
1008    gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
1009    t1 = tcg_temp_new();
1010    gen_addr_add(ctx, t1, t0, 8);
1011    gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
1012    tcg_temp_free(t1);
1013    if (ra != 0)
1014        tcg_gen_mov_tl(cpu_gpr[ra], t0);
1015    tcg_temp_free(t0);
1016}
1017
1018/* stfqux */
1019static void gen_stfqux(DisasContext *ctx)
1020{
1021    int ra = rA(ctx->opcode);
1022    int rd = rD(ctx->opcode);
1023    TCGv t0, t1;
1024    gen_set_access_type(ctx, ACCESS_FLOAT);
1025    t0 = tcg_temp_new();
1026    gen_addr_reg_index(ctx, t0);
1027    gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
1028    t1 = tcg_temp_new();
1029    gen_addr_add(ctx, t1, t0, 8);
1030    gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t1);
1031    tcg_temp_free(t1);
1032    if (ra != 0)
1033        tcg_gen_mov_tl(cpu_gpr[ra], t0);
1034    tcg_temp_free(t0);
1035}
1036
1037/* stfqx */
1038static void gen_stfqx(DisasContext *ctx)
1039{
1040    int rd = rD(ctx->opcode);
1041    TCGv t0;
1042    gen_set_access_type(ctx, ACCESS_FLOAT);
1043    t0 = tcg_temp_new();
1044    gen_addr_reg_index(ctx, t0);
1045    gen_qemu_st64_i64(ctx, cpu_fpr[rd], t0);
1046    gen_addr_add(ctx, t0, t0, 8);
1047    gen_qemu_st64_i64(ctx, cpu_fpr[(rd + 1) % 32], t0);
1048    tcg_temp_free(t0);
1049}
1050
1051#undef _GEN_FLOAT_ACB
1052#undef GEN_FLOAT_ACB
1053#undef _GEN_FLOAT_AB
1054#undef GEN_FLOAT_AB
1055#undef _GEN_FLOAT_AC
1056#undef GEN_FLOAT_AC
1057#undef GEN_FLOAT_B
1058#undef GEN_FLOAT_BS
1059
1060#undef GEN_LDF
1061#undef GEN_LDUF
1062#undef GEN_LDUXF
1063#undef GEN_LDXF
1064#undef GEN_LDFS
1065
1066#undef GEN_STF
1067#undef GEN_STUF
1068#undef GEN_STUXF
1069#undef GEN_STXF
1070#undef GEN_STFS
1071