--- uae/src/fpp.c 2018/04/24 16:40:04 1.1.1.3 +++ uae/src/fpp.c 2018/04/24 16:50:07 1.1.1.5 @@ -18,11 +18,14 @@ #include "readcpu.h" #include "newcpu.h" #include "ersatz.h" +#include "md-fpp.h" #if 1 #define DEBUG_FPP 0 +#define MAKE_FPSR(fpsr,r) (fpsr) = ((fpsr) & 0x00FFFFFF) | ((r) == 0 ? 0x4000000 : 0) | ((r) < 0 ? 0x8000000 : 0) + /* single : S 8*E 23*F */ /* double : S 11*E 52*F */ /* extended : S 15*E 64*F */ @@ -31,125 +34,7 @@ /* E = MAX & F # 0 -> NotANumber */ /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */ -static __inline__ double to_single (uae_u32 value) -{ - double frac; - - if ((value & 0x7fffffff) == 0) - return (0.0); - frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0; - if (value & 0x80000000) - frac = -frac; - return (ldexp (frac, ((value >> 23) & 0xff) - 127)); -} - -static __inline__ uae_u32 from_single (double src) -{ - int expon; - uae_u32 tmp; - double frac; - - if (src == 0.0) - return 0; - if (src < 0) { - tmp = 0x80000000; - src = -src; - } else { - tmp = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 16777216.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - return (tmp | (((expon + 127 - 1) & 0xff) << 23) | - (((int) (frac * 16777216.0)) & 0x7fffff)); -} - -static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - double frac; - - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return 0.0; - frac = (double) wrd2 / 2147483648.0 + - (double) wrd3 / 9223372036854775808.0; - if (wrd1 & 0x80000000) - frac = -frac; - return ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383); -} - -static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) -{ - int expon; - double frac; - - if (src == 0.0) { - *wrd1 = 0; - *wrd2 = 0; - *wrd3 = 0; - return; - } - if (src < 0) { - *wrd1 = 0x80000000; - src = -src; - } else { - *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 18446744073709551616.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); - *wrd2 = (uae_u32) (frac * 4294967296.0); - *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0); -} - -static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2) -{ - double frac; - - if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) - return 0.0; - frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 + - (double) wrd2 / 4503599627370496.0; - if (wrd1 & 0x80000000) - frac = -frac; - return ldexp (frac, ((wrd1 >> 20) & 0x7ff) - 1023); -} - -static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2) -{ - int expon; - int tmp; - double frac; - - if (src == 0.0) { - *wrd1 = 0; - *wrd2 = 0; - return; - } - if (src < 0) { - *wrd1 = 0x80000000; - src = -src; - } else { - *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 9007199254740992.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - tmp = (uae_u32) (frac * 2097152.0); - *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff); - *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0); -} - -static __inline__ double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +STATIC_INLINE double to_pack (uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { double d; char *cp; @@ -183,18 +68,18 @@ static __inline__ double to_pack(uae_u32 *cp++ = ((wrd1 >> 20) & 0xf) + '0'; *cp++ = ((wrd1 >> 16) & 0xf) + '0'; *cp = 0; - sscanf(str, "%le", &d); + sscanf (str, "%le", &d); return d; } -static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +STATIC_INLINE void from_pack (double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { int i; int t; char *cp; char str[100]; - sprintf(str, "%.16e", src); + sprintf (str, "%.16e", src); cp = str; *wrd1 = *wrd2 = *wrd3 = 0; if (*cp == '-') { @@ -233,7 +118,7 @@ static __inline__ void from_pack(double } } -static __inline__ int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src) +STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src) { uaecptr tmppc; uae_u16 tmp; @@ -241,10 +126,8 @@ static __inline__ int get_fp_value (uae_ int mode; int reg; uae_u32 ad = 0; - static int sz1[8] = - {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = - {4, 4, 12, 12, 2, 8, 2, 0}; + static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; if ((extra & 0x4000) == 0) { *src = regs.fp[(extra >> 10) & 7]; @@ -266,7 +149,7 @@ static __inline__ int get_fp_value (uae_ *src = (double) (uae_s32) m68k_dreg (regs, reg); break; case 1: - *src = to_single(m68k_dreg (regs, reg)); + *src = to_single (m68k_dreg (regs, reg)); break; default: return 0; @@ -286,26 +169,26 @@ static __inline__ int get_fp_value (uae_ ad = m68k_areg (regs, reg); break; case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); break; case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); break; case 7: switch (reg) { case 0: - ad = (uae_s32) (uae_s16) next_iword(); + ad = (uae_s32) (uae_s16) next_iword (); break; case 1: - ad = next_ilong(); + ad = next_ilong (); break; case 2: ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); + ad += (uae_s32) (uae_s16) next_iword (); break; case 3: tmppc = m68k_getpc (); - tmp = next_iword(); + tmp = next_iword (); ad = get_disp_ea_020 (tmppc, tmp); break; case 4: @@ -321,7 +204,7 @@ static __inline__ int get_fp_value (uae_ *src = (double) (uae_s32) get_long (ad); break; case 1: - *src = to_single(get_long (ad)); + *src = to_single (get_long (ad)); break; case 2:{ uae_u32 wrd1, wrd2, wrd3; @@ -330,7 +213,7 @@ static __inline__ int get_fp_value (uae_ wrd2 = get_long (ad); ad += 4; wrd3 = get_long (ad); - *src = to_exten(wrd1, wrd2, wrd3); + *src = to_exten (wrd1, wrd2, wrd3); } break; case 3:{ @@ -340,22 +223,22 @@ static __inline__ int get_fp_value (uae_ wrd2 = get_long (ad); ad += 4; wrd3 = get_long (ad); - *src = to_pack(wrd1, wrd2, wrd3); + *src = to_pack (wrd1, wrd2, wrd3); } break; case 4: - *src = (double) (uae_s16) get_word(ad); + *src = (double) (uae_s16) get_word (ad); break; case 5:{ uae_u32 wrd1, wrd2; wrd1 = get_long (ad); ad += 4; wrd2 = get_long (ad); - *src = to_double(wrd1, wrd2); + *src = to_double (wrd1, wrd2); } break; case 6: - *src = (double) (uae_s8) get_byte(ad); + *src = (double) (uae_s8) get_byte (ad); break; default: return 0; @@ -363,7 +246,7 @@ static __inline__ int get_fp_value (uae_ return 1; } -static __inline__ int put_fp_value (double value, uae_u32 opcode, uae_u16 extra) +STATIC_INLINE int put_fp_value (double value, uae_u32 opcode, uae_u16 extra) { uae_u16 tmp; uaecptr tmppc; @@ -371,10 +254,8 @@ static __inline__ int put_fp_value (doub int mode; int reg; uae_u32 ad; - static int sz1[8] = - {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = - {4, 4, 12, 12, 2, 8, 2, 0}; + static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; if ((extra & 0x4000) == 0) { regs.fp[(extra >> 10) & 7] = value; @@ -389,17 +270,17 @@ static __inline__ int put_fp_value (doub switch (size) { case 6: m68k_dreg (regs, reg) = (((int) value & 0xff) - | (m68k_dreg (regs, reg) & ~0xff)); + | (m68k_dreg (regs, reg) & ~0xff)); break; case 4: m68k_dreg (regs, reg) = (((int) value & 0xffff) - | (m68k_dreg (regs, reg) & ~0xffff)); + | (m68k_dreg (regs, reg) & ~0xffff)); break; case 0: m68k_dreg (regs, reg) = (int) value; break; case 1: - m68k_dreg (regs, reg) = from_single(value); + m68k_dreg (regs, reg) = from_single (value); break; default: return 0; @@ -419,26 +300,26 @@ static __inline__ int put_fp_value (doub ad = m68k_areg (regs, reg); break; case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); break; case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); break; case 7: switch (reg) { case 0: - ad = (uae_s32) (uae_s16) next_iword(); + ad = (uae_s32) (uae_s16) next_iword (); break; case 1: - ad = next_ilong(); + ad = next_ilong (); break; case 2: ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); + ad += (uae_s32) (uae_s16) next_iword (); break; case 3: tmppc = m68k_getpc (); - tmp = next_iword(); + tmp = next_iword (); ad = get_disp_ea_020 (tmppc, tmp); break; case 4: @@ -454,12 +335,12 @@ static __inline__ int put_fp_value (doub put_long (ad, (uae_s32) value); break; case 1: - put_long (ad, from_single(value)); + put_long (ad, from_single (value)); break; case 2: { uae_u32 wrd1, wrd2, wrd3; - from_exten(value, &wrd1, &wrd2, &wrd3); + from_exten (value, &wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -470,7 +351,7 @@ static __inline__ int put_fp_value (doub case 3: { uae_u32 wrd1, wrd2, wrd3; - from_pack(value, &wrd1, &wrd2, &wrd3); + from_pack (value, &wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -479,18 +360,18 @@ static __inline__ int put_fp_value (doub } break; case 4: - put_word(ad, (uae_s16) value); + put_word (ad, (uae_s16) value); break; case 5:{ uae_u32 wrd1, wrd2; - from_double(value, &wrd1, &wrd2); + from_double (value, &wrd1, &wrd2); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); } break; case 6: - put_byte(ad, (uae_s8) value); + put_byte (ad, (uae_s8) value); break; default: return 0; @@ -498,7 +379,7 @@ static __inline__ int put_fp_value (doub return 1; } -static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad) +STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) { uae_u16 tmp; uaecptr tmppc; @@ -521,26 +402,26 @@ static __inline__ int get_fp_ad(uae_u32 *ad = m68k_areg (regs, reg); break; case 5: - *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); break; case 6: - *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); break; case 7: switch (reg) { case 0: - *ad = (uae_s32) (uae_s16) next_iword(); + *ad = (uae_s32) (uae_s16) next_iword (); break; case 1: - *ad = next_ilong(); + *ad = next_ilong (); break; case 2: *ad = m68k_getpc (); - *ad += (uae_s32) (uae_s16) next_iword(); + *ad += (uae_s32) (uae_s16) next_iword (); break; case 3: tmppc = m68k_getpc (); - tmp = next_iword(); + tmp = next_iword (); *ad = get_disp_ea_020 (tmppc, tmp); break; default: @@ -550,7 +431,7 @@ static __inline__ int get_fp_ad(uae_u32 return 1; } -static __inline__ int fpp_cond(uae_u32 opcode, int contition) +STATIC_INLINE int fpp_cond (uae_u32 opcode, int contition) { int N = (regs.fpsr & 0x8000000) != 0; int Z = (regs.fpsr & 0x4000000) != 0; @@ -626,17 +507,17 @@ static __inline__ int fpp_cond(uae_u32 o return -1; } -void fdbcc_opp(uae_u32 opcode, uae_u16 extra) +void fdbcc_opp (uae_u32 opcode, uae_u16 extra) { uaecptr pc = (uae_u32) m68k_getpc (); - uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + uae_s32 disp = (uae_s32) (uae_s16) next_iword (); int cc; #if DEBUG_FPP - printf("fdbcc_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("fdbcc_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - cc = fpp_cond(opcode, extra & 0x3f); + cc = fpp_cond (opcode, extra & 0x3f); if (cc == -1) { m68k_setpc (pc - 4); op_illg (opcode); @@ -644,63 +525,62 @@ void fdbcc_opp(uae_u32 opcode, uae_u16 e int reg = opcode & 0x7; m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) - | ((m68k_dreg (regs, reg) - 1) & 0xffff)); + | ((m68k_dreg (regs, reg) - 1) & 0xffff)); if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) m68k_setpc (pc + disp); } } -void fscc_opp(uae_u32 opcode, uae_u16 extra) +void fscc_opp (uae_u32 opcode, uae_u16 extra) { uae_u32 ad; int cc; #if DEBUG_FPP - printf("fscc_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("fscc_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - cc = fpp_cond(opcode, extra & 0x3f); + cc = fpp_cond (opcode, extra & 0x3f); if (cc == -1) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); } else if ((opcode & 0x38) == 0) { - m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | - (cc ? 0xff : 0x00); + m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00); } else { - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); } else - put_byte(ad, cc ? 0xff : 0x00); + put_byte (ad, cc ? 0xff : 0x00); } } -void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc) +void ftrapcc_opp (uae_u32 opcode, uaecptr oldpc) { int cc; #if DEBUG_FPP - printf("ftrapcc_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("ftrapcc_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - cc = fpp_cond(opcode, opcode & 0x3f); + cc = fpp_cond (opcode, opcode & 0x3f); if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); } if (cc) - Exception(7, oldpc - 2); + Exception (7, oldpc - 2); } -void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra) +void fbcc_opp (uae_u32 opcode, uaecptr pc, uae_u32 extra) { int cc; #if DEBUG_FPP - printf("fbcc_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("fbcc_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - cc = fpp_cond(opcode, opcode & 0x3f); + cc = fpp_cond (opcode, opcode & 0x3f); if (cc == -1) { m68k_setpc (pc); op_illg (opcode); @@ -711,39 +591,43 @@ void fbcc_opp(uae_u32 opcode, uaecptr pc } } -void fsave_opp(uae_u32 opcode) +void fsave_opp (uae_u32 opcode) { uae_u32 ad; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; int i; #if DEBUG_FPP - printf("fsave_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("fsave_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 2); op_illg (opcode); return; } - if (incr < 0) { - ad -= 4; - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); + + if (currprefs.cpu_level == 4) { } else { - put_long (ad, 0x1f180000); - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); + if (incr < 0) { + ad -= 4; + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); + } else { + put_long (ad, 0x1f180000); + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + put_long (ad, 0x70000000); ad += 4; } - put_long (ad, 0x70000000); - ad += 4; } if ((opcode & 0x38) == 0x18) m68k_areg (regs, opcode & 7) = ad; @@ -751,42 +635,45 @@ void fsave_opp(uae_u32 opcode) m68k_areg (regs, opcode & 7) = ad; } -void frestore_opp(uae_u32 opcode) +void frestore_opp (uae_u32 opcode) { uae_u32 ad; uae_u32 d; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; #if DEBUG_FPP - printf("frestore_opp at %08lx\n", m68k_getpc ()); - fflush(stdout); + printf ("frestore_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); #endif - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 2); op_illg (opcode); return; } - if (incr < 0) { - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad -= 45 * 4; - } + if (currprefs.cpu_level == 4) { } else { - d = get_long (ad); - ad += 4; - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad += 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad += 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad += 45 * 4; + if (incr < 0) { + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } else { + d = get_long (ad); + ad += 4; + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad += 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad += 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad += 45 * 4; + } } } if ((opcode & 0x38) == 0x18) @@ -795,15 +682,14 @@ void frestore_opp(uae_u32 opcode) m68k_areg (regs, opcode & 7) = ad; } -void fpp_opp(uae_u32 opcode, uae_u16 extra) +void fpp_opp (uae_u32 opcode, uae_u16 extra) { int reg; double src; #if DEBUG_FPP - printf("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, - m68k_getpc () - 4); - fflush(stdout); + printf ("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, m68k_getpc () - 4); + fflush (stdout); #endif switch ((extra >> 13) & 0x7) { case 3: @@ -849,18 +735,18 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext } else if ((opcode & 0x3f) == 0x3c) { if ((extra & 0x2000) == 0) { if (extra & 0x1000) - regs.fpcr = next_ilong(); + regs.fpcr = next_ilong (); if (extra & 0x0800) - regs.fpsr = next_ilong(); + regs.fpsr = next_ilong (); if (extra & 0x0400) - regs.fpiar = next_ilong(); + regs.fpiar = next_ilong (); } } else if (extra & 0x2000) { /* FMOVEM FPP->memory */ uae_u32 ad; int incr = 0; - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); return; @@ -895,7 +781,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext /* FMOVEM memory->FPP */ uae_u32 ad; - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); return; @@ -926,7 +812,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext int incr = 0; if (extra & 0x2000) { /* FMOVEM FPP->memory */ - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); return; @@ -952,8 +838,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext while (list) { uae_u32 wrd1, wrd2, wrd3; if (incr < 0) { - from_exten(regs.fp[fpp_movem_index2[list]], - &wrd1, &wrd2, &wrd3); + from_exten (regs.fp[fpp_movem_index2[list]], &wrd1, &wrd2, &wrd3); ad -= 4; put_long (ad, wrd3); ad -= 4; @@ -961,8 +846,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext ad -= 4; put_long (ad, wrd1); } else { - from_exten(regs.fp[fpp_movem_index1[list]], - &wrd1, &wrd2, &wrd3); + from_exten (regs.fp[fpp_movem_index1[list]], &wrd1, &wrd2, &wrd3); put_long (ad, wrd1); ad += 4; put_long (ad, wrd2); @@ -978,7 +862,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext m68k_areg (regs, opcode & 7) = ad; } else { /* FMOVEM memory->FPP */ - if (get_fp_ad(opcode, &ad) == 0) { + if (get_fp_ad (opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); op_illg (opcode); return; @@ -1035,7 +919,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext if ((extra & 0xfc00) == 0x5c00) { switch (extra & 0x7f) { case 0x00: - regs.fp[reg] = 4.0 * atan(1.0); + regs.fp[reg] = 4.0 * atan (1.0); break; case 0x0b: regs.fp[reg] = log10 (2.0); @@ -1117,51 +1001,59 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext switch (extra & 0x7f) { case 0x00: /* FMOVE */ regs.fp[reg] = src; + /* Brian King was here. to register needs FPSR updated. + * See page 3-73 in Motorola 68K programmers reference manual. + * %%%FPU */ + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x01: /* FINT */ - regs.fp[reg] = (int) (src + 0.5); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + /* need to take the current rounding mode into account */ + switch ((regs.fpcr >> 4) & 0x3) { + case 0: + regs.fp[reg] = (int) (src + 0.5); + break; + case 1: + regs.fp[reg] = (int) src; + break; + case 2: + regs.fp[reg] = floor (src); + break; + case 3: + regs.fp[reg] = ceil (src); + break; + } break; case 0x02: /* FSINH */ regs.fp[reg] = sinh (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x03: /* FINTRZ */ regs.fp[reg] = (int) src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x04: /* FSQRT */ regs.fp[reg] = sqrt (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x06: /* FLOGNP1 */ regs.fp[reg] = log (src + 1.0); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x08: /* FETOXM1 */ regs.fp[reg] = exp (src) - 1.0; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x09: /* FTANH */ regs.fp[reg] = tanh (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x0a: /* FATAN */ regs.fp[reg] = atan (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x0c: /* FASIN */ regs.fp[reg] = asin (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x0d: /* FATANH */ #if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ @@ -1169,137 +1061,110 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext #else regs.fp[reg] = atanh (src); #endif - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x0e: /* FSIN */ regs.fp[reg] = sin (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x0f: /* FTAN */ regs.fp[reg] = tan (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x10: /* FETOX */ regs.fp[reg] = exp (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x11: /* FTWOTOX */ - regs.fp[reg] = pow(2.0, src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = pow (2.0, src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x12: /* FTENTOX */ - regs.fp[reg] = pow(10.0, src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = pow (10.0, src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x14: /* FLOGN */ regs.fp[reg] = log (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x15: /* FLOG10 */ regs.fp[reg] = log10 (src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x16: /* FLOG2 */ regs.fp[reg] = log (src) / log (2.0); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x18: /* FABS */ regs.fp[reg] = src < 0 ? -src : src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x19: /* FCOSH */ - regs.fp[reg] = cosh(src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = cosh (src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x1a: /* FNEG */ regs.fp[reg] = -src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x1c: /* FACOS */ - regs.fp[reg] = acos(src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = acos (src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x1d: /* FCOS */ - regs.fp[reg] = cos(src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = cos (src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x1e: /* FGETEXP */ { int expon; frexp (src, &expon); regs.fp[reg] = (double) (expon - 1); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); } break; case 0x1f: /* FGETMAN */ { int expon; regs.fp[reg] = frexp (src, &expon) * 2.0; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); } break; case 0x20: /* FDIV */ regs.fp[reg] /= src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x21: /* FMOD */ - regs.fp[reg] = regs.fp[reg] - - (double) ((int) (regs.fp[reg] / src)) * src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src; + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x22: /* FADD */ regs.fp[reg] += src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x23: /* FMUL */ regs.fp[reg] *= src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x24: /* FSGLDIV */ regs.fp[reg] /= src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x25: /* FREM */ - regs.fp[reg] = regs.fp[reg] - - (double) ((int) (regs.fp[reg] / src + 0.5)) * src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src; + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x26: /* FSCALE */ regs.fp[reg] *= exp (log (2.0) * src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x27: /* FSGLMUL */ regs.fp[reg] *= src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x28: /* FSUB */ regs.fp[reg] -= src; - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x30: /* FSINCOS */ case 0x31: @@ -1310,20 +1175,17 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext case 0x36: case 0x37: regs.fp[reg] = sin (src); - regs.fp[extra & 7] = cos(src); - regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | - (regs.fp[reg] < 0 ? 0x8000000 : 0); + regs.fp[extra & 7] = cos (src); + MAKE_FPSR (regs.fpsr, regs.fp[reg]); break; case 0x38: /* FCMP */ { double tmp = regs.fp[reg] - src; - regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | - (tmp < 0 ? 0x8000000 : 0); + regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); } break; case 0x3a: /* FTST */ - regs.fpsr = (src == 0 ? 0x4000000 : 0) | - (src < 0 ? 0x8000000 : 0); + regs.fpsr = (src == 0 ? 0x4000000 : 0) | (src < 0 ? 0x8000000 : 0); break; default: m68k_setpc (m68k_getpc () - 4);