RFA: RL78: Fix simulation of G13 multiply/divide peripheral

Message ID 87fv91nfy3.fsf@redhat.com
State Committed
Headers

Commit Message

Nick Clifton March 19, 2015, 3:51 p.m. UTC
  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

DJ Delorie March 19, 2015, 3:56 p.m. UTC | #1
Ok.
  
Mike Frysinger March 19, 2015, 6:42 p.m. UTC | #2
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
  
Nick Clifton March 20, 2015, 10:28 a.m. UTC | #3
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
  
Mike Frysinger March 20, 2015, 3:40 p.m. UTC | #4
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
  
Mike Frysinger March 23, 2015, 8:19 a.m. UTC | #5
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
  

Patch

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;