aboutsummaryrefslogtreecommitdiff
path: root/sim/rl78
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-03-20 10:29:46 +0000
committerNick Clifton <nickc@redhat.com>2015-03-20 10:30:53 +0000
commit4819f490bd2bc88bccf636755abf3d50b7f3850f (patch)
tree824a00d02e0deefc4732e0f661df8259a4c6f669 /sim/rl78
parente8ffc436d9d849eed52af64568d9f37aeaddbd9e (diff)
downloadfsf-binutils-gdb-4819f490bd2bc88bccf636755abf3d50b7f3850f.zip
fsf-binutils-gdb-4819f490bd2bc88bccf636755abf3d50b7f3850f.tar.gz
fsf-binutils-gdb-4819f490bd2bc88bccf636755abf3d50b7f3850f.tar.bz2
Fixes implementation of hardware multiply/divide peripheral in RL78 G13 cores.
* load.c (rl78_load): If the G10, G13 or G14 flag bits are set in the ELF header use them to select the proper emulation mode. * mem.c (mem_put_byte): Use mem_put_hi to store a value into the MDB register. (mem_get_byte): Use mem_get_hi to extract a value from the MDB register.
Diffstat (limited to 'sim/rl78')
-rw-r--r--sim/rl78/ChangeLog9
-rw-r--r--sim/rl78/load.c14
-rw-r--r--sim/rl78/mem.c18
3 files changed, 35 insertions, 6 deletions
diff --git a/sim/rl78/ChangeLog b/sim/rl78/ChangeLog
index 3c92412..018b1ff 100644
--- a/sim/rl78/ChangeLog
+++ b/sim/rl78/ChangeLog
@@ -1,3 +1,12 @@
+2015-03-20 Nick Clifton <nickc@redhat.com>
+
+ * load.c (rl78_load): If the G10, G13 or G14 flag bits are set in
+ the ELF header use them to select the proper emulation mode.
+ * mem.c (mem_put_byte): Use mem_put_hi to store a value into the
+ MDB register.
+ (mem_get_byte): Use mem_get_hi to extract a value from the MDB
+ register.
+
2015-03-16 Mike Frysinger <vapier@gentoo.org>
* aclocal.m4, config.in, configure: Regenerate.
diff --git a/sim/rl78/load.c b/sim/rl78/load.c
index fcbe1ae..8d3a138 100644
--- a/sim/rl78/load.c
+++ b/sim/rl78/load.c
@@ -27,6 +27,8 @@
#include "libiberty.h"
#include "bfd.h"
+#include "elf-bfd.h"
+#include "elf/rl78.h"
#include "libbfd.h"
#include "cpu.h"
#include "mem.h"
@@ -89,7 +91,17 @@ rl78_load (bfd *prog, host_callback *callbacks, const char * const simname)
fprintf (stderr, "%s: Failed to read program headers\n", simname);
return;
}
-
+
+ rl78_g10_mode = 0;
+ switch (elf_elfheader (prog)->e_flags & E_FLAG_RL78_CPU_MASK)
+ {
+ case E_FLAG_RL78_G10: rl78_g10_mode = 1; break;
+ case E_FLAG_RL78_G13: g13_multiply = 1; break;
+ case E_FLAG_RL78_G14:
+ default:
+ break;
+ }
+
for (i = 0; i < num_headers; i++)
{
Elf_Internal_Phdr * p = phdrs + i;
diff --git a/sim/rl78/mem.c b/sim/rl78/mem.c
index 042c76e..8d95199 100644
--- a/sim/rl78/mem.c
+++ b/sim/rl78/mem.c
@@ -140,6 +140,10 @@ mem_put_byte (int address, unsigned char value)
printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", value, pc);
value &= ~1;
}
+
+ if (! g13_multiply)
+ return;
+
if (address == MDUC)
{
if ((value & 0x81) == 0x81)
@@ -166,20 +170,23 @@ mem_put_byte (int address, unsigned char value)
ahu = mem_get_hi (MDAH);
rvu = alu * ahu;
tprintf ("MDUC: %lu * %lu = %lu\n", alu, ahu, rvu);
- mem_put_si (MDBL, rvu);
+ mem_put_hi (MDBL, rvu & 0xffff);
+ mem_put_hi (MDBH, rvu >> 16);
break;
case 0x08:
als = sign_ext (mem_get_hi (MDAL), 16);
ahs = sign_ext (mem_get_hi (MDAH), 16);
rvs = als * ahs;
tprintf ("MDUC: %ld * %ld = %ld\n", als, ahs, rvs);
- mem_put_si (MDBL, rvs);
+ mem_put_hi (MDBL, rvs & 0xffff);
+ mem_put_hi (MDBH, rvs >> 16);
break;
case 0x40:
alu = mem_get_hi (MDAL);
ahu = mem_get_hi (MDAH);
rvu = alu * ahu;
- mem_put_si (MDBL, rvu);
+ mem_put_hi (MDBL, rvu & 0xffff);
+ mem_put_hi (MDBH, rvu >> 16);
mdc = mem_get_si (MDCL);
tprintf ("MDUC: %lu * %lu + %lu = ", alu, ahu, mdc);
mdc += (long) rvu;
@@ -190,7 +197,8 @@ mem_put_byte (int address, unsigned char value)
als = sign_ext (mem_get_hi (MDAL), 16);
ahs = sign_ext (mem_get_hi (MDAH), 16);
rvs = als * ahs;
- mem_put_si (MDBL, rvs);
+ mem_put_hi (MDBL, rvs & 0xffff);
+ mem_put_hi (MDBH, rvs >> 16);
mdc = mem_get_si (MDCL);
tprintf ("MDUC: %ld * %ld + %ld = ", als, ahs, mdc);
tprintf ("%ld\n", mdc);
@@ -228,7 +236,7 @@ mem_get_byte (int address)
unsigned long a, b, q, r;
memory [MDUC] &= 0xfe;
a = mem_get_si (MDAL);
- b = mem_get_si (MDAL);
+ b = mem_get_hi (MDBL) | (mem_get_hi (MDBH) << 16);
if (b == 0)
{
q = ~0;