Fixes implementation of hardware multiply/divide peripheral in RL78 G13 cores.
authorNick Clifton <nickc@redhat.com>
Fri, 20 Mar 2015 10:29:46 +0000 (10:29 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 20 Mar 2015 10:30:53 +0000 (10:30 +0000)
* 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.

sim/rl78/ChangeLog
sim/rl78/load.c
sim/rl78/mem.c

index 3c92412031a52aac48ffe569a358c0c7efef2fa1..018b1ff77d05db58113021099051dd481c25a99e 100644 (file)
@@ -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.
index fcbe1aef85dd10964edcc6c765378a407f92d766..8d3a13823e2c09e2169de907f7deab422d1744c5 100644 (file)
@@ -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;
index 042c76e131d9c2fbe159b53cce02f73d888479e1..8d95199352cae54aa19daf39bbb93150fca5a764 100644 (file)
@@ -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;