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: |
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 |
|
} |
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; |
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[FLO]; |
520 |
|
*wrd1 = p[FHI]; |
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}; |
877 |
< |
static int sz2[8] = |
878 |
< |
{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; |
1338 |
|
} |
1339 |
|
|
1340 |
|
// FRESTORE has no pre-decrement |
1341 |
< |
void frestore_opp(uae_u32 opcode) |
1341 |
> |
void REGPARAM2 frestore_opp(uae_u32 opcode) |
1342 |
|
{ |
1343 |
|
uae_u32 ad; |
1344 |
|
uae_u32 d; |
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 |
|
|
1623 |
– |
/* |
1624 |
– |
while (list) { |
1625 |
– |
uae_u32 wrd1, wrd2, wrd3; |
1626 |
– |
if (incr < 0) { |
1627 |
– |
from_exten(regs.fp[fpp_movem_index2[list]], |
1628 |
– |
&wrd1, &wrd2, &wrd3); |
1629 |
– |
ad -= 4; |
1630 |
– |
put_long (ad, wrd3); |
1631 |
– |
ad -= 4; |
1632 |
– |
put_long (ad, wrd2); |
1633 |
– |
ad -= 4; |
1634 |
– |
put_long (ad, wrd1); |
1635 |
– |
} else { |
1636 |
– |
from_exten(regs.fp[fpp_movem_index1[list]], |
1637 |
– |
&wrd1, &wrd2, &wrd3); |
1638 |
– |
put_long (ad, wrd1); |
1639 |
– |
ad += 4; |
1640 |
– |
put_long (ad, wrd2); |
1641 |
– |
ad += 4; |
1642 |
– |
put_long (ad, wrd3); |
1643 |
– |
ad += 4; |
1644 |
– |
} |
1645 |
– |
list = fpp_movem_next[list]; |
1646 |
– |
} |
1647 |
– |
*/ |
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 ) { |
1690 |
– |
wrd1 = get_long (ad); |
1691 |
– |
ad -= 4; |
1692 |
– |
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 |
|
} |
1715 |
– |
/**/ |
1716 |
– |
|
1717 |
– |
/* |
1718 |
– |
while (list) { |
1719 |
– |
uae_u32 wrd1, wrd2, wrd3; |
1720 |
– |
if (incr < 0) { |
1721 |
– |
ad -= 4; |
1722 |
– |
wrd3 = get_long (ad); |
1723 |
– |
ad -= 4; |
1724 |
– |
wrd2 = get_long (ad); |
1725 |
– |
ad -= 4; |
1726 |
– |
wrd1 = get_long (ad); |
1727 |
– |
regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3); |
1728 |
– |
} else { |
1729 |
– |
wrd1 = get_long (ad); |
1730 |
– |
ad += 4; |
1731 |
– |
wrd2 = get_long (ad); |
1732 |
– |
ad += 4; |
1733 |
– |
wrd3 = get_long (ad); |
1734 |
– |
ad += 4; |
1735 |
– |
regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3); |
1736 |
– |
} |
1737 |
– |
list = fpp_movem_next[list]; |
1738 |
– |
} |
1739 |
– |
*/ |
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 |
|
} |