Commit 4ecc31906d7535c4ad88fcc63968bef412dd67ba

Authored by bellard
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
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 { \