fpu fixes (Jocelyn Mayer) - soft float support
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 Mar 2005 17:01:22 +0000 (17:01 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 Mar 2005 17:01:22 +0000 (17:01 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1335 c046a42c-6fe2-441c-8c8c-71466251a162

target-ppc/cpu.h
target-ppc/exec.h
target-ppc/helper.c
target-ppc/op.c
target-ppc/op_helper.c
target-ppc/translate.c

index 1776a35..70ee835 100644 (file)
@@ -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;
index 503cf26..ad21c56 100644 (file)
@@ -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);
index a9424df..b54b5d2 100644 (file)
@@ -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__
index 5accc55..6ae7a52 100644 (file)
 #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();
index 20aba8b..102249d 100644 (file)
@@ -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 */
index bb3bbbb..f41bbb8 100644 (file)
@@ -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 {                                                                  \