diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 17:01:22 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 17:01:22 +0000 |
commit | 4ecc31906d7535c4ad88fcc63968bef412dd67ba (patch) | |
tree | 9a38e0726804d67f9458293a32daabf9e7f1d894 /target-ppc | |
parent | 4c2e770f377a2c38bb26c24e333b747511ddd040 (diff) |
fpu fixes (Jocelyn Mayer) - soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1335 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 12 | ||||
-rw-r--r-- | target-ppc/exec.h | 10 | ||||
-rw-r--r-- | target-ppc/helper.c | 3 | ||||
-rw-r--r-- | target-ppc/op.c | 74 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 145 | ||||
-rw-r--r-- | target-ppc/translate.c | 95 |
6 files changed, 181 insertions, 158 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 1776a3577a..70ee83507a 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -27,6 +27,8 @@ #include "config.h" #include <setjmp.h> +#include "softfloat.h" + /* Instruction types */ enum { PPC_NONE = 0x0000, @@ -94,7 +96,7 @@ typedef struct CPUPPCState { /* general purpose registers */ uint32_t gpr[32]; /* floating point registers */ - double fpr[32]; + float64 fpr[32]; /* segment registers */ uint32_t sdr1; uint32_t sr[16]; @@ -119,9 +121,11 @@ typedef struct CPUPPCState { uint32_t spr[1024]; /* qemu dedicated */ /* temporary float registers */ - double ft0; - double ft1; - double ft2; + float64 ft0; + float64 ft1; + float64 ft2; + float_status fp_status; + int interrupt_request; jmp_buf jmp_env; int exception_index; diff --git a/target-ppc/exec.h b/target-ppc/exec.h index 503cf26c6d..ad21c56696 100644 --- a/target-ppc/exec.h +++ b/target-ppc/exec.h @@ -32,9 +32,6 @@ register uint32_t T2 asm(AREG3); #define FT0 (env->ft0) #define FT1 (env->ft1) #define FT2 (env->ft2) -#define FTS0 ((float)env->ft0) -#define FTS1 ((float)env->ft1) -#define FTS2 ((float)env->ft2) #if defined (DEBUG_OP) #define RETURN() __asm__ __volatile__("nop"); @@ -137,17 +134,12 @@ void do_fctiw (void); void do_fctiwz (void); void do_fnmadd (void); void do_fnmsub (void); -void do_fnmadds (void); -void do_fnmsubs (void); void do_fsqrt (void); -void do_fsqrts (void); void do_fres (void); -void do_fsqrte (void); +void do_frsqrte (void); void do_fsel (void); void do_fcmpu (void); void do_fcmpo (void); -void do_fabs (void); -void do_fnabs (void); void do_check_reservation (void); void do_icbi (void); diff --git a/target-ppc/helper.c b/target-ppc/helper.c index a9424dfa70..b54b5d2051 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -809,6 +809,7 @@ void do_interrupt (CPUState *env) msr |= 0x00010000; goto store_current; case EXCP_NO_FP: + msr &= ~0xFFFF0000; goto store_current; case EXCP_DECR: if (msr_ee == 0) { @@ -854,7 +855,6 @@ void do_interrupt (CPUState *env) return; case EXCP_RFI: /* Restore user-mode state */ - tb_flush(env); #if defined (DEBUG_EXCEPTIONS) if (msr_pr == 1) printf("Return from exception => 0x%08x\n", (uint32_t)env->nip); @@ -887,7 +887,6 @@ void do_interrupt (CPUState *env) env->nip = excp << 8; env->exception_index = EXCP_NONE; /* Invalidate all TLB as we may have changed translation mode */ - tlb_flush(env, 1); /* ensure that no TB jump will be modified as the program flow was changed */ #ifdef __sparc__ diff --git a/target-ppc/op.c b/target-ppc/op.c index 5accc55064..6ae7a523b5 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -32,10 +32,6 @@ #define FT1 (env->ft1) #define FT2 (env->ft2) -#define FTS0 ((float)env->ft0) -#define FTS1 ((float)env->ft1) -#define FTS2 ((float)env->ft2) - #define PPC_OP(name) void glue(op_, name)(void) #define REG 0 @@ -1204,13 +1200,6 @@ PPC_OP(fadd) RETURN(); } -/* fadds - fadds. */ -PPC_OP(fadds) -{ - FT0 = FTS0 + FTS1; - RETURN(); -} - /* fsub - fsub. */ PPC_OP(fsub) { @@ -1218,13 +1207,6 @@ PPC_OP(fsub) RETURN(); } -/* fsubs - fsubs. */ -PPC_OP(fsubs) -{ - FT0 = FTS0 - FTS1; - RETURN(); -} - /* fmul - fmul. */ PPC_OP(fmul) { @@ -1232,24 +1214,11 @@ PPC_OP(fmul) RETURN(); } -/* fmuls - fmuls. */ -PPC_OP(fmuls) -{ - FT0 = FTS0 * FTS1; - RETURN(); -} - /* fdiv - fdiv. */ +void do_fdiv (void); PPC_OP(fdiv) { - FT0 /= FT1; - RETURN(); -} - -/* fdivs - fdivs. */ -PPC_OP(fdivs) -{ - FT0 = FTS0 / FTS1; + do_fdiv(); RETURN(); } @@ -1260,13 +1229,6 @@ PPC_OP(fsqrt) RETURN(); } -/* fsqrts - fsqrts. */ -PPC_OP(fsqrts) -{ - do_fsqrts(); - RETURN(); -} - /* fres - fres. */ PPC_OP(fres) { @@ -1277,7 +1239,7 @@ PPC_OP(fres) /* frsqrte - frsqrte. */ PPC_OP(frsqrte) { - do_fsqrte(); + do_frsqrte(); RETURN(); } @@ -1296,13 +1258,6 @@ PPC_OP(fmadd) RETURN(); } -/* fmadds - fmadds. */ -PPC_OP(fmadds) -{ - FT0 = (FTS0 * FTS1) + FTS2; - RETURN(); -} - /* fmsub - fmsub. */ PPC_OP(fmsub) { @@ -1310,13 +1265,6 @@ PPC_OP(fmsub) RETURN(); } -/* fmsubs - fmsubs. */ -PPC_OP(fmsubs) -{ - FT0 = (FTS0 * FTS1) - FTS2; - RETURN(); -} - /* fnmadd - fnmadd. - fnmadds - fnmadds. */ PPC_OP(fnmadd) { @@ -1324,13 +1272,6 @@ PPC_OP(fnmadd) RETURN(); } -/* fnmadds - fnmadds. */ -PPC_OP(fnmadds) -{ - do_fnmadds(); - RETURN(); -} - /* fnmsub - fnmsub. */ PPC_OP(fnmsub) { @@ -1338,13 +1279,6 @@ PPC_OP(fnmsub) RETURN(); } -/* fnmsubs - fnmsubs. */ -PPC_OP(fnmsubs) -{ - do_fnmsubs(); - RETURN(); -} - /*** Floating-Point round & convert ***/ /* frsp - frsp. */ PPC_OP(frsp) @@ -1385,6 +1319,7 @@ PPC_OP(fcmpo) /*** Floating-point move ***/ /* fabs */ +void do_fabs (void); PPC_OP(fabs) { do_fabs(); @@ -1392,6 +1327,7 @@ PPC_OP(fabs) } /* fnabs */ +void do_fnabs (void); PPC_OP(fnabs) { do_fnabs(); diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 20aba8b6eb..102249d414 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -213,7 +213,7 @@ void do_store_fpscr (uint32_t mask) uint32_t u[2]; } s; } u; - int i; + int i, rnd_type; u.d = FT0; if (mask & 0x80) @@ -227,21 +227,23 @@ void do_store_fpscr (uint32_t mask) switch (env->fpscr[0] & 0x3) { case 0: /* Best approximation (round to nearest) */ - fesetround(FE_TONEAREST); + rnd_type = float_round_nearest_even; break; case 1: /* Smaller magnitude (round toward zero) */ - fesetround(FE_TOWARDZERO); + rnd_type = float_round_to_zero; break; case 2: /* Round toward +infinite */ - fesetround(FE_UPWARD); + rnd_type = float_round_up; break; + default: case 3: /* Round toward -infinite */ - fesetround(FE_DOWNWARD); + rnd_type = float_round_down; break; } + set_float_rounding_mode(rnd_type, &env->fp_status); } void do_fctiw (void) @@ -249,16 +251,14 @@ void do_fctiw (void) union { double d; uint64_t i; - } *p = (void *)&FT1; + } p; - if (FT0 > (double)0x7FFFFFFF) - p->i = 0x7FFFFFFFULL << 32; - else if (FT0 < -(double)0x80000000) - p->i = 0x80000000ULL << 32; - else - p->i = 0; - p->i |= (uint32_t)FT0; - FT0 = p->d; + /* XXX: higher bits are not supposed to be significant. + * to make tests easier, return the same as a real PPC 750 (aka G3) + */ + p.i = float64_to_int32(FT0, &env->fp_status); + p.i |= 0xFFF80000ULL << 32; + FT0 = p.d; } void do_fctiwz (void) @@ -266,39 +266,36 @@ void do_fctiwz (void) union { double d; uint64_t i; - } *p = (void *)&FT1; - int cround = fegetround(); - - fesetround(FE_TOWARDZERO); - if (FT0 > (double)0x7FFFFFFF) - p->i = 0x7FFFFFFFULL << 32; - else if (FT0 < -(double)0x80000000) - p->i = 0x80000000ULL << 32; - else - p->i = 0; - p->i |= (uint32_t)FT0; - FT0 = p->d; - fesetround(cround); + } p; + + /* XXX: higher bits are not supposed to be significant. + * to make tests easier, return the same as a real PPC 750 (aka G3) + */ + p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status); + p.i |= 0xFFF80000ULL << 32; + FT0 = p.d; } void do_fnmadd (void) { - FT0 = -((FT0 * FT1) + FT2); + FT0 = (FT0 * FT1) + FT2; + if (!isnan(FT0)) + FT0 = -FT0; } void do_fnmsub (void) { - FT0 = -((FT0 * FT1) - FT2); + FT0 = (FT0 * FT1) - FT2; + if (!isnan(FT0)) + FT0 = -FT0; } -void do_fnmadds (void) +void do_fdiv (void) { - FT0 = -((FTS0 * FTS1) + FTS2); -} - -void do_fnmsubs (void) -{ - FT0 = -((FTS0 * FTS1) - FTS2); + if (FT0 == -0.0 && FT1 == -0.0) + FT0 = 0.0 / 0.0; + else + FT0 /= FT1; } void do_fsqrt (void) @@ -306,27 +303,65 @@ void do_fsqrt (void) FT0 = sqrt(FT0); } -void do_fsqrts (void) -{ - FT0 = (float)sqrt((float)FT0); -} - void do_fres (void) { - FT0 = 1.0 / FT0; + union { + double d; + uint64_t i; + } p; + + if (isnormal(FT0)) { + FT0 = (float)(1.0 / FT0); + } else { + p.d = FT0; + if (p.i == 0x8000000000000000ULL) { + p.i = 0xFFF0000000000000ULL; + } else if (p.i == 0x0000000000000000ULL) { + p.i = 0x7FF0000000000000ULL; + } else if (isnan(FT0)) { + p.i = 0x7FF8000000000000ULL; + } else if (FT0 < 0.0) { + p.i = 0x8000000000000000ULL; + } else { + p.i = 0x0000000000000000ULL; + } + FT0 = p.d; + } } -void do_fsqrte (void) +void do_frsqrte (void) { - FT0 = 1.0 / sqrt(FT0); + union { + double d; + uint64_t i; + } p; + + if (isnormal(FT0) && FT0 > 0.0) { + FT0 = (float)(1.0 / sqrt(FT0)); + } else { + p.d = FT0; + if (p.i == 0x8000000000000000ULL) { + p.i = 0xFFF0000000000000ULL; + } else if (p.i == 0x0000000000000000ULL) { + p.i = 0x7FF0000000000000ULL; + } else if (isnan(FT0)) { + if (!(p.i & 0x0008000000000000ULL)) + p.i |= 0x000FFFFFFFFFFFFFULL; + } else if (FT0 < 0) { + p.i = 0x7FF8000000000000ULL; + } else { + p.i = 0x0000000000000000ULL; + } + FT0 = p.d; + } } void do_fsel (void) { if (FT0 >= 0) - FT0 = FT2; - else FT0 = FT1; + else + FT0 = FT2; } void do_fcmpu (void) @@ -371,12 +406,26 @@ void do_fcmpo (void) void do_fabs (void) { - FT0 = fabsl(FT0); + union { + double d; + uint64_t i; + } p; + + p.d = FT0; + p.i &= ~0x8000000000000000ULL; + FT0 = p.d; } void do_fnabs (void) { - FT0 = -fabsl(FT0); + union { + double d; + uint64_t i; + } p; + + p.d = FT0; + p.i |= 0x8000000000000000ULL; + FT0 = p.d; } /* Instruction cache invalidation helper */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index bb3bbbb544..f41bbb845b 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -740,6 +740,7 @@ __GEN_LOGICAL2(sraw, 0x18, 0x18); GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) { gen_op_load_gpr_T0(rS(ctx->opcode)); + if (SH(ctx->opcode) != 0) gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31)); if (Rc(ctx->opcode) != 0) gen_op_set_Rc0(); @@ -749,7 +750,7 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) __GEN_LOGICAL2(srw, 0x18, 0x10); /*** Floating-Point arithmetic ***/ -#define _GEN_FLOAT_ACB(name, op1, op2) \ +#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -760,17 +761,20 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rC(ctx->opcode)); \ gen_op_load_fpr_FT2(rB(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_ACB(name, op2) \ -_GEN_FLOAT_ACB(name, 0x3F, op2); \ -_GEN_FLOAT_ACB(name##s, 0x3B, op2); +_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \ +_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1); -#define _GEN_FLOAT_AB(name, op1, op2, inval) \ +#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -780,16 +784,19 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ gen_op_reset_scrfx(); \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rB(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_AB(name, op2, inval) \ -_GEN_FLOAT_AB(name, 0x3F, op2, inval); \ -_GEN_FLOAT_AB(name##s, 0x3B, op2, inval); +_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \ +_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); -#define _GEN_FLOAT_AC(name, op1, op2, inval) \ +#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -799,14 +806,17 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ gen_op_reset_scrfx(); \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rC(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_AC(name, op2, inval) \ -_GEN_FLOAT_AC(name, 0x3F, op2, inval); \ -_GEN_FLOAT_AC(name##s, 0x3B, op2, inval); +_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \ +_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); #define GEN_FLOAT_B(name, op2, op3) \ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ @@ -823,8 +833,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ gen_op_set_Rc1(); \ } -#define GEN_FLOAT_BS(name, op2) \ -GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ +#define GEN_FLOAT_BS(name, op1, op2) \ +GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ RET_EXCP(ctx, EXCP_NO_FP, 0); \ @@ -840,24 +850,24 @@ GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ /* fadd - fadds */ GEN_FLOAT_AB(add, 0x15, 0x000007C0); -/* fdiv */ +/* fdiv - fdivs */ GEN_FLOAT_AB(div, 0x12, 0x000007C0); -/* fmul */ +/* fmul - fmuls */ GEN_FLOAT_AC(mul, 0x19, 0x0000F800); /* fres */ -GEN_FLOAT_BS(res, 0x18); +GEN_FLOAT_BS(res, 0x3B, 0x18); /* frsqrte */ -GEN_FLOAT_BS(rsqrte, 0x1A); +GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A); /* fsel */ -_GEN_FLOAT_ACB(sel, 0x3F, 0x17); -/* fsub */ +_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0); +/* fsub - fsubs */ GEN_FLOAT_AB(sub, 0x14, 0x000007C0); /* Optional: */ /* fsqrt */ -GEN_FLOAT_BS(sqrt, 0x16); +GEN_FLOAT_BS(sqrt, 0x3F, 0x16); GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) { @@ -867,20 +877,21 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) } gen_op_reset_scrfx(); gen_op_load_fpr_FT0(rB(ctx->opcode)); - gen_op_fsqrts(); + gen_op_fsqrt(); + gen_op_frsp(); gen_op_store_FT0_fpr(rD(ctx->opcode)); if (Rc(ctx->opcode)) gen_op_set_Rc1(); } /*** Floating-Point multiply-and-add ***/ -/* fmadd */ +/* fmadd - fmadds */ GEN_FLOAT_ACB(madd, 0x1D); -/* fmsub */ +/* fmsub - fmsubs */ GEN_FLOAT_ACB(msub, 0x1C); -/* fnmadd */ +/* fnmadd - fnmadds */ GEN_FLOAT_ACB(nmadd, 0x1F); -/* fnmsub */ +/* fnmsub - fnmsubs */ GEN_FLOAT_ACB(nmsub, 0x1E); /*** Floating-Point round & convert ***/ @@ -1426,6 +1437,10 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ @@ -1441,6 +1456,10 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ @@ -1457,6 +1476,10 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ #define GEN_LDUXF(width, opc) \ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ @@ -1473,6 +1496,10 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ #define GEN_LDXF(width, opc2, opc3) \ GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ @@ -1501,6 +1528,10 @@ GEN_LDFS(fs, 0x10); GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ @@ -1516,6 +1547,10 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ @@ -1531,6 +1566,10 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ #define GEN_STUXF(width, opc) \ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ @@ -1546,6 +1585,10 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ #define GEN_STXF(width, opc2, opc3) \ GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ |