--- uae/src/fpp.c 2018/04/24 16:40:04 1.1.1.3 +++ uae/src/fpp.c 2018/04/24 16:48:45 1.1.1.4 @@ -18,6 +18,7 @@ #include "readcpu.h" #include "newcpu.h" #include "ersatz.h" +#include "md-fpp.h" #if 1 @@ -31,125 +32,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; @@ -187,7 +70,7 @@ static __inline__ double to_pack(uae_u32 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; @@ -233,7 +116,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 +124,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]; @@ -363,7 +244,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 +252,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,11 +268,11 @@ 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; @@ -498,7 +377,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; @@ -550,7 +429,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; @@ -1117,12 +996,29 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext switch (extra & 0x7f) { case 0x00: /* FMOVE */ regs.fp[reg] = src; - break; - case 0x01: /* FINT */ - regs.fp[reg] = (int) (src + 0.5); + /* Brian King was here. to register needs FPSR updated. + * See page 3-73 in Motorola 68K programmers reference manual. + * %%%FPU */ regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) | (regs.fp[reg] < 0 ? 0x8000000 : 0); break; + case 0x01: /* FINT */ + /* 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) |