This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFA: RL78: Fix simulation of G13 multiply/divide peripheral
- From: Nick Clifton <nickc at redhat dot com>
- To: dj at redhat dot com
- Cc: gdb-patches at sourceware dot org
- Date: Thu, 19 Mar 2015 15:51:32 +0000
- Subject: RFA: RL78: Fix simulation of G13 multiply/divide peripheral
- Authentication-results: sourceware.org; auth=none
Hi DJ,
The patch below fixes a problem with the RL78 simulator simulation of
the G13 multiply/divide peripheral. Namely the MDB register is not
32-bit aligned so the mem_put_si and mem_get_si functions cannot be
used with it. Instead the value has to be split up into two 16-bit
parts and the mem_{get|put}_hi functions used.
In addition the patch adds support for the new G13 and G14 flags in
RL78 ELF headers. If one of these flag bits is present then the patch
selects the appropriate G10/G13/G14 emulation mode.
Tested with no regressions on an rl78-elf toolchain.
OK to apply ?
Cheers
Nick
sim/rl78/ChangeLog
2015-03-19 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.
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;