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 { \ |