Commit 4ecc31906d7535c4ad88fcc63968bef412dd67ba
1 parent
4c2e770f
fpu fixes (Jocelyn Mayer) - soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1335 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
181 additions
and
158 deletions
target-ppc/cpu.h
| @@ -27,6 +27,8 @@ | @@ -27,6 +27,8 @@ | ||
| 27 | #include "config.h" | 27 | #include "config.h" |
| 28 | #include <setjmp.h> | 28 | #include <setjmp.h> |
| 29 | 29 | ||
| 30 | +#include "softfloat.h" | ||
| 31 | + | ||
| 30 | /* Instruction types */ | 32 | /* Instruction types */ |
| 31 | enum { | 33 | enum { |
| 32 | PPC_NONE = 0x0000, | 34 | PPC_NONE = 0x0000, |
| @@ -94,7 +96,7 @@ typedef struct CPUPPCState { | @@ -94,7 +96,7 @@ typedef struct CPUPPCState { | ||
| 94 | /* general purpose registers */ | 96 | /* general purpose registers */ |
| 95 | uint32_t gpr[32]; | 97 | uint32_t gpr[32]; |
| 96 | /* floating point registers */ | 98 | /* floating point registers */ |
| 97 | - double fpr[32]; | 99 | + float64 fpr[32]; |
| 98 | /* segment registers */ | 100 | /* segment registers */ |
| 99 | uint32_t sdr1; | 101 | uint32_t sdr1; |
| 100 | uint32_t sr[16]; | 102 | uint32_t sr[16]; |
| @@ -119,9 +121,11 @@ typedef struct CPUPPCState { | @@ -119,9 +121,11 @@ typedef struct CPUPPCState { | ||
| 119 | uint32_t spr[1024]; | 121 | uint32_t spr[1024]; |
| 120 | /* qemu dedicated */ | 122 | /* qemu dedicated */ |
| 121 | /* temporary float registers */ | 123 | /* temporary float registers */ |
| 122 | - double ft0; | ||
| 123 | - double ft1; | ||
| 124 | - double ft2; | 124 | + float64 ft0; |
| 125 | + float64 ft1; | ||
| 126 | + float64 ft2; | ||
| 127 | + float_status fp_status; | ||
| 128 | + | ||
| 125 | int interrupt_request; | 129 | int interrupt_request; |
| 126 | jmp_buf jmp_env; | 130 | jmp_buf jmp_env; |
| 127 | int exception_index; | 131 | int exception_index; |
target-ppc/exec.h
| @@ -32,9 +32,6 @@ register uint32_t T2 asm(AREG3); | @@ -32,9 +32,6 @@ register uint32_t T2 asm(AREG3); | ||
| 32 | #define FT0 (env->ft0) | 32 | #define FT0 (env->ft0) |
| 33 | #define FT1 (env->ft1) | 33 | #define FT1 (env->ft1) |
| 34 | #define FT2 (env->ft2) | 34 | #define FT2 (env->ft2) |
| 35 | -#define FTS0 ((float)env->ft0) | ||
| 36 | -#define FTS1 ((float)env->ft1) | ||
| 37 | -#define FTS2 ((float)env->ft2) | ||
| 38 | 35 | ||
| 39 | #if defined (DEBUG_OP) | 36 | #if defined (DEBUG_OP) |
| 40 | #define RETURN() __asm__ __volatile__("nop"); | 37 | #define RETURN() __asm__ __volatile__("nop"); |
| @@ -137,17 +134,12 @@ void do_fctiw (void); | @@ -137,17 +134,12 @@ void do_fctiw (void); | ||
| 137 | void do_fctiwz (void); | 134 | void do_fctiwz (void); |
| 138 | void do_fnmadd (void); | 135 | void do_fnmadd (void); |
| 139 | void do_fnmsub (void); | 136 | void do_fnmsub (void); |
| 140 | -void do_fnmadds (void); | ||
| 141 | -void do_fnmsubs (void); | ||
| 142 | void do_fsqrt (void); | 137 | void do_fsqrt (void); |
| 143 | -void do_fsqrts (void); | ||
| 144 | void do_fres (void); | 138 | void do_fres (void); |
| 145 | -void do_fsqrte (void); | 139 | +void do_frsqrte (void); |
| 146 | void do_fsel (void); | 140 | void do_fsel (void); |
| 147 | void do_fcmpu (void); | 141 | void do_fcmpu (void); |
| 148 | void do_fcmpo (void); | 142 | void do_fcmpo (void); |
| 149 | -void do_fabs (void); | ||
| 150 | -void do_fnabs (void); | ||
| 151 | 143 | ||
| 152 | void do_check_reservation (void); | 144 | void do_check_reservation (void); |
| 153 | void do_icbi (void); | 145 | void do_icbi (void); |
target-ppc/helper.c
| @@ -809,6 +809,7 @@ void do_interrupt (CPUState *env) | @@ -809,6 +809,7 @@ void do_interrupt (CPUState *env) | ||
| 809 | msr |= 0x00010000; | 809 | msr |= 0x00010000; |
| 810 | goto store_current; | 810 | goto store_current; |
| 811 | case EXCP_NO_FP: | 811 | case EXCP_NO_FP: |
| 812 | + msr &= ~0xFFFF0000; | ||
| 812 | goto store_current; | 813 | goto store_current; |
| 813 | case EXCP_DECR: | 814 | case EXCP_DECR: |
| 814 | if (msr_ee == 0) { | 815 | if (msr_ee == 0) { |
| @@ -854,7 +855,6 @@ void do_interrupt (CPUState *env) | @@ -854,7 +855,6 @@ void do_interrupt (CPUState *env) | ||
| 854 | return; | 855 | return; |
| 855 | case EXCP_RFI: | 856 | case EXCP_RFI: |
| 856 | /* Restore user-mode state */ | 857 | /* Restore user-mode state */ |
| 857 | - tb_flush(env); | ||
| 858 | #if defined (DEBUG_EXCEPTIONS) | 858 | #if defined (DEBUG_EXCEPTIONS) |
| 859 | if (msr_pr == 1) | 859 | if (msr_pr == 1) |
| 860 | printf("Return from exception => 0x%08x\n", (uint32_t)env->nip); | 860 | printf("Return from exception => 0x%08x\n", (uint32_t)env->nip); |
| @@ -887,7 +887,6 @@ void do_interrupt (CPUState *env) | @@ -887,7 +887,6 @@ void do_interrupt (CPUState *env) | ||
| 887 | env->nip = excp << 8; | 887 | env->nip = excp << 8; |
| 888 | env->exception_index = EXCP_NONE; | 888 | env->exception_index = EXCP_NONE; |
| 889 | /* Invalidate all TLB as we may have changed translation mode */ | 889 | /* Invalidate all TLB as we may have changed translation mode */ |
| 890 | - tlb_flush(env, 1); | ||
| 891 | /* ensure that no TB jump will be modified as | 890 | /* ensure that no TB jump will be modified as |
| 892 | the program flow was changed */ | 891 | the program flow was changed */ |
| 893 | #ifdef __sparc__ | 892 | #ifdef __sparc__ |
target-ppc/op.c
| @@ -32,10 +32,6 @@ | @@ -32,10 +32,6 @@ | ||
| 32 | #define FT1 (env->ft1) | 32 | #define FT1 (env->ft1) |
| 33 | #define FT2 (env->ft2) | 33 | #define FT2 (env->ft2) |
| 34 | 34 | ||
| 35 | -#define FTS0 ((float)env->ft0) | ||
| 36 | -#define FTS1 ((float)env->ft1) | ||
| 37 | -#define FTS2 ((float)env->ft2) | ||
| 38 | - | ||
| 39 | #define PPC_OP(name) void glue(op_, name)(void) | 35 | #define PPC_OP(name) void glue(op_, name)(void) |
| 40 | 36 | ||
| 41 | #define REG 0 | 37 | #define REG 0 |
| @@ -1204,13 +1200,6 @@ PPC_OP(fadd) | @@ -1204,13 +1200,6 @@ PPC_OP(fadd) | ||
| 1204 | RETURN(); | 1200 | RETURN(); |
| 1205 | } | 1201 | } |
| 1206 | 1202 | ||
| 1207 | -/* fadds - fadds. */ | ||
| 1208 | -PPC_OP(fadds) | ||
| 1209 | -{ | ||
| 1210 | - FT0 = FTS0 + FTS1; | ||
| 1211 | - RETURN(); | ||
| 1212 | -} | ||
| 1213 | - | ||
| 1214 | /* fsub - fsub. */ | 1203 | /* fsub - fsub. */ |
| 1215 | PPC_OP(fsub) | 1204 | PPC_OP(fsub) |
| 1216 | { | 1205 | { |
| @@ -1218,13 +1207,6 @@ PPC_OP(fsub) | @@ -1218,13 +1207,6 @@ PPC_OP(fsub) | ||
| 1218 | RETURN(); | 1207 | RETURN(); |
| 1219 | } | 1208 | } |
| 1220 | 1209 | ||
| 1221 | -/* fsubs - fsubs. */ | ||
| 1222 | -PPC_OP(fsubs) | ||
| 1223 | -{ | ||
| 1224 | - FT0 = FTS0 - FTS1; | ||
| 1225 | - RETURN(); | ||
| 1226 | -} | ||
| 1227 | - | ||
| 1228 | /* fmul - fmul. */ | 1210 | /* fmul - fmul. */ |
| 1229 | PPC_OP(fmul) | 1211 | PPC_OP(fmul) |
| 1230 | { | 1212 | { |
| @@ -1232,24 +1214,11 @@ PPC_OP(fmul) | @@ -1232,24 +1214,11 @@ PPC_OP(fmul) | ||
| 1232 | RETURN(); | 1214 | RETURN(); |
| 1233 | } | 1215 | } |
| 1234 | 1216 | ||
| 1235 | -/* fmuls - fmuls. */ | ||
| 1236 | -PPC_OP(fmuls) | ||
| 1237 | -{ | ||
| 1238 | - FT0 = FTS0 * FTS1; | ||
| 1239 | - RETURN(); | ||
| 1240 | -} | ||
| 1241 | - | ||
| 1242 | /* fdiv - fdiv. */ | 1217 | /* fdiv - fdiv. */ |
| 1218 | +void do_fdiv (void); | ||
| 1243 | PPC_OP(fdiv) | 1219 | PPC_OP(fdiv) |
| 1244 | { | 1220 | { |
| 1245 | - FT0 /= FT1; | ||
| 1246 | - RETURN(); | ||
| 1247 | -} | ||
| 1248 | - | ||
| 1249 | -/* fdivs - fdivs. */ | ||
| 1250 | -PPC_OP(fdivs) | ||
| 1251 | -{ | ||
| 1252 | - FT0 = FTS0 / FTS1; | 1221 | + do_fdiv(); |
| 1253 | RETURN(); | 1222 | RETURN(); |
| 1254 | } | 1223 | } |
| 1255 | 1224 | ||
| @@ -1260,13 +1229,6 @@ PPC_OP(fsqrt) | @@ -1260,13 +1229,6 @@ PPC_OP(fsqrt) | ||
| 1260 | RETURN(); | 1229 | RETURN(); |
| 1261 | } | 1230 | } |
| 1262 | 1231 | ||
| 1263 | -/* fsqrts - fsqrts. */ | ||
| 1264 | -PPC_OP(fsqrts) | ||
| 1265 | -{ | ||
| 1266 | - do_fsqrts(); | ||
| 1267 | - RETURN(); | ||
| 1268 | -} | ||
| 1269 | - | ||
| 1270 | /* fres - fres. */ | 1232 | /* fres - fres. */ |
| 1271 | PPC_OP(fres) | 1233 | PPC_OP(fres) |
| 1272 | { | 1234 | { |
| @@ -1277,7 +1239,7 @@ PPC_OP(fres) | @@ -1277,7 +1239,7 @@ PPC_OP(fres) | ||
| 1277 | /* frsqrte - frsqrte. */ | 1239 | /* frsqrte - frsqrte. */ |
| 1278 | PPC_OP(frsqrte) | 1240 | PPC_OP(frsqrte) |
| 1279 | { | 1241 | { |
| 1280 | - do_fsqrte(); | 1242 | + do_frsqrte(); |
| 1281 | RETURN(); | 1243 | RETURN(); |
| 1282 | } | 1244 | } |
| 1283 | 1245 | ||
| @@ -1296,13 +1258,6 @@ PPC_OP(fmadd) | @@ -1296,13 +1258,6 @@ PPC_OP(fmadd) | ||
| 1296 | RETURN(); | 1258 | RETURN(); |
| 1297 | } | 1259 | } |
| 1298 | 1260 | ||
| 1299 | -/* fmadds - fmadds. */ | ||
| 1300 | -PPC_OP(fmadds) | ||
| 1301 | -{ | ||
| 1302 | - FT0 = (FTS0 * FTS1) + FTS2; | ||
| 1303 | - RETURN(); | ||
| 1304 | -} | ||
| 1305 | - | ||
| 1306 | /* fmsub - fmsub. */ | 1261 | /* fmsub - fmsub. */ |
| 1307 | PPC_OP(fmsub) | 1262 | PPC_OP(fmsub) |
| 1308 | { | 1263 | { |
| @@ -1310,13 +1265,6 @@ PPC_OP(fmsub) | @@ -1310,13 +1265,6 @@ PPC_OP(fmsub) | ||
| 1310 | RETURN(); | 1265 | RETURN(); |
| 1311 | } | 1266 | } |
| 1312 | 1267 | ||
| 1313 | -/* fmsubs - fmsubs. */ | ||
| 1314 | -PPC_OP(fmsubs) | ||
| 1315 | -{ | ||
| 1316 | - FT0 = (FTS0 * FTS1) - FTS2; | ||
| 1317 | - RETURN(); | ||
| 1318 | -} | ||
| 1319 | - | ||
| 1320 | /* fnmadd - fnmadd. - fnmadds - fnmadds. */ | 1268 | /* fnmadd - fnmadd. - fnmadds - fnmadds. */ |
| 1321 | PPC_OP(fnmadd) | 1269 | PPC_OP(fnmadd) |
| 1322 | { | 1270 | { |
| @@ -1324,13 +1272,6 @@ PPC_OP(fnmadd) | @@ -1324,13 +1272,6 @@ PPC_OP(fnmadd) | ||
| 1324 | RETURN(); | 1272 | RETURN(); |
| 1325 | } | 1273 | } |
| 1326 | 1274 | ||
| 1327 | -/* fnmadds - fnmadds. */ | ||
| 1328 | -PPC_OP(fnmadds) | ||
| 1329 | -{ | ||
| 1330 | - do_fnmadds(); | ||
| 1331 | - RETURN(); | ||
| 1332 | -} | ||
| 1333 | - | ||
| 1334 | /* fnmsub - fnmsub. */ | 1275 | /* fnmsub - fnmsub. */ |
| 1335 | PPC_OP(fnmsub) | 1276 | PPC_OP(fnmsub) |
| 1336 | { | 1277 | { |
| @@ -1338,13 +1279,6 @@ PPC_OP(fnmsub) | @@ -1338,13 +1279,6 @@ PPC_OP(fnmsub) | ||
| 1338 | RETURN(); | 1279 | RETURN(); |
| 1339 | } | 1280 | } |
| 1340 | 1281 | ||
| 1341 | -/* fnmsubs - fnmsubs. */ | ||
| 1342 | -PPC_OP(fnmsubs) | ||
| 1343 | -{ | ||
| 1344 | - do_fnmsubs(); | ||
| 1345 | - RETURN(); | ||
| 1346 | -} | ||
| 1347 | - | ||
| 1348 | /*** Floating-Point round & convert ***/ | 1282 | /*** Floating-Point round & convert ***/ |
| 1349 | /* frsp - frsp. */ | 1283 | /* frsp - frsp. */ |
| 1350 | PPC_OP(frsp) | 1284 | PPC_OP(frsp) |
| @@ -1385,6 +1319,7 @@ PPC_OP(fcmpo) | @@ -1385,6 +1319,7 @@ PPC_OP(fcmpo) | ||
| 1385 | 1319 | ||
| 1386 | /*** Floating-point move ***/ | 1320 | /*** Floating-point move ***/ |
| 1387 | /* fabs */ | 1321 | /* fabs */ |
| 1322 | +void do_fabs (void); | ||
| 1388 | PPC_OP(fabs) | 1323 | PPC_OP(fabs) |
| 1389 | { | 1324 | { |
| 1390 | do_fabs(); | 1325 | do_fabs(); |
| @@ -1392,6 +1327,7 @@ PPC_OP(fabs) | @@ -1392,6 +1327,7 @@ PPC_OP(fabs) | ||
| 1392 | } | 1327 | } |
| 1393 | 1328 | ||
| 1394 | /* fnabs */ | 1329 | /* fnabs */ |
| 1330 | +void do_fnabs (void); | ||
| 1395 | PPC_OP(fnabs) | 1331 | PPC_OP(fnabs) |
| 1396 | { | 1332 | { |
| 1397 | do_fnabs(); | 1333 | do_fnabs(); |
target-ppc/op_helper.c
| @@ -213,7 +213,7 @@ void do_store_fpscr (uint32_t mask) | @@ -213,7 +213,7 @@ void do_store_fpscr (uint32_t mask) | ||
| 213 | uint32_t u[2]; | 213 | uint32_t u[2]; |
| 214 | } s; | 214 | } s; |
| 215 | } u; | 215 | } u; |
| 216 | - int i; | 216 | + int i, rnd_type; |
| 217 | 217 | ||
| 218 | u.d = FT0; | 218 | u.d = FT0; |
| 219 | if (mask & 0x80) | 219 | if (mask & 0x80) |
| @@ -227,21 +227,23 @@ void do_store_fpscr (uint32_t mask) | @@ -227,21 +227,23 @@ void do_store_fpscr (uint32_t mask) | ||
| 227 | switch (env->fpscr[0] & 0x3) { | 227 | switch (env->fpscr[0] & 0x3) { |
| 228 | case 0: | 228 | case 0: |
| 229 | /* Best approximation (round to nearest) */ | 229 | /* Best approximation (round to nearest) */ |
| 230 | - fesetround(FE_TONEAREST); | 230 | + rnd_type = float_round_nearest_even; |
| 231 | break; | 231 | break; |
| 232 | case 1: | 232 | case 1: |
| 233 | /* Smaller magnitude (round toward zero) */ | 233 | /* Smaller magnitude (round toward zero) */ |
| 234 | - fesetround(FE_TOWARDZERO); | 234 | + rnd_type = float_round_to_zero; |
| 235 | break; | 235 | break; |
| 236 | case 2: | 236 | case 2: |
| 237 | /* Round toward +infinite */ | 237 | /* Round toward +infinite */ |
| 238 | - fesetround(FE_UPWARD); | 238 | + rnd_type = float_round_up; |
| 239 | break; | 239 | break; |
| 240 | + default: | ||
| 240 | case 3: | 241 | case 3: |
| 241 | /* Round toward -infinite */ | 242 | /* Round toward -infinite */ |
| 242 | - fesetround(FE_DOWNWARD); | 243 | + rnd_type = float_round_down; |
| 243 | break; | 244 | break; |
| 244 | } | 245 | } |
| 246 | + set_float_rounding_mode(rnd_type, &env->fp_status); | ||
| 245 | } | 247 | } |
| 246 | 248 | ||
| 247 | void do_fctiw (void) | 249 | void do_fctiw (void) |
| @@ -249,16 +251,14 @@ void do_fctiw (void) | @@ -249,16 +251,14 @@ void do_fctiw (void) | ||
| 249 | union { | 251 | union { |
| 250 | double d; | 252 | double d; |
| 251 | uint64_t i; | 253 | uint64_t i; |
| 252 | - } *p = (void *)&FT1; | 254 | + } p; |
| 253 | 255 | ||
| 254 | - if (FT0 > (double)0x7FFFFFFF) | ||
| 255 | - p->i = 0x7FFFFFFFULL << 32; | ||
| 256 | - else if (FT0 < -(double)0x80000000) | ||
| 257 | - p->i = 0x80000000ULL << 32; | ||
| 258 | - else | ||
| 259 | - p->i = 0; | ||
| 260 | - p->i |= (uint32_t)FT0; | ||
| 261 | - FT0 = p->d; | 256 | + /* XXX: higher bits are not supposed to be significant. |
| 257 | + * to make tests easier, return the same as a real PPC 750 (aka G3) | ||
| 258 | + */ | ||
| 259 | + p.i = float64_to_int32(FT0, &env->fp_status); | ||
| 260 | + p.i |= 0xFFF80000ULL << 32; | ||
| 261 | + FT0 = p.d; | ||
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | void do_fctiwz (void) | 264 | void do_fctiwz (void) |
| @@ -266,39 +266,36 @@ void do_fctiwz (void) | @@ -266,39 +266,36 @@ void do_fctiwz (void) | ||
| 266 | union { | 266 | union { |
| 267 | double d; | 267 | double d; |
| 268 | uint64_t i; | 268 | uint64_t i; |
| 269 | - } *p = (void *)&FT1; | ||
| 270 | - int cround = fegetround(); | ||
| 271 | - | ||
| 272 | - fesetround(FE_TOWARDZERO); | ||
| 273 | - if (FT0 > (double)0x7FFFFFFF) | ||
| 274 | - p->i = 0x7FFFFFFFULL << 32; | ||
| 275 | - else if (FT0 < -(double)0x80000000) | ||
| 276 | - p->i = 0x80000000ULL << 32; | ||
| 277 | - else | ||
| 278 | - p->i = 0; | ||
| 279 | - p->i |= (uint32_t)FT0; | ||
| 280 | - FT0 = p->d; | ||
| 281 | - fesetround(cround); | 269 | + } p; |
| 270 | + | ||
| 271 | + /* XXX: higher bits are not supposed to be significant. | ||
| 272 | + * to make tests easier, return the same as a real PPC 750 (aka G3) | ||
| 273 | + */ | ||
| 274 | + p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status); | ||
| 275 | + p.i |= 0xFFF80000ULL << 32; | ||
| 276 | + FT0 = p.d; | ||
| 282 | } | 277 | } |
| 283 | 278 | ||
| 284 | void do_fnmadd (void) | 279 | void do_fnmadd (void) |
| 285 | { | 280 | { |
| 286 | - FT0 = -((FT0 * FT1) + FT2); | 281 | + FT0 = (FT0 * FT1) + FT2; |
| 282 | + if (!isnan(FT0)) | ||
| 283 | + FT0 = -FT0; | ||
| 287 | } | 284 | } |
| 288 | 285 | ||
| 289 | void do_fnmsub (void) | 286 | void do_fnmsub (void) |
| 290 | { | 287 | { |
| 291 | - FT0 = -((FT0 * FT1) - FT2); | 288 | + FT0 = (FT0 * FT1) - FT2; |
| 289 | + if (!isnan(FT0)) | ||
| 290 | + FT0 = -FT0; | ||
| 292 | } | 291 | } |
| 293 | 292 | ||
| 294 | -void do_fnmadds (void) | 293 | +void do_fdiv (void) |
| 295 | { | 294 | { |
| 296 | - FT0 = -((FTS0 * FTS1) + FTS2); | ||
| 297 | -} | ||
| 298 | - | ||
| 299 | -void do_fnmsubs (void) | ||
| 300 | -{ | ||
| 301 | - FT0 = -((FTS0 * FTS1) - FTS2); | 295 | + if (FT0 == -0.0 && FT1 == -0.0) |
| 296 | + FT0 = 0.0 / 0.0; | ||
| 297 | + else | ||
| 298 | + FT0 /= FT1; | ||
| 302 | } | 299 | } |
| 303 | 300 | ||
| 304 | void do_fsqrt (void) | 301 | void do_fsqrt (void) |
| @@ -306,27 +303,65 @@ void do_fsqrt (void) | @@ -306,27 +303,65 @@ void do_fsqrt (void) | ||
| 306 | FT0 = sqrt(FT0); | 303 | FT0 = sqrt(FT0); |
| 307 | } | 304 | } |
| 308 | 305 | ||
| 309 | -void do_fsqrts (void) | ||
| 310 | -{ | ||
| 311 | - FT0 = (float)sqrt((float)FT0); | ||
| 312 | -} | ||
| 313 | - | ||
| 314 | void do_fres (void) | 306 | void do_fres (void) |
| 315 | { | 307 | { |
| 316 | - FT0 = 1.0 / FT0; | 308 | + union { |
| 309 | + double d; | ||
| 310 | + uint64_t i; | ||
| 311 | + } p; | ||
| 312 | + | ||
| 313 | + if (isnormal(FT0)) { | ||
| 314 | + FT0 = (float)(1.0 / FT0); | ||
| 315 | + } else { | ||
| 316 | + p.d = FT0; | ||
| 317 | + if (p.i == 0x8000000000000000ULL) { | ||
| 318 | + p.i = 0xFFF0000000000000ULL; | ||
| 319 | + } else if (p.i == 0x0000000000000000ULL) { | ||
| 320 | + p.i = 0x7FF0000000000000ULL; | ||
| 321 | + } else if (isnan(FT0)) { | ||
| 322 | + p.i = 0x7FF8000000000000ULL; | ||
| 323 | + } else if (FT0 < 0.0) { | ||
| 324 | + p.i = 0x8000000000000000ULL; | ||
| 325 | + } else { | ||
| 326 | + p.i = 0x0000000000000000ULL; | ||
| 327 | + } | ||
| 328 | + FT0 = p.d; | ||
| 329 | + } | ||
| 317 | } | 330 | } |
| 318 | 331 | ||
| 319 | -void do_fsqrte (void) | 332 | +void do_frsqrte (void) |
| 320 | { | 333 | { |
| 321 | - FT0 = 1.0 / sqrt(FT0); | 334 | + union { |
| 335 | + double d; | ||
| 336 | + uint64_t i; | ||
| 337 | + } p; | ||
| 338 | + | ||
| 339 | + if (isnormal(FT0) && FT0 > 0.0) { | ||
| 340 | + FT0 = (float)(1.0 / sqrt(FT0)); | ||
| 341 | + } else { | ||
| 342 | + p.d = FT0; | ||
| 343 | + if (p.i == 0x8000000000000000ULL) { | ||
| 344 | + p.i = 0xFFF0000000000000ULL; | ||
| 345 | + } else if (p.i == 0x0000000000000000ULL) { | ||
| 346 | + p.i = 0x7FF0000000000000ULL; | ||
| 347 | + } else if (isnan(FT0)) { | ||
| 348 | + if (!(p.i & 0x0008000000000000ULL)) | ||
| 349 | + p.i |= 0x000FFFFFFFFFFFFFULL; | ||
| 350 | + } else if (FT0 < 0) { | ||
| 351 | + p.i = 0x7FF8000000000000ULL; | ||
| 352 | + } else { | ||
| 353 | + p.i = 0x0000000000000000ULL; | ||
| 354 | + } | ||
| 355 | + FT0 = p.d; | ||
| 356 | + } | ||
| 322 | } | 357 | } |
| 323 | 358 | ||
| 324 | void do_fsel (void) | 359 | void do_fsel (void) |
| 325 | { | 360 | { |
| 326 | if (FT0 >= 0) | 361 | if (FT0 >= 0) |
| 327 | - FT0 = FT2; | ||
| 328 | - else | ||
| 329 | FT0 = FT1; | 362 | FT0 = FT1; |
| 363 | + else | ||
| 364 | + FT0 = FT2; | ||
| 330 | } | 365 | } |
| 331 | 366 | ||
| 332 | void do_fcmpu (void) | 367 | void do_fcmpu (void) |
| @@ -371,12 +406,26 @@ void do_fcmpo (void) | @@ -371,12 +406,26 @@ void do_fcmpo (void) | ||
| 371 | 406 | ||
| 372 | void do_fabs (void) | 407 | void do_fabs (void) |
| 373 | { | 408 | { |
| 374 | - FT0 = fabsl(FT0); | 409 | + union { |
| 410 | + double d; | ||
| 411 | + uint64_t i; | ||
| 412 | + } p; | ||
| 413 | + | ||
| 414 | + p.d = FT0; | ||
| 415 | + p.i &= ~0x8000000000000000ULL; | ||
| 416 | + FT0 = p.d; | ||
| 375 | } | 417 | } |
| 376 | 418 | ||
| 377 | void do_fnabs (void) | 419 | void do_fnabs (void) |
| 378 | { | 420 | { |
| 379 | - FT0 = -fabsl(FT0); | 421 | + union { |
| 422 | + double d; | ||
| 423 | + uint64_t i; | ||
| 424 | + } p; | ||
| 425 | + | ||
| 426 | + p.d = FT0; | ||
| 427 | + p.i |= 0x8000000000000000ULL; | ||
| 428 | + FT0 = p.d; | ||
| 380 | } | 429 | } |
| 381 | 430 | ||
| 382 | /* Instruction cache invalidation helper */ | 431 | /* Instruction cache invalidation helper */ |
target-ppc/translate.c
| @@ -740,6 +740,7 @@ __GEN_LOGICAL2(sraw, 0x18, 0x18); | @@ -740,6 +740,7 @@ __GEN_LOGICAL2(sraw, 0x18, 0x18); | ||
| 740 | GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) | 740 | GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) |
| 741 | { | 741 | { |
| 742 | gen_op_load_gpr_T0(rS(ctx->opcode)); | 742 | gen_op_load_gpr_T0(rS(ctx->opcode)); |
| 743 | + if (SH(ctx->opcode) != 0) | ||
| 743 | gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31)); | 744 | gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31)); |
| 744 | if (Rc(ctx->opcode) != 0) | 745 | if (Rc(ctx->opcode) != 0) |
| 745 | gen_op_set_Rc0(); | 746 | gen_op_set_Rc0(); |
| @@ -749,7 +750,7 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) | @@ -749,7 +750,7 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) | ||
| 749 | __GEN_LOGICAL2(srw, 0x18, 0x10); | 750 | __GEN_LOGICAL2(srw, 0x18, 0x10); |
| 750 | 751 | ||
| 751 | /*** Floating-Point arithmetic ***/ | 752 | /*** Floating-Point arithmetic ***/ |
| 752 | -#define _GEN_FLOAT_ACB(name, op1, op2) \ | 753 | +#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \ |
| 753 | GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ | 754 | GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ |
| 754 | { \ | 755 | { \ |
| 755 | if (!ctx->fpu_enabled) { \ | 756 | if (!ctx->fpu_enabled) { \ |
| @@ -760,17 +761,20 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ | @@ -760,17 +761,20 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ | ||
| 760 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ | 761 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
| 761 | gen_op_load_fpr_FT1(rC(ctx->opcode)); \ | 762 | gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
| 762 | gen_op_load_fpr_FT2(rB(ctx->opcode)); \ | 763 | gen_op_load_fpr_FT2(rB(ctx->opcode)); \ |
| 763 | - gen_op_f##name(); \ | 764 | + gen_op_f##op(); \ |
| 765 | + if (isfloat) { \ | ||
| 766 | + gen_op_frsp(); \ | ||
| 767 | + } \ | ||
| 764 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ | 768 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
| 765 | if (Rc(ctx->opcode)) \ | 769 | if (Rc(ctx->opcode)) \ |
| 766 | gen_op_set_Rc1(); \ | 770 | gen_op_set_Rc1(); \ |
| 767 | } | 771 | } |
| 768 | 772 | ||
| 769 | #define GEN_FLOAT_ACB(name, op2) \ | 773 | #define GEN_FLOAT_ACB(name, op2) \ |
| 770 | -_GEN_FLOAT_ACB(name, 0x3F, op2); \ | ||
| 771 | -_GEN_FLOAT_ACB(name##s, 0x3B, op2); | 774 | +_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \ |
| 775 | +_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1); | ||
| 772 | 776 | ||
| 773 | -#define _GEN_FLOAT_AB(name, op1, op2, inval) \ | 777 | +#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \ |
| 774 | GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | 778 | GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
| 775 | { \ | 779 | { \ |
| 776 | if (!ctx->fpu_enabled) { \ | 780 | if (!ctx->fpu_enabled) { \ |
| @@ -780,16 +784,19 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | @@ -780,16 +784,19 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | ||
| 780 | gen_op_reset_scrfx(); \ | 784 | gen_op_reset_scrfx(); \ |
| 781 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ | 785 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
| 782 | gen_op_load_fpr_FT1(rB(ctx->opcode)); \ | 786 | gen_op_load_fpr_FT1(rB(ctx->opcode)); \ |
| 783 | - gen_op_f##name(); \ | 787 | + gen_op_f##op(); \ |
| 788 | + if (isfloat) { \ | ||
| 789 | + gen_op_frsp(); \ | ||
| 790 | + } \ | ||
| 784 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ | 791 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
| 785 | if (Rc(ctx->opcode)) \ | 792 | if (Rc(ctx->opcode)) \ |
| 786 | gen_op_set_Rc1(); \ | 793 | gen_op_set_Rc1(); \ |
| 787 | } | 794 | } |
| 788 | #define GEN_FLOAT_AB(name, op2, inval) \ | 795 | #define GEN_FLOAT_AB(name, op2, inval) \ |
| 789 | -_GEN_FLOAT_AB(name, 0x3F, op2, inval); \ | ||
| 790 | -_GEN_FLOAT_AB(name##s, 0x3B, op2, inval); | 796 | +_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \ |
| 797 | +_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); | ||
| 791 | 798 | ||
| 792 | -#define _GEN_FLOAT_AC(name, op1, op2, inval) \ | 799 | +#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \ |
| 793 | GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | 800 | GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
| 794 | { \ | 801 | { \ |
| 795 | if (!ctx->fpu_enabled) { \ | 802 | if (!ctx->fpu_enabled) { \ |
| @@ -799,14 +806,17 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | @@ -799,14 +806,17 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ | ||
| 799 | gen_op_reset_scrfx(); \ | 806 | gen_op_reset_scrfx(); \ |
| 800 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ | 807 | gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
| 801 | gen_op_load_fpr_FT1(rC(ctx->opcode)); \ | 808 | gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
| 802 | - gen_op_f##name(); \ | 809 | + gen_op_f##op(); \ |
| 810 | + if (isfloat) { \ | ||
| 811 | + gen_op_frsp(); \ | ||
| 812 | + } \ | ||
| 803 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ | 813 | gen_op_store_FT0_fpr(rD(ctx->opcode)); \ |
| 804 | if (Rc(ctx->opcode)) \ | 814 | if (Rc(ctx->opcode)) \ |
| 805 | gen_op_set_Rc1(); \ | 815 | gen_op_set_Rc1(); \ |
| 806 | } | 816 | } |
| 807 | #define GEN_FLOAT_AC(name, op2, inval) \ | 817 | #define GEN_FLOAT_AC(name, op2, inval) \ |
| 808 | -_GEN_FLOAT_AC(name, 0x3F, op2, inval); \ | ||
| 809 | -_GEN_FLOAT_AC(name##s, 0x3B, op2, inval); | 818 | +_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \ |
| 819 | +_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); | ||
| 810 | 820 | ||
| 811 | #define GEN_FLOAT_B(name, op2, op3) \ | 821 | #define GEN_FLOAT_B(name, op2, op3) \ |
| 812 | GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ | 822 | GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ |
| @@ -823,8 +833,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ | @@ -823,8 +833,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ | ||
| 823 | gen_op_set_Rc1(); \ | 833 | gen_op_set_Rc1(); \ |
| 824 | } | 834 | } |
| 825 | 835 | ||
| 826 | -#define GEN_FLOAT_BS(name, op2) \ | ||
| 827 | -GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ | 836 | +#define GEN_FLOAT_BS(name, op1, op2) \ |
| 837 | +GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ | ||
| 828 | { \ | 838 | { \ |
| 829 | if (!ctx->fpu_enabled) { \ | 839 | if (!ctx->fpu_enabled) { \ |
| 830 | RET_EXCP(ctx, EXCP_NO_FP, 0); \ | 840 | RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
| @@ -840,24 +850,24 @@ GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ | @@ -840,24 +850,24 @@ GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ | ||
| 840 | 850 | ||
| 841 | /* fadd - fadds */ | 851 | /* fadd - fadds */ |
| 842 | GEN_FLOAT_AB(add, 0x15, 0x000007C0); | 852 | GEN_FLOAT_AB(add, 0x15, 0x000007C0); |
| 843 | -/* fdiv */ | 853 | +/* fdiv - fdivs */ |
| 844 | GEN_FLOAT_AB(div, 0x12, 0x000007C0); | 854 | GEN_FLOAT_AB(div, 0x12, 0x000007C0); |
| 845 | -/* fmul */ | 855 | +/* fmul - fmuls */ |
| 846 | GEN_FLOAT_AC(mul, 0x19, 0x0000F800); | 856 | GEN_FLOAT_AC(mul, 0x19, 0x0000F800); |
| 847 | 857 | ||
| 848 | /* fres */ | 858 | /* fres */ |
| 849 | -GEN_FLOAT_BS(res, 0x18); | 859 | +GEN_FLOAT_BS(res, 0x3B, 0x18); |
| 850 | 860 | ||
| 851 | /* frsqrte */ | 861 | /* frsqrte */ |
| 852 | -GEN_FLOAT_BS(rsqrte, 0x1A); | 862 | +GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A); |
| 853 | 863 | ||
| 854 | /* fsel */ | 864 | /* fsel */ |
| 855 | -_GEN_FLOAT_ACB(sel, 0x3F, 0x17); | ||
| 856 | -/* fsub */ | 865 | +_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0); |
| 866 | +/* fsub - fsubs */ | ||
| 857 | GEN_FLOAT_AB(sub, 0x14, 0x000007C0); | 867 | GEN_FLOAT_AB(sub, 0x14, 0x000007C0); |
| 858 | /* Optional: */ | 868 | /* Optional: */ |
| 859 | /* fsqrt */ | 869 | /* fsqrt */ |
| 860 | -GEN_FLOAT_BS(sqrt, 0x16); | 870 | +GEN_FLOAT_BS(sqrt, 0x3F, 0x16); |
| 861 | 871 | ||
| 862 | GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) | 872 | GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) |
| 863 | { | 873 | { |
| @@ -867,20 +877,21 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) | @@ -867,20 +877,21 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) | ||
| 867 | } | 877 | } |
| 868 | gen_op_reset_scrfx(); | 878 | gen_op_reset_scrfx(); |
| 869 | gen_op_load_fpr_FT0(rB(ctx->opcode)); | 879 | gen_op_load_fpr_FT0(rB(ctx->opcode)); |
| 870 | - gen_op_fsqrts(); | 880 | + gen_op_fsqrt(); |
| 881 | + gen_op_frsp(); | ||
| 871 | gen_op_store_FT0_fpr(rD(ctx->opcode)); | 882 | gen_op_store_FT0_fpr(rD(ctx->opcode)); |
| 872 | if (Rc(ctx->opcode)) | 883 | if (Rc(ctx->opcode)) |
| 873 | gen_op_set_Rc1(); | 884 | gen_op_set_Rc1(); |
| 874 | } | 885 | } |
| 875 | 886 | ||
| 876 | /*** Floating-Point multiply-and-add ***/ | 887 | /*** Floating-Point multiply-and-add ***/ |
| 877 | -/* fmadd */ | 888 | +/* fmadd - fmadds */ |
| 878 | GEN_FLOAT_ACB(madd, 0x1D); | 889 | GEN_FLOAT_ACB(madd, 0x1D); |
| 879 | -/* fmsub */ | 890 | +/* fmsub - fmsubs */ |
| 880 | GEN_FLOAT_ACB(msub, 0x1C); | 891 | GEN_FLOAT_ACB(msub, 0x1C); |
| 881 | -/* fnmadd */ | 892 | +/* fnmadd - fnmadds */ |
| 882 | GEN_FLOAT_ACB(nmadd, 0x1F); | 893 | GEN_FLOAT_ACB(nmadd, 0x1F); |
| 883 | -/* fnmsub */ | 894 | +/* fnmsub - fnmsubs */ |
| 884 | GEN_FLOAT_ACB(nmsub, 0x1E); | 895 | GEN_FLOAT_ACB(nmsub, 0x1E); |
| 885 | 896 | ||
| 886 | /*** Floating-Point round & convert ***/ | 897 | /*** Floating-Point round & convert ***/ |
| @@ -1426,6 +1437,10 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) | @@ -1426,6 +1437,10 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) | ||
| 1426 | GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | 1437 | GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ |
| 1427 | { \ | 1438 | { \ |
| 1428 | uint32_t simm = SIMM(ctx->opcode); \ | 1439 | uint32_t simm = SIMM(ctx->opcode); \ |
| 1440 | + if (!ctx->fpu_enabled) { \ | ||
| 1441 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1442 | + return; \ | ||
| 1443 | + } \ | ||
| 1429 | if (rA(ctx->opcode) == 0) { \ | 1444 | if (rA(ctx->opcode) == 0) { \ |
| 1430 | gen_op_set_T0(simm); \ | 1445 | gen_op_set_T0(simm); \ |
| 1431 | } else { \ | 1446 | } else { \ |
| @@ -1441,6 +1456,10 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | @@ -1441,6 +1456,10 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | ||
| 1441 | GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | 1456 | GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ |
| 1442 | { \ | 1457 | { \ |
| 1443 | uint32_t simm = SIMM(ctx->opcode); \ | 1458 | uint32_t simm = SIMM(ctx->opcode); \ |
| 1459 | + if (!ctx->fpu_enabled) { \ | ||
| 1460 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1461 | + return; \ | ||
| 1462 | + } \ | ||
| 1444 | if (rA(ctx->opcode) == 0 || \ | 1463 | if (rA(ctx->opcode) == 0 || \ |
| 1445 | rA(ctx->opcode) == rD(ctx->opcode)) { \ | 1464 | rA(ctx->opcode) == rD(ctx->opcode)) { \ |
| 1446 | RET_INVAL(ctx); \ | 1465 | RET_INVAL(ctx); \ |
| @@ -1457,6 +1476,10 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | @@ -1457,6 +1476,10 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | ||
| 1457 | #define GEN_LDUXF(width, opc) \ | 1476 | #define GEN_LDUXF(width, opc) \ |
| 1458 | GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | 1477 | GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ |
| 1459 | { \ | 1478 | { \ |
| 1479 | + if (!ctx->fpu_enabled) { \ | ||
| 1480 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1481 | + return; \ | ||
| 1482 | + } \ | ||
| 1460 | if (rA(ctx->opcode) == 0 || \ | 1483 | if (rA(ctx->opcode) == 0 || \ |
| 1461 | rA(ctx->opcode) == rD(ctx->opcode)) { \ | 1484 | rA(ctx->opcode) == rD(ctx->opcode)) { \ |
| 1462 | RET_INVAL(ctx); \ | 1485 | RET_INVAL(ctx); \ |
| @@ -1473,6 +1496,10 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | @@ -1473,6 +1496,10 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | ||
| 1473 | #define GEN_LDXF(width, opc2, opc3) \ | 1496 | #define GEN_LDXF(width, opc2, opc3) \ |
| 1474 | GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ | 1497 | GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ |
| 1475 | { \ | 1498 | { \ |
| 1499 | + if (!ctx->fpu_enabled) { \ | ||
| 1500 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1501 | + return; \ | ||
| 1502 | + } \ | ||
| 1476 | if (rA(ctx->opcode) == 0) { \ | 1503 | if (rA(ctx->opcode) == 0) { \ |
| 1477 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ | 1504 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ |
| 1478 | } else { \ | 1505 | } else { \ |
| @@ -1501,6 +1528,10 @@ GEN_LDFS(fs, 0x10); | @@ -1501,6 +1528,10 @@ GEN_LDFS(fs, 0x10); | ||
| 1501 | GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | 1528 | GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ |
| 1502 | { \ | 1529 | { \ |
| 1503 | uint32_t simm = SIMM(ctx->opcode); \ | 1530 | uint32_t simm = SIMM(ctx->opcode); \ |
| 1531 | + if (!ctx->fpu_enabled) { \ | ||
| 1532 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1533 | + return; \ | ||
| 1534 | + } \ | ||
| 1504 | if (rA(ctx->opcode) == 0) { \ | 1535 | if (rA(ctx->opcode) == 0) { \ |
| 1505 | gen_op_set_T0(simm); \ | 1536 | gen_op_set_T0(simm); \ |
| 1506 | } else { \ | 1537 | } else { \ |
| @@ -1516,6 +1547,10 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | @@ -1516,6 +1547,10 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | ||
| 1516 | GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | 1547 | GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ |
| 1517 | { \ | 1548 | { \ |
| 1518 | uint32_t simm = SIMM(ctx->opcode); \ | 1549 | uint32_t simm = SIMM(ctx->opcode); \ |
| 1550 | + if (!ctx->fpu_enabled) { \ | ||
| 1551 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1552 | + return; \ | ||
| 1553 | + } \ | ||
| 1519 | if (rA(ctx->opcode) == 0) { \ | 1554 | if (rA(ctx->opcode) == 0) { \ |
| 1520 | RET_INVAL(ctx); \ | 1555 | RET_INVAL(ctx); \ |
| 1521 | return; \ | 1556 | return; \ |
| @@ -1531,6 +1566,10 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | @@ -1531,6 +1566,10 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ | ||
| 1531 | #define GEN_STUXF(width, opc) \ | 1566 | #define GEN_STUXF(width, opc) \ |
| 1532 | GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | 1567 | GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ |
| 1533 | { \ | 1568 | { \ |
| 1569 | + if (!ctx->fpu_enabled) { \ | ||
| 1570 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1571 | + return; \ | ||
| 1572 | + } \ | ||
| 1534 | if (rA(ctx->opcode) == 0) { \ | 1573 | if (rA(ctx->opcode) == 0) { \ |
| 1535 | RET_INVAL(ctx); \ | 1574 | RET_INVAL(ctx); \ |
| 1536 | return; \ | 1575 | return; \ |
| @@ -1546,6 +1585,10 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | @@ -1546,6 +1585,10 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ | ||
| 1546 | #define GEN_STXF(width, opc2, opc3) \ | 1585 | #define GEN_STXF(width, opc2, opc3) \ |
| 1547 | GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ | 1586 | GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ |
| 1548 | { \ | 1587 | { \ |
| 1588 | + if (!ctx->fpu_enabled) { \ | ||
| 1589 | + RET_EXCP(ctx, EXCP_NO_FP, 0); \ | ||
| 1590 | + return; \ | ||
| 1591 | + } \ | ||
| 1549 | if (rA(ctx->opcode) == 0) { \ | 1592 | if (rA(ctx->opcode) == 0) { \ |
| 1550 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ | 1593 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ |
| 1551 | } else { \ | 1594 | } else { \ |