diff options
Diffstat (limited to 'sim/sh/interp.c')
-rw-r--r-- | sim/sh/interp.c | 96 |
1 files changed, 57 insertions, 39 deletions
diff --git a/sim/sh/interp.c b/sim/sh/interp.c index d6a528d..38a1d26 100644 --- a/sim/sh/interp.c +++ b/sim/sh/interp.c @@ -44,6 +44,7 @@ #define MACL saved_state.asregs.macl #define M saved_state.asregs.sr.bits.m #define Q saved_state.asregs.sr.bits.q +#define S saved_state.asregs.sr.bits.s #define GET_SR() (saved_state.asregs.sr.bits.t = T, saved_state.asregs.sr.word) #define SET_SR(x) {saved_state.asregs.sr.word = (x); T =saved_state.asregs.sr.bits.t;} @@ -80,11 +81,7 @@ int valid[16]; #define UNDEF(x) #endif -#ifdef __GNUC__ -#define INLINE inline -#else -#define INLINE -#endif +static int IOMEM PARAMS ((int addr, int write, int value)); /* These variables are at file scope so that functions other than sim_resume can use the fetch/store macros */ @@ -703,49 +700,70 @@ dmul (sign, rm, rn) unsigned long temp0, temp1, temp2, temp3; unsigned long Res2, Res1, Res0; - - if (!sign) + RnL = rn & 0xffff; + RnH = (rn >> 16) & 0xffff; + RmL = rm & 0xffff; + RmH = (rm >> 16) & 0xffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2 += 1; + Res2 += ((Res1 >> 16) & 0xffff) + temp3; + + if (sign) { + if (rn & 0x80000000) + Res2 -= rm; + if (rm & 0x80000000) + Res2 -= rn; + } - RnL = rn & 0xffff; - RnH = (rn >> 16) & 0xffff; - RmL = rm & 0xffff; - RmH = (rm >> 16) & 0xffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2 += 1; - Res2 += ((Res1 >> 16) & 0xffff) + temp3; - MACH = Res2; - MACL = Res0; + MACH = Res2; + MACL = Res0; +} - } +static void +macw (regs, memory, n, m) + int *regs; + unsigned char *memory; + int m, n; +{ + long tempm, tempn; + long prod, macl, sum; + tempm=RSWAT(regs[m]); regs[m]+=2; + tempn=RSWAT(regs[n]); regs[n]+=2; + + macl = MACL; + prod = (long)(short) tempm * (long)(short) tempn; + sum = prod + macl; + if (S) + { + if ((~(prod ^ macl) & (sum ^ prod)) < 0) + { + /* MACH's lsb is a sticky overflow bit. */ + MACH |= 1; + /* Store the smallest negative number in MACL if prod is + negative, and the largest positive number otherwise. */ + sum = 0x7fffffff + (prod < 0); + } + } else { -#ifdef __GNUC__ - long long res; - long long a = rn; - long long b = rm; - res = a * b; - MACH = res >> 32; - MACL = res & 0xffffffff; -#else - abort (); -#endif + /* Add to MACH the sign extended product, and carry from low sum. */ + MACH += (-(prod < 0)) + ((unsigned long) sum < prod); } - + MACL = sum; } - /* Set the memory size to the power of two provided. */ void |