diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2016-04-10 11:00:01 +0900 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2016-04-10 11:02:47 +0900 |
commit | 93e6fe04ccb4008f14e3584bb1e86b2d04c9234c (patch) | |
tree | 6434e6b44038c517764a4c7005cc7c87cd8320a9 /sim/sh | |
parent | ba442f0f41a57ee9a3f0c7f574500f2bda896d08 (diff) | |
download | binutils-93e6fe04ccb4008f14e3584bb1e86b2d04c9234c.zip binutils-93e6fe04ccb4008f14e3584bb1e86b2d04c9234c.tar.gz binutils-93e6fe04ccb4008f14e3584bb1e86b2d04c9234c.tar.bz2 |
Fix primary reason why the SH simulation hasn't been working on 64 bit hosts.
sim/sh/
* interp.c (dmul): Split into dmul_s and dmul_u. Use explicit integer
width types and simplify implementation.
* gencode.c (dmuls.l, dmulu.l): Use new functions dmul_s and dmul_u.
Diffstat (limited to 'sim/sh')
-rw-r--r-- | sim/sh/ChangeLog | 8 | ||||
-rw-r--r-- | sim/sh/gencode.c | 4 | ||||
-rw-r--r-- | sim/sh/interp.c | 46 |
3 files changed, 21 insertions, 37 deletions
diff --git a/sim/sh/ChangeLog b/sim/sh/ChangeLog index 4328049..9d3cf44 100644 --- a/sim/sh/ChangeLog +++ b/sim/sh/ChangeLog @@ -1,6 +1,12 @@ +2016-04-10 Oleg Endo <olegendo@gcc.gnu.org> + + * interp.c (dmul): Split into dmul_s and dmul_u. Use explicit integer + width types and simplify implementation. + * gencode.c (dmuls.l, dmulu.l): Use new functions dmul_s and dmul_u. + 2016-04-09 Oleg Endo <olegendo@gcc.gnu.org> - * sh/interp.c (sim_memory_size): Default init to 30. + * interp.c (sim_memory_size): Default init to 30. (parse_and_set_memory_size): Adjust upper bound to 31. 2016-01-10 Mike Frysinger <vapier@gentoo.org> diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c index e3978ea..2f1a3f5 100644 --- a/sim/sh/gencode.c +++ b/sim/sh/gencode.c @@ -405,11 +405,11 @@ static op tab[] = }, { "", "nm", "dmuls.l <REG_M>,<REG_N>", "0011nnnnmmmm1101", - "dmul (1/*signed*/, R[n], R[m]);", + "dmul_s (R[n], R[m]);", }, { "", "nm", "dmulu.l <REG_M>,<REG_N>", "0011nnnnmmmm0101", - "dmul (0/*unsigned*/, R[n], R[m]);", + "dmul_u (R[n], R[m]);", }, { "n", "n", "dt <REG_N>", "0100nnnn00010000", diff --git a/sim/sh/interp.c b/sim/sh/interp.c index 46701e2..32618ba 100644 --- a/sim/sh/interp.c +++ b/sim/sh/interp.c @@ -558,7 +558,7 @@ rwat_fast (unsigned char *memory, int x, int maskw, int endianw) static INLINE int riat_fast (unsigned char *insn_ptr, int endianw) { - unsigned short *p = (unsigned short *) ((size_t) insn_ptr ^ endianw); + unsigned short *p = (unsigned short *) ((uintptr_t) insn_ptr ^ endianw); return *p; } @@ -1185,41 +1185,19 @@ div1 (int *R, int iRn2, int iRn1/*, int T*/) } static void -dmul (int sign, unsigned int rm, unsigned int rn) +dmul_s (uint32_t rm, uint32_t rn) { - unsigned long RnL, RnH; - unsigned long RmL, RmH; - unsigned long temp0, temp1, temp2, temp3; - unsigned long Res2, Res1, Res0; - - 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; - } + int64_t res = (int64_t)(int32_t)rm * (int64_t)(int32_t)rn; + MACH = (uint32_t)((uint64_t)res >> 32); + MACL = (uint32_t)res; +} - MACH = Res2; - MACL = Res0; +static void +dmul_u (uint32_t rm, uint32_t rn) +{ + uint64_t res = (uint64_t)(uint32_t)rm * (uint64_t)(uint32_t)rn; + MACH = (uint32_t)(res >> 32); + MACL = (uint32_t)res; } static void |