From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1D6d8h-0007sS-SD for qemu-devel@nongnu.org; Wed, 02 Mar 2005 18:20:24 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1D6d8V-0007nM-Lr for qemu-devel@nongnu.org; Wed, 02 Mar 2005 18:20:13 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1D6d8V-0007mx-Ff for qemu-devel@nongnu.org; Wed, 02 Mar 2005 18:20:11 -0500 Received: from [62.210.158.45] (helo=quito.magic.fr) by monty-python.gnu.org with esmtp (Exim 4.34) id 1D6ctm-0008Bz-2g for qemu-devel@nongnu.org; Wed, 02 Mar 2005 18:04:59 -0500 From: "J. Mayer" Content-Type: multipart/mixed; boundary="=-qVGG9Dtd6N4si0kQ7jSe" Message-Id: <1109804693.13299.9584.camel@rapid> Mime-Version: 1.0 Date: Thu, 03 Mar 2005 00:04:53 +0100 Subject: [Qemu-devel] More PPC emulation fixes Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --=-qVGG9Dtd6N4si0kQ7jSe Content-Type: text/plain Content-Transfer-Encoding: 7bit Here's a new patch that fixes the last (!) bug in PPC fixed point operations and most FPU bugs. Apply and enjoy. More infos about this patch: I did test exhaustively all arithmetic, logical and compare operations for fixed point and floating points computation with large ranges of operands then compared the result with the ones I got from a real G3. The bugs I found which are fixed with this patch are: - srawi did set the overflow bit in XER register in some case when used with a 0 shift. Then, I now do no computation if shift is 0. - I did forget to generate FP_UNAVAILABLE exception when trying to use lfd, lfs, stfd and stfs instructions when FPU is not enabled. This lead to random crashes or bad computations under Linux. - operands for fsel where interverted. - fres major opcode was false. - conversion from float to int has been improved. - floating points operations applied on single operands where false: PPC specifies that the cast to single should be done only on the computation result. Then I removed all micro-ops for single float operands and now just use frsp after computation. - multiply-and-add/sub-and-negate operations have been fixed for special operands (NaN, infinite, ...) - estimated single operation (ie fres, frsqrte) have been fixed for special operands - absolute values computation have been fixed. - I also removed unusefull tb_flush & tlb_flush which are not needed anymore now that tb flags are set properly. There still are some things to improve: - some computations on single operands may have a difference on the last significant bit of the mantissa. This only appears when a multiplication is involved, ie for fmuls, fmadds, fmsubs, fnmadds and fnmsubs. All other operations give exactly the same result as a real G3. As PPC specs talks about multiply computation with 105 bits mantissa intermediary results, I may have to use long doubles to fix this issue (not tried). But I really think the current results may not hurt anyone. - No flags are managed for floating-point computations, except for compare instructions. This does not seem to be important for the glibc but is a potential problem for other OSes. With this patch, Debian Sarge is now able to install. It need OHW patches to reboot and go on running the installer. I'll released a second 0.4 preview with fixes for this (and more...) soon. However, one need to run "expert" installation, or the installer will go into an infinite loop trying to probe the link on the NE2k device. -- J. Mayer Never organized --=-qVGG9Dtd6N4si0kQ7jSe Content-Disposition: attachment; filename=ppc_fixes.diff Content-Type: text/x-patch; name=ppc_fixes.diff; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Index: target-ppc/exec.h =================================================================== RCS file: /cvsroot/qemu/qemu/target-ppc/exec.h,v retrieving revision 1.9 diff -u -d -w -B -b -d -p -r1.9 exec.h --- target-ppc/exec.h 3 Jan 2005 23:42:39 -0000 1.9 +++ target-ppc/exec.h 2 Mar 2005 21:51:07 -0000 @@ -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: target-ppc/helper.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-ppc/helper.c,v retrieving revision 1.21 diff -u -d -w -B -b -d -p -r1.21 helper.c --- target-ppc/helper.c 15 Feb 2005 23:06:19 -0000 1.21 +++ target-ppc/helper.c 2 Mar 2005 21:51:07 -0000 @@ -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 +888,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: target-ppc/op.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-ppc/op.c,v retrieving revision 1.15 diff -u -d -w -B -b -d -p -r1.15 op.c --- target-ppc/op.c 15 Feb 2005 23:06:19 -0000 1.15 +++ target-ppc/op.c 2 Mar 2005 21:51:07 -0000 @@ -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(); Index: target-ppc/op_helper.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-ppc/op_helper.c,v retrieving revision 1.11 diff -u -d -w -B -b -d -p -r1.11 op_helper.c --- target-ppc/op_helper.c 15 Feb 2005 23:06:19 -0000 1.11 +++ target-ppc/op_helper.c 2 Mar 2005 21:51:07 -0000 @@ -249,16 +249,25 @@ 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.d = FT0; + if (FT0 > (double)0x7FFFFFFF) { + p.i = 0x7FFFFFFFULL; + // env->fpscr |= 1 << 17; + } else if (FT0 < -(double)0x80000000) { + p.i = 0x80000000ULL; + // env->fpscr |= 1 << 17; + } else if (p.i & 0x8000000000000000ULL) { + p.i = 0x100000000ULL | (uint32_t)FT0; + } else { + p.i = (uint32_t)FT0; + } + p.i |= 0xFFF80000ULL << 32; + FT0 = p.d; } void do_fctiwz (void) @@ -266,39 +275,50 @@ void do_fctiwz (void) union { double d; uint64_t i; - } *p = (void *)&FT1; + } p; int cround = fegetround(); + /* XXX: higher bits are not supposed to be significant. + * to make tests easier, return the same as a real PPC 750 (aka G3) + */ + p.d = FT0; 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; + if (FT0 > (double)0x7FFFFFFF) { + p.i = 0x7FFFFFFFULL; + // env->fpscr |= 1 << 17; + } else if (FT0 < -(double)0x80000000) { + p.i = 0x80000000ULL; + // env->fpscr |= 1 << 17; + } else if (p.i & 0x8000000000000000ULL) { + p.i = 0x100000000ULL | (uint32_t)FT0; + } else { + p.i = (uint32_t)FT0; + } + p.i |= 0xFFF80000ULL << 32; + FT0 = p.d; fesetround(cround); } 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); -} - -void do_fnmadds (void) -{ - FT0 = -((FTS0 * FTS1) + FTS2); + FT0 = (FT0 * FT1) - FT2; + if (!isnan(FT0)) + FT0 = -FT0; } -void do_fnmsubs (void) +void do_fdiv (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 +326,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 +429,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: target-ppc/translate.c =================================================================== RCS file: /cvsroot/qemu/qemu/target-ppc/translate.c,v retrieving revision 1.27 diff -u -d -w -B -b -d -p -r1.27 translate.c --- target-ppc/translate.c 15 Feb 2005 23:06:19 -0000 1.27 +++ target-ppc/translate.c 2 Mar 2005 21:51:08 -0000 @@ -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, 0x0 __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, 0x0 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, inv 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, inv 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, 0x0 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, 0x /* 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, 0x } 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, 0x03 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, 0 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 #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, op #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, 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, 0xF #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, o #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 { \ --=-qVGG9Dtd6N4si0kQ7jSe--