RFA: RL78: Fix simulation of G13 multiply/divide peripheral
Commit Message
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.
Comments
On 19 Mar 2015 15:51, Nick Clifton wrote:
> 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.
how do you really know when there are no sim tests ?
-mike
Hi Mike,
>> Tested with no regressions on an rl78-elf toolchain.
>
> how do you really know when there are no sim tests ?
Because I use the sim to help run the gcc testsuite, and without this
patch several gcc tests were failing due to errors from the sim about
misaligned accesses to the MDB register. With this patch those failures
went away and no new failures were introduced. Hence I felt confident
that the patch was good.
Cheers
Nick
On 20 Mar 2015 10:28, Nicholas Clifton wrote:
> >> Tested with no regressions on an rl78-elf toolchain.
> >
> > how do you really know when there are no sim tests ?
>
> Because I use the sim to help run the gcc testsuite, and without this
> patch several gcc tests were failing due to errors from the sim about
> misaligned accesses to the MDB register. With this patch those failures
> went away and no new failures were introduced. Hence I felt confident
> that the patch was good.
OK. it would be nice if there were at least one minor sim test though.
it's dirt simple to add one written in just assembly ...
i have found directed sim tests to be better than gcc in the long run.
-mike
On 19 Mar 2015 15:51, Nick Clifton wrote:
> 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.
did you forgot to commit some other change ? rl78 fails to build now:
gcc -DHAVE_CONFIG_H -DPROFILE=1 -DWITH_PROFILE=-1
-DDEFAULT_INLINE=0 -Wall -I. -I../../../../sim/rl78 -I../common
-I../../../../sim/rl78/../common -I../../include
-I../../../../sim/rl78/../../include -I../../bfd
-I../../../../sim/rl78/../../bfd -I../../opcodes
-I../../../../sim/rl78/../../opcodes -g -O2 -c -o load.o -MT load.o -MMD -MP
-MF .deps/load.Tpo ../../../../sim/rl78/load.c
../../../../sim/rl78/load.c: In function 'rl78_load':
../../../../sim/rl78/load.c:95:3: error: 'rl78_g10_mode' undeclared (first use
in this function)
rl78_g10_mode = 0;
^
../../../../sim/rl78/load.c:95:3: note: each undeclared identifier is reported
only once for each function it appears in
../../../../sim/rl78/load.c:99:16: error: 'g13_multiply' undeclared (first use
in this function)
case E_FLAG_RL78_G13: g13_multiply = 1; break;
^
Makefile:530: recipe for target 'load.o' failed
make[2]: *** [load.o] Error 1
i don't see either of those identifiers in the current master.
-mike
@@ -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;
@@ -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;