43 |
|
* FDBcc: |
44 |
|
* The loop termination condition was wrong. |
45 |
|
* Possible leak from int16 to int32 fixed. |
46 |
< |
* Now fpcr high 16 bits are always read as zeores, no matter what was |
46 |
> |
* get_fp_value: |
47 |
> |
* Immediate addressing mode && Operation Length == Byte -> |
48 |
> |
* Use the low-order byte of the extension word. |
49 |
> |
* Now fpcr high 16 bits are always read as zeroes, no matter what was |
50 |
|
* written to them. |
51 |
|
* |
52 |
|
* Other: |
74 |
|
#include "memory.h" |
75 |
|
#include "readcpu.h" |
76 |
|
#include "newcpu.h" |
77 |
+ |
#include "main.h" |
78 |
|
|
79 |
|
#define DEBUG 0 |
80 |
|
#include "debug.h" |
83 |
|
// Only define if you have IEEE 64 bit doubles. |
84 |
|
#define HAVE_IEEE_DOUBLE 1 |
85 |
|
|
86 |
+ |
#ifdef WORDS_BIGENDIAN |
87 |
+ |
#define FLO 1 |
88 |
+ |
#define FHI 0 |
89 |
+ |
#else |
90 |
+ |
#define FLO 0 |
91 |
+ |
#define FHI 1 |
92 |
+ |
#endif |
93 |
+ |
|
94 |
|
// fpcr rounding modes |
95 |
|
#define ROUND_TO_NEAREST 0 |
96 |
|
#define ROUND_TO_ZERO 0x10 |
185 |
|
|
186 |
|
static __inline__ uae_u32 IS_NAN(uae_u32 *p) |
187 |
|
{ |
188 |
< |
if( (p[1] & 0x7FF00000) == 0x7FF00000 ) { |
188 |
> |
if( (p[FHI] & 0x7FF00000) == 0x7FF00000 ) { |
189 |
|
// logical or is faster here. |
190 |
< |
if( (p[1] & 0x000FFFFF) || p[0] ) { |
190 |
> |
if( (p[FHI] & 0x000FFFFF) || p[FLO] ) { |
191 |
|
return(1); |
192 |
|
} |
193 |
|
} |
196 |
|
|
197 |
|
static __inline__ uae_u32 IS_INFINITY(uae_u32 *p) |
198 |
|
{ |
199 |
< |
if( ((p[1] & 0x7FF00000) == 0x7FF00000) && p[0] == 0 ) { |
199 |
> |
if( ((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0 ) { |
200 |
|
return(1); |
201 |
|
} |
202 |
|
return(0); |
204 |
|
|
205 |
|
static __inline__ uae_u32 IS_NEGATIVE(uae_u32 *p) |
206 |
|
{ |
207 |
< |
return( (p[1] & 0x80000000) != 0 ); |
207 |
> |
return( (p[FHI] & 0x80000000) != 0 ); |
208 |
|
} |
209 |
|
|
210 |
|
static __inline__ uae_u32 IS_ZERO(uae_u32 *p) |
211 |
|
{ |
212 |
< |
return( ((p[1] & 0x7FF00000) == 0) && p[0] == 0 ); |
212 |
> |
return( ((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0 ); |
213 |
|
} |
214 |
|
|
215 |
|
// This should not touch the quotient. |
248 |
|
|
249 |
|
static __inline__ void MAKE_NAN(uae_u32 *p) |
250 |
|
{ |
251 |
< |
p[0] = 0xFFFFFFFF; |
252 |
< |
p[1] = 0x7FFFFFFF; |
251 |
> |
p[FLO] = 0xFFFFFFFF; |
252 |
> |
p[FHI] = 0x7FFFFFFF; |
253 |
|
} |
254 |
|
|
255 |
|
static __inline__ void MAKE_ZERO_POSITIVE(uae_u32 *p) |
256 |
|
{ |
257 |
< |
p[0] = p[1] = 0; |
257 |
> |
p[FLO] = p[FHI] = 0; |
258 |
|
} |
259 |
|
|
260 |
|
static __inline__ void MAKE_ZERO_NEGATIVE(uae_u32 *p) |
261 |
|
{ |
262 |
< |
p[0] = 0; |
263 |
< |
p[1] = 0x80000000; |
262 |
> |
p[FLO] = 0; |
263 |
> |
p[FHI] = 0x80000000; |
264 |
|
} |
265 |
|
|
266 |
|
static __inline__ void MAKE_INF_POSITIVE(uae_u32 *p) |
267 |
|
{ |
268 |
< |
p[0] = 0; |
269 |
< |
p[1] = 0x7FF00000; |
268 |
> |
p[FLO] = 0; |
269 |
> |
p[FHI] = 0x7FF00000; |
270 |
|
} |
271 |
|
|
272 |
|
static __inline__ void MAKE_INF_NEGATIVE(uae_u32 *p) |
273 |
|
{ |
274 |
< |
p[0] = 0; |
275 |
< |
p[1] = 0xFFF00000; |
274 |
> |
p[FLO] = 0; |
275 |
> |
p[FHI] = 0xFFF00000; |
276 |
|
} |
277 |
|
|
278 |
|
static __inline__ void FAST_SCALE(uae_u32 *p, int add) |
279 |
|
{ |
280 |
|
int exp; |
281 |
|
|
282 |
< |
exp = (p[1] & 0x7FF00000) >> 20; |
282 |
> |
exp = (p[FHI] & 0x7FF00000) >> 20; |
283 |
|
// TODO: overflow flags |
284 |
|
exp += add; |
285 |
|
if(exp >= 2047) { |
286 |
|
MAKE_INF_POSITIVE(p); |
287 |
|
} else if(exp < 0) { |
288 |
|
// keep sign (+/- 0) |
289 |
< |
p[1] &= 0x80000000; |
289 |
> |
p[FHI] &= 0x80000000; |
290 |
|
} else { |
291 |
< |
p[1] = (p[1] & 0x800FFFFF) | ((uae_u32)exp << 20); |
291 |
> |
p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); |
292 |
|
} |
293 |
|
} |
294 |
|
|
295 |
|
static __inline__ double FAST_FGETEXP(uae_u32 *p) |
296 |
|
{ |
297 |
< |
int exp = (p[1] & 0x7FF00000) >> 20; |
297 |
> |
int exp = (p[FHI] & 0x7FF00000) >> 20; |
298 |
|
return( exp - 1023 ); |
299 |
|
} |
300 |
|
|
301 |
|
// Normalize to range 1..2 |
302 |
|
static __inline__ void FAST_REMOVE_EXPONENT(uae_u32 *p) |
303 |
|
{ |
304 |
< |
p[1] = (p[1] & 0x800FFFFF) | 0x3FF00000; |
304 |
> |
p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; |
305 |
|
} |
306 |
|
|
307 |
|
// The sign of the quotient is the exclusive-OR of the sign bits |
308 |
|
// of the source and destination operands. |
309 |
|
static __inline__ uae_u32 GET_QUOTIENT_SIGN(uae_u32 *a, uae_u32 *b) |
310 |
|
{ |
311 |
< |
return( ((a[1] ^ b[1]) & 0x80000000) ? 0x800000 : 0); |
311 |
> |
return( ((a[FHI] ^ b[FHI]) & 0x80000000) ? 0x800000 : 0); |
312 |
|
} |
313 |
|
|
314 |
|
// Quotient Byte is loaded with the sign and least significant |
331 |
|
uae_u32 sign = (value & 0x80000000); |
332 |
|
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; |
333 |
|
|
334 |
< |
p[0] = value << 29; |
335 |
< |
p[1] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); |
334 |
> |
p[FLO] = value << 29; |
335 |
> |
p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); |
336 |
|
|
337 |
|
D(bug("to_single (%X) = %.04f\r\n",value,(float)result)); |
338 |
|
|
346 |
|
|
347 |
|
if (src == 0.0) return 0; |
348 |
|
|
349 |
< |
uae_u32 sign = (p[1] & 0x80000000); |
350 |
< |
uae_u32 exp = (p[1] & 0x7FF00000) >> 20; |
349 |
> |
uae_u32 sign = (p[FHI] & 0x80000000); |
350 |
> |
uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; |
351 |
|
|
352 |
|
if(exp + 127 < 1023) { |
353 |
|
exp = 0; |
357 |
|
exp = exp + 127 - 1023; |
358 |
|
} |
359 |
|
|
360 |
< |
result = sign | (exp << 23) | ((p[1] & 0x000FFFFF) << 3) | (p[0] >> 29); |
360 |
> |
result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); |
361 |
|
|
362 |
|
D(bug("from_single (%.04f) = %X\r\n",(float)src,result)); |
363 |
|
|
380 |
|
if( wrd2 | wrd3 ) { |
381 |
|
// mantissa, not fraction. |
382 |
|
uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; |
383 |
< |
while( (man & UVAL64(0x8000000000000000)) == 0 ) { |
383 |
> |
while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { |
384 |
|
man <<= 1; |
385 |
|
exp--; |
386 |
|
} |
407 |
|
} |
408 |
|
|
409 |
|
// drop the explicit integer bit. |
410 |
< |
p[0] = (wrd2 << 21) | (wrd3 >> 11); |
411 |
< |
p[1] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); |
410 |
> |
p[FLO] = (wrd2 << 21) | (wrd3 >> 11); |
411 |
> |
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); |
412 |
|
|
413 |
|
D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result)); |
414 |
|
|
415 |
|
return(result); |
416 |
|
} |
417 |
|
|
418 |
+ |
/* |
419 |
+ |
Would be so much easier with full size floats :( |
420 |
+ |
... this is so vague. |
421 |
+ |
*/ |
422 |
+ |
static __inline__ void to_exten_no_normalize( |
423 |
+ |
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, uae_u32 *p |
424 |
+ |
) |
425 |
+ |
{ |
426 |
+ |
// double result; |
427 |
+ |
// uae_u32 *p = (uae_u32 *)&result; |
428 |
+ |
|
429 |
+ |
// Is it zero? |
430 |
+ |
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { |
431 |
+ |
MAKE_ZERO_POSITIVE(p); |
432 |
+ |
return; |
433 |
+ |
} |
434 |
+ |
|
435 |
+ |
// Is it NaN? |
436 |
+ |
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { |
437 |
+ |
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { |
438 |
+ |
MAKE_NAN( p ); |
439 |
+ |
return; |
440 |
+ |
} |
441 |
+ |
} |
442 |
+ |
|
443 |
+ |
uae_u32 sign = wrd1 & 0x80000000; |
444 |
+ |
uae_u32 exp = (wrd1 >> 16) & 0x7fff; |
445 |
+ |
|
446 |
+ |
if(exp < 16383 - 1023) { |
447 |
+ |
// should set underflow. |
448 |
+ |
exp = 0; |
449 |
+ |
} else if(exp > 16383 + 1023) { |
450 |
+ |
// should set overflow. |
451 |
+ |
exp = 2047; |
452 |
+ |
} else { |
453 |
+ |
exp = exp + 1023 - 16383; |
454 |
+ |
} |
455 |
+ |
|
456 |
+ |
// drop the explicit integer bit. |
457 |
+ |
p[FLO] = (wrd2 << 21) | (wrd3 >> 11); |
458 |
+ |
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); |
459 |
+ |
|
460 |
+ |
D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); |
461 |
+ |
|
462 |
+ |
// return(result); |
463 |
+ |
} |
464 |
+ |
|
465 |
|
static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) |
466 |
|
{ |
467 |
|
uae_u32 *p = (uae_u32 *)&src; |
471 |
|
return; |
472 |
|
} |
473 |
|
|
474 |
< |
D(bug("from_exten (%X,%X)\r\n",p[0],p[1])); |
474 |
> |
D(bug("from_exten (%X,%X)\r\n",p[FLO],p[FHI])); |
475 |
|
|
476 |
< |
uae_u32 sign = p[1] & 0x80000000; |
476 |
> |
uae_u32 sign = p[FHI] & 0x80000000; |
477 |
|
|
478 |
< |
uae_u32 exp = ((p[1] >> 20) & 0x7ff); |
478 |
> |
uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); |
479 |
|
// Check for maximum |
480 |
|
if(exp == 0x7FF) { |
481 |
|
exp = 0x7FFF; |
485 |
|
|
486 |
|
*wrd1 = sign | (exp << 16); |
487 |
|
// always set the explicit integer bit. |
488 |
< |
*wrd2 = 0x80000000 | ((p[1] & 0x000FFFFF) << 11) | ((p[0] & 0xFFE00000) >> 21); |
489 |
< |
*wrd3 = p[0] << 11; |
488 |
> |
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); |
489 |
> |
*wrd3 = p[FLO] << 11; |
490 |
|
|
491 |
|
D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); |
492 |
|
} |
499 |
|
if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0; |
500 |
|
|
501 |
|
p = (uae_u32 *)&result; |
502 |
< |
p[0] = wrd2; |
503 |
< |
p[1] = wrd1; |
502 |
> |
p[FLO] = wrd2; |
503 |
> |
p[FHI] = wrd1; |
504 |
|
|
505 |
|
D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result)); |
506 |
|
|
509 |
|
|
510 |
|
static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2) |
511 |
|
{ |
512 |
+ |
/* |
513 |
|
if (src == 0.0) { |
514 |
|
*wrd1 = *wrd2 = 0; |
515 |
|
return; |
516 |
|
} |
517 |
+ |
*/ |
518 |
|
uae_u32 *p = (uae_u32 *)&src; |
519 |
< |
*wrd2 = p[0]; |
520 |
< |
*wrd1 = p[1]; |
519 |
> |
*wrd2 = p[FLO]; |
520 |
> |
*wrd1 = p[FHI]; |
521 |
|
|
522 |
|
D(bug("from_double (%.04f) = %X,%X\r\n",(float)src,*wrd1,*wrd2)); |
523 |
|
} |
853 |
|
case 4: |
854 |
|
ad = m68k_getpc (); |
855 |
|
m68k_setpc (ad + sz2[size]); |
856 |
+ |
// Immediate addressing mode && Operation Length == Byte -> |
857 |
+ |
// Use the low-order byte of the extension word. |
858 |
+ |
if(size == 6) ad++; |
859 |
|
break; |
860 |
|
default: |
861 |
|
return 0; |
927 |
|
int mode; |
928 |
|
int reg; |
929 |
|
uae_u32 ad; |
930 |
< |
static int sz1[8] = |
931 |
< |
{4, 4, 12, 12, 2, 8, 1, 0}; |
868 |
< |
static int sz2[8] = |
869 |
< |
{4, 4, 12, 12, 2, 8, 2, 0}; |
930 |
> |
static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; |
931 |
> |
static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; |
932 |
|
|
933 |
|
// D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra)); |
934 |
|
|
1108 |
|
return 1; |
1109 |
|
} |
1110 |
|
|
1111 |
< |
static __inline__ int fpp_cond(uae_u32 opcode, int contition) |
1111 |
> |
static __inline__ int fpp_cond(uae_u32 opcode, int condition) |
1112 |
|
{ |
1113 |
< |
int N = (regs.fpsr & 0x8000000) != 0; |
1114 |
< |
int Z = (regs.fpsr & 0x4000000) != 0; |
1115 |
< |
/* int I = (regs.fpsr & 0x2000000) != 0; */ |
1116 |
< |
int NotANumber = (regs.fpsr & 0x1000000) != 0; |
1113 |
> |
#define N ((regs.fpsr & 0x8000000) != 0) |
1114 |
> |
#define Z ((regs.fpsr & 0x4000000) != 0) |
1115 |
> |
#define I ((regs.fpsr & 0x2000000) != 0) |
1116 |
> |
#define NotANumber ((regs.fpsr & 0x1000000) != 0) |
1117 |
|
|
1118 |
< |
switch (contition) { |
1118 |
> |
switch (condition) { |
1119 |
|
case 0x00: |
1120 |
|
CONDRET("False",0); |
1121 |
|
case 0x01: |
1181 |
|
CONDRET("Signaling Not Equal",!Z); |
1182 |
|
case 0x1f: |
1183 |
|
CONDRET("Signaling True",1); |
1184 |
+ |
default: |
1185 |
+ |
CONDRET("",-1); |
1186 |
|
} |
1187 |
< |
CONDRET("",-1); |
1187 |
> |
#undef N |
1188 |
> |
#undef Z |
1189 |
> |
#undef I |
1190 |
> |
#undef NotANumber |
1191 |
|
} |
1192 |
|
|
1193 |
< |
void fdbcc_opp(uae_u32 opcode, uae_u16 extra) |
1193 |
> |
void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra) |
1194 |
|
{ |
1195 |
|
uaecptr pc = (uae_u32) m68k_getpc (); |
1196 |
|
uae_s32 disp = (uae_s32) (uae_s16) next_iword(); |
1221 |
|
} |
1222 |
|
} |
1223 |
|
|
1224 |
< |
void fscc_opp(uae_u32 opcode, uae_u16 extra) |
1224 |
> |
void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra) |
1225 |
|
{ |
1226 |
|
uae_u32 ad; |
1227 |
|
int cc; |
1244 |
|
} |
1245 |
|
} |
1246 |
|
|
1247 |
< |
void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) |
1247 |
> |
void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) |
1248 |
|
{ |
1249 |
|
int cc; |
1250 |
|
|
1260 |
|
} |
1261 |
|
|
1262 |
|
// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) |
1263 |
< |
void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) |
1263 |
> |
void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) |
1264 |
|
{ |
1265 |
|
int cc; |
1266 |
|
|
1279 |
|
|
1280 |
|
// FSAVE has no post-increment |
1281 |
|
// 0x1f180000 == IDLE state frame, coprocessor version number 1F |
1282 |
< |
void fsave_opp(uae_u32 opcode) |
1282 |
> |
void REGPARAM2 fsave_opp(uae_u32 opcode) |
1283 |
|
{ |
1284 |
|
uae_u32 ad; |
1285 |
|
int incr = (opcode & 0x38) == 0x20 ? -1 : 1; |
1293 |
|
return; |
1294 |
|
} |
1295 |
|
|
1296 |
< |
// Put 28 byte IDLE frame. |
1297 |
< |
// NOTE!!! IDLE frame is only 4 bytes on a 68040!! |
1298 |
< |
|
1299 |
< |
if (incr < 0) { |
1300 |
< |
D(bug("fsave_opp pre-decrement\r\n")); |
1301 |
< |
ad -= 4; |
1302 |
< |
// What's this? Some BIU flags, or (incorrectly placed) command/condition? |
1303 |
< |
put_long (ad, 0x70000000); |
1237 |
< |
for (i = 0; i < 5; i++) { |
1238 |
< |
ad -= 4; |
1239 |
< |
put_long (ad, 0x00000000); |
1240 |
< |
} |
1241 |
< |
ad -= 4; |
1242 |
< |
put_long (ad, 0x1f180000); // IDLE, vers 1f |
1243 |
< |
} else { |
1244 |
< |
put_long (ad, 0x1f180000); // IDLE, vers 1f |
1245 |
< |
ad += 4; |
1246 |
< |
for (i = 0; i < 5; i++) { |
1247 |
< |
put_long (ad, 0x00000000); |
1248 |
< |
ad += 4; |
1296 |
> |
if (CPUType == 4) { |
1297 |
> |
// Put 4 byte 68040 IDLE frame. |
1298 |
> |
if (incr < 0) { |
1299 |
> |
ad -= 4; |
1300 |
> |
put_long (ad, 0x41000000); |
1301 |
> |
} else { |
1302 |
> |
put_long (ad, 0x41000000); |
1303 |
> |
ad += 4; |
1304 |
|
} |
1305 |
< |
// What's this? Some BIU flags, or (incorrectly placed) command/condition? |
1306 |
< |
put_long (ad, 0x70000000); |
1307 |
< |
ad += 4; |
1308 |
< |
} |
1305 |
> |
} else { |
1306 |
> |
// Put 28 byte 68881 IDLE frame. |
1307 |
> |
if (incr < 0) { |
1308 |
> |
D(bug("fsave_opp pre-decrement\r\n")); |
1309 |
> |
ad -= 4; |
1310 |
> |
// What's this? Some BIU flags, or (incorrectly placed) command/condition? |
1311 |
> |
put_long (ad, 0x70000000); |
1312 |
> |
for (i = 0; i < 5; i++) { |
1313 |
> |
ad -= 4; |
1314 |
> |
put_long (ad, 0x00000000); |
1315 |
> |
} |
1316 |
> |
ad -= 4; |
1317 |
> |
put_long (ad, 0x1f180000); // IDLE, vers 1f |
1318 |
> |
} else { |
1319 |
> |
put_long (ad, 0x1f180000); // IDLE, vers 1f |
1320 |
> |
ad += 4; |
1321 |
> |
for (i = 0; i < 5; i++) { |
1322 |
> |
put_long (ad, 0x00000000); |
1323 |
> |
ad += 4; |
1324 |
> |
} |
1325 |
> |
// What's this? Some BIU flags, or (incorrectly placed) command/condition? |
1326 |
> |
put_long (ad, 0x70000000); |
1327 |
> |
ad += 4; |
1328 |
> |
} |
1329 |
> |
} |
1330 |
|
if ((opcode & 0x38) == 0x18) { |
1331 |
|
m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 |
1332 |
|
D(bug("PROBLEM: fsave_opp post-increment\r\n")); |
1337 |
|
} |
1338 |
|
} |
1339 |
|
|
1340 |
< |
// FSAVE has no pre-decrement |
1341 |
< |
void frestore_opp(uae_u32 opcode) |
1340 |
> |
// FRESTORE has no pre-decrement |
1341 |
> |
void REGPARAM2 frestore_opp(uae_u32 opcode) |
1342 |
|
{ |
1343 |
|
uae_u32 ad; |
1344 |
|
uae_u32 d; |
1352 |
|
return; |
1353 |
|
} |
1354 |
|
|
1355 |
< |
if (incr < 0) { |
1356 |
< |
|
1357 |
< |
D(bug("PROBLEM: frestore_opp incr < 0\r\n")); |
1358 |
< |
|
1359 |
< |
// this may be wrong, but it's never called. |
1360 |
< |
ad -= 4; |
1361 |
< |
d = get_long (ad); |
1362 |
< |
if ((d & 0xff000000) != 0) { |
1363 |
< |
if ((d & 0x00ff0000) == 0x00180000) |
1364 |
< |
ad -= 6 * 4; |
1365 |
< |
else if ((d & 0x00ff0000) == 0x00380000) |
1366 |
< |
ad -= 14 * 4; |
1367 |
< |
else if ((d & 0x00ff0000) == 0x00b40000) |
1368 |
< |
ad -= 45 * 4; |
1355 |
> |
if (CPUType == 4) { |
1356 |
> |
// 68040 |
1357 |
> |
if (incr < 0) { |
1358 |
> |
D(bug("PROBLEM: frestore_opp incr < 0\r\n")); |
1359 |
> |
// this may be wrong, but it's never called. |
1360 |
> |
ad -= 4; |
1361 |
> |
d = get_long (ad); |
1362 |
> |
if ((d & 0xff000000) != 0) { // Not a NULL frame? |
1363 |
> |
if ((d & 0x00ff0000) == 0) { // IDLE |
1364 |
> |
D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); |
1365 |
> |
} else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP |
1366 |
> |
D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); |
1367 |
> |
ad -= 44; |
1368 |
> |
} else if ((d & 0x00ff0000) == 0x00600000) { // BUSY |
1369 |
> |
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); |
1370 |
> |
ad -= 92; |
1371 |
> |
} |
1372 |
> |
} |
1373 |
> |
} else { |
1374 |
> |
d = get_long (ad); |
1375 |
> |
D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); |
1376 |
> |
ad += 4; |
1377 |
> |
if ((d & 0xff000000) != 0) { // Not a NULL frame? |
1378 |
> |
if ((d & 0x00ff0000) == 0) { // IDLE |
1379 |
> |
D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); |
1380 |
> |
} else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP |
1381 |
> |
D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); |
1382 |
> |
ad += 44; |
1383 |
> |
} else if ((d & 0x00ff0000) == 0x00600000) { // BUSY |
1384 |
> |
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); |
1385 |
> |
ad += 92; |
1386 |
> |
} |
1387 |
> |
} |
1388 |
|
} |
1389 |
< |
} else { |
1390 |
< |
d = get_long (ad); |
1391 |
< |
|
1392 |
< |
D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); |
1393 |
< |
|
1394 |
< |
ad += 4; |
1395 |
< |
if ((d & 0xff000000) != 0) { // Not a NULL frame? |
1396 |
< |
if ((d & 0x00ff0000) == 0x00180000) { // IDLE |
1397 |
< |
D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); |
1398 |
< |
ad += 6 * 4; |
1399 |
< |
} else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? |
1400 |
< |
ad += 14 * 4; |
1401 |
< |
D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); |
1402 |
< |
} else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY |
1403 |
< |
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); |
1404 |
< |
ad += 45 * 4; |
1389 |
> |
} else { |
1390 |
> |
// 68881 |
1391 |
> |
if (incr < 0) { |
1392 |
> |
D(bug("PROBLEM: frestore_opp incr < 0\r\n")); |
1393 |
> |
// this may be wrong, but it's never called. |
1394 |
> |
ad -= 4; |
1395 |
> |
d = get_long (ad); |
1396 |
> |
if ((d & 0xff000000) != 0) { |
1397 |
> |
if ((d & 0x00ff0000) == 0x00180000) |
1398 |
> |
ad -= 6 * 4; |
1399 |
> |
else if ((d & 0x00ff0000) == 0x00380000) |
1400 |
> |
ad -= 14 * 4; |
1401 |
> |
else if ((d & 0x00ff0000) == 0x00b40000) |
1402 |
> |
ad -= 45 * 4; |
1403 |
> |
} |
1404 |
> |
} else { |
1405 |
> |
d = get_long (ad); |
1406 |
> |
D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); |
1407 |
> |
ad += 4; |
1408 |
> |
if ((d & 0xff000000) != 0) { // Not a NULL frame? |
1409 |
> |
if ((d & 0x00ff0000) == 0x00180000) { // IDLE |
1410 |
> |
D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); |
1411 |
> |
ad += 6 * 4; |
1412 |
> |
} else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? |
1413 |
> |
ad += 14 * 4; |
1414 |
> |
D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); |
1415 |
> |
} else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY |
1416 |
> |
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); |
1417 |
> |
ad += 45 * 4; |
1418 |
> |
} |
1419 |
|
} |
1420 |
|
} |
1421 |
|
} |
1667 |
|
uae_u32 wrd1, wrd2, wrd3; |
1668 |
|
if( list & 0x80 ) { |
1669 |
|
from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3); |
1670 |
< |
put_long (ad, wrd3); |
1670 |
> |
put_long (ad, wrd1); |
1671 |
|
ad += 4; |
1672 |
|
put_long (ad, wrd2); |
1673 |
|
ad += 4; |
1674 |
< |
put_long (ad, wrd1); |
1674 |
> |
put_long (ad, wrd3); |
1675 |
|
ad += 4; |
1676 |
|
} |
1677 |
|
list <<= 1; |
1678 |
|
} |
1679 |
|
} |
1680 |
|
|
1572 |
– |
/* |
1573 |
– |
while (list) { |
1574 |
– |
uae_u32 wrd1, wrd2, wrd3; |
1575 |
– |
if (incr < 0) { |
1576 |
– |
from_exten(regs.fp[fpp_movem_index2[list]], |
1577 |
– |
&wrd1, &wrd2, &wrd3); |
1578 |
– |
ad -= 4; |
1579 |
– |
put_long (ad, wrd3); |
1580 |
– |
ad -= 4; |
1581 |
– |
put_long (ad, wrd2); |
1582 |
– |
ad -= 4; |
1583 |
– |
put_long (ad, wrd1); |
1584 |
– |
} else { |
1585 |
– |
from_exten(regs.fp[fpp_movem_index1[list]], |
1586 |
– |
&wrd1, &wrd2, &wrd3); |
1587 |
– |
put_long (ad, wrd1); |
1588 |
– |
ad += 4; |
1589 |
– |
put_long (ad, wrd2); |
1590 |
– |
ad += 4; |
1591 |
– |
put_long (ad, wrd3); |
1592 |
– |
ad += 4; |
1593 |
– |
} |
1594 |
– |
list = fpp_movem_next[list]; |
1595 |
– |
} |
1596 |
– |
*/ |
1681 |
|
if ((opcode & 0x38) == 0x18) // post-increment? |
1682 |
|
m68k_areg (regs, opcode & 7) = ad; |
1683 |
|
if ((opcode & 0x38) == 0x20) // pre-decrement? |
1720 |
|
for(reg=7; reg>=0; reg--) { |
1721 |
|
uae_u32 wrd1, wrd2, wrd3; |
1722 |
|
if( list & 0x80 ) { |
1639 |
– |
wrd1 = get_long (ad); |
1640 |
– |
ad -= 4; |
1641 |
– |
wrd2 = get_long (ad); |
1723 |
|
ad -= 4; |
1724 |
|
wrd3 = get_long (ad); |
1725 |
|
ad -= 4; |
1726 |
< |
regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); |
1726 |
> |
wrd2 = get_long (ad); |
1727 |
> |
ad -= 4; |
1728 |
> |
wrd1 = get_long (ad); |
1729 |
> |
// regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); |
1730 |
> |
to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)®s.fp[reg]); |
1731 |
|
} |
1732 |
|
list <<= 1; |
1733 |
|
} |
1741 |
|
ad += 4; |
1742 |
|
wrd3 = get_long (ad); |
1743 |
|
ad += 4; |
1744 |
< |
regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); |
1744 |
> |
// regs.fp[reg] = to_exten (wrd1, wrd2, wrd3); |
1745 |
> |
to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)®s.fp[reg]); |
1746 |
|
} |
1747 |
|
list <<= 1; |
1748 |
|
} |
1749 |
|
} |
1664 |
– |
/**/ |
1665 |
– |
|
1666 |
– |
/* |
1667 |
– |
while (list) { |
1668 |
– |
uae_u32 wrd1, wrd2, wrd3; |
1669 |
– |
if (incr < 0) { |
1670 |
– |
ad -= 4; |
1671 |
– |
wrd3 = get_long (ad); |
1672 |
– |
ad -= 4; |
1673 |
– |
wrd2 = get_long (ad); |
1674 |
– |
ad -= 4; |
1675 |
– |
wrd1 = get_long (ad); |
1676 |
– |
regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3); |
1677 |
– |
} else { |
1678 |
– |
wrd1 = get_long (ad); |
1679 |
– |
ad += 4; |
1680 |
– |
wrd2 = get_long (ad); |
1681 |
– |
ad += 4; |
1682 |
– |
wrd3 = get_long (ad); |
1683 |
– |
ad += 4; |
1684 |
– |
regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3); |
1685 |
– |
} |
1686 |
– |
list = fpp_movem_next[list]; |
1687 |
– |
} |
1688 |
– |
*/ |
1750 |
|
if ((opcode & 0x38) == 0x18) // post-increment? |
1751 |
|
m68k_areg (regs, opcode & 7) = ad; |
1752 |
|
if ((opcode & 0x38) == 0x20) // pre-decrement? |
1877 |
|
dump_fp_regs( "END "); |
1878 |
|
return; |
1879 |
|
} |
1880 |
+ |
D(bug("returned from get_fp_value m68k_getpc()=%X\r\n",m68k_getpc())); |
1881 |
|
|
1882 |
|
switch (extra & 0x7f) { |
1883 |
|
case 0x00: /* FMOVE */ |
1996 |
|
MAKE_FPSR(regs.fpsr,regs.fp[reg]); |
1997 |
|
break; |
1998 |
|
case 0x18: /* FABS */ |
1999 |
+ |
case 0x58: /* single precision rounding */ |
2000 |
+ |
case 0x5C: /* double precision rounding */ |
2001 |
|
D(bug("FABS %.04f\r\n",(float)src)); |
2002 |
|
regs.fp[reg] = src < 0 ? -src : src; |
2003 |
|
MAKE_FPSR(regs.fpsr,regs.fp[reg]); |
2080 |
|
} |
2081 |
|
break; |
2082 |
|
case 0x22: /* FADD */ |
2083 |
+ |
case 0x62: /* single */ |
2084 |
+ |
case 0x66: /* double */ |
2085 |
|
D(bug("FADD %.04f\r\n",(float)src)); |
2086 |
|
regs.fp[reg] += src; |
2087 |
|
MAKE_FPSR(regs.fpsr,regs.fp[reg]); |
2088 |
|
break; |
2089 |
|
case 0x23: /* FMUL */ |
2090 |
|
D(bug("FMUL %.04f\r\n",(float)src)); |
2091 |
+ |
#if HAVE_IEEE_DOUBLE |
2092 |
|
GET_DEST_FLAGS((uae_u32 *)®s.fp[reg]); |
2093 |
|
GET_SOURCE_FLAGS((uae_u32 *)&src); |
2094 |
|
if(fl_dest.in_range && fl_source.in_range) { |
2115 |
|
MAKE_INF_POSITIVE((uae_u32 *)®s.fp[reg]); |
2116 |
|
} |
2117 |
|
} |
2118 |
+ |
#else |
2119 |
+ |
D(bug("FMUL %.04f\r\n",(float)src)); |
2120 |
+ |
regs.fp[reg] *= src; |
2121 |
+ |
#endif |
2122 |
|
MAKE_FPSR(regs.fpsr,regs.fp[reg]); |
2123 |
|
break; |
2124 |
|
case 0x24: /* FSGLDIV */ |
2223 |
|
} |
2224 |
|
} else { |
2225 |
|
double tmp = regs.fp[reg] - src; |
2226 |
< |
regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); |
2226 |
> |
// regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); |
2227 |
> |
regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); |
2228 |
|
} |
2229 |
|
#else |
2230 |
|
{ |
2244 |
|
op_illg (opcode); |
2245 |
|
break; |
2246 |
|
} |
2247 |
+ |
D(bug("END m68k_getpc()=%X\r\n",m68k_getpc())); |
2248 |
|
dump_fp_regs( "END "); |
2249 |
|
return; |
2250 |
|
} |
2253 |
|
op_illg (opcode); |
2254 |
|
dump_fp_regs( "END "); |
2255 |
|
} |
2256 |
+ |
|
2257 |
+ |
/* -------------------------- Initialization -------------------------- */ |
2258 |
+ |
|
2259 |
+ |
void fpu_set_integral_fpu (bool is_integral) |
2260 |
+ |
{ |
2261 |
+ |
D(bug("fpu_set_integral_fpu : %s\n", (is_integral ? "yes" : "no"))); |
2262 |
+ |
} |
2263 |
+ |
|
2264 |
+ |
void fpu_init (void) |
2265 |
+ |
{ |
2266 |
+ |
D(bug("fpu_init\n")); |
2267 |
+ |
regs.fpcr = regs.fpsr = regs.fpiar = 0; |
2268 |
+ |
} |
2269 |
+ |
|
2270 |
+ |
void fpu_exit (void) |
2271 |
+ |
{ |
2272 |
+ |
D(bug("fpu_exit\n")); |
2273 |
+ |
} |
2274 |
+ |
|
2275 |
+ |
void fpu_reset (void) |
2276 |
+ |
{ |
2277 |
+ |
D(bug("fpu_reset\n")); |
2278 |
+ |
fpu_exit(); |
2279 |
+ |
fpu_init(); |
2280 |
+ |
} |