Automatic date update in version.in
[deliverable/binutils-gdb.git] / sim / rx / rx.c
index 17f5b46f4af23a4b8563b796c88d4b4cb6fe8764..f6f93966b97278fc3103a33d7822be1622477440 100644 (file)
@@ -1,6 +1,6 @@
 /* rx.c --- opcode semantics for stand-alone RX simulator.
 
 /* rx.c --- opcode semantics for stand-alone RX simulator.
 
-Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+Copyright (C) 2008-2020 Free Software Foundation, Inc.
 Contributed by Red Hat, Inc.
 
 This file is part of the GNU simulators.
 Contributed by Red Hat, Inc.
 
 This file is part of the GNU simulators.
@@ -23,6 +23,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include "libiberty.h"
 
 #include "opcode/rx.h"
 #include "cpu.h"
 
 #include "opcode/rx.h"
 #include "cpu.h"
@@ -80,6 +81,10 @@ static const char * id_names[] = {
   "RXO_nop",
   "RXO_nop2",
   "RXO_nop3",
   "RXO_nop",
   "RXO_nop2",
   "RXO_nop3",
+  "RXO_nop4",
+  "RXO_nop5",
+  "RXO_nop6",
+  "RXO_nop7",
 
   "RXO_scmpu",
   "RXO_smovu",
 
   "RXO_scmpu",
   "RXO_smovu",
@@ -136,7 +141,7 @@ static const char * id_names[] = {
 };
 
 static const char * optype_names[] = {
 };
 
 static const char * optype_names[] = {
-  "    ",
+  " -  ",
   "#Imm",      /* #addend */
   " Rn ",      /* Rn */
   "[Rn]",      /* [Rn + addend] */
   "#Imm",      /* #addend */
   " Rn ",      /* Rn */
   "[Rn]",      /* [Rn + addend] */
@@ -147,9 +152,9 @@ static const char * optype_names[] = {
   "RbRi"       /* [Rb + scale * Ri] */
 };
 
   "RbRi"       /* [Rb + scale * Ri] */
 };
 
-#define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
-#define N_RXT (sizeof(optype_names)/sizeof(optype_names[0]))
-#define N_MAP 30
+#define N_RXO ARRAY_SIZE (id_names)
+#define N_RXT ARRAY_SIZE (optype_names)
+#define N_MAP 90
 
 static unsigned long long benchmark_start_cycle;
 static unsigned long long benchmark_end_cycle;
 
 static unsigned long long benchmark_start_cycle;
 static unsigned long long benchmark_end_cycle;
@@ -264,6 +269,52 @@ cycles (int throughput)
       new_rt = r;                              \
     }
 
       new_rt = r;                              \
     }
 
+static int
+lsb_count (unsigned long v, int is_signed)
+{
+  int i, lsb;
+  if (is_signed && (v & 0x80000000U))
+    v = (unsigned long)(long)(-v);
+  for (i=31; i>=0; i--)
+    if (v & (1 << i))
+      {
+       /* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
+       lsb = (i + 2) / 2;
+       return lsb;
+      }
+  return 0;
+}
+
+static int
+divu_cycles(unsigned long num, unsigned long den)
+{
+  int nb = lsb_count (num, 0);
+  int db = lsb_count (den, 0);
+  int rv;
+
+  if (nb < db)
+    rv = 2;
+  else
+    rv = 3 + nb - db;
+  E (rv);
+  return rv;
+}
+
+static int
+div_cycles(long num, long den)
+{
+  int nb = lsb_count ((unsigned long)num, 1);
+  int db = lsb_count ((unsigned long)den, 1);
+  int rv;
+
+  if (nb < db)
+    rv = 3;
+  else
+    rv = 5 + nb - db;
+  E (rv);
+  return rv;
+}
+
 #else /* !CYCLE_ACCURATE */
 
 #define cycles(t)
 #else /* !CYCLE_ACCURATE */
 
 #define cycles(t)
@@ -274,6 +325,9 @@ cycles (int throughput)
 #define RL(r)
 #define RLD(r)
 
 #define RL(r)
 #define RLD(r)
 
+#define divu_cycles(n,d)
+#define div_cycles(n,d)
+
 #endif /* else CYCLE_ACCURATE */
 
 static int size2bytes[] = {
 #endif /* else CYCLE_ACCURATE */
 
 static int size2bytes[] = {
@@ -357,6 +411,7 @@ get_op (const RX_Opcode_Decoded *rd, int i)
       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
       /* fall through */
     case RX_Operand_Postinc:   /* [Rn+] */
       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
       /* fall through */
     case RX_Operand_Postinc:   /* [Rn+] */
+    case RX_Operand_Zero_Indirect:     /* [Rn + 0] */
     case RX_Operand_Indirect:  /* [Rn + addend] */
     case RX_Operand_TwoReg:    /* [Rn + scale * R2] */
 #ifdef CYCLE_ACCURATE
     case RX_Operand_Indirect:  /* [Rn + addend] */
     case RX_Operand_TwoReg:    /* [Rn + scale * R2] */
 #ifdef CYCLE_ACCURATE
@@ -384,6 +439,7 @@ get_op (const RX_Opcode_Decoded *rd, int i)
 
       switch (o->size)
        {
 
       switch (o->size)
        {
+       default:
        case RX_AnySize:
          rx_abort ();
 
        case RX_AnySize:
          rx_abort ();
 
@@ -424,6 +480,7 @@ get_op (const RX_Opcode_Decoded *rd, int i)
      to the size.  */
   switch (o->size)
     {
      to the size.  */
   switch (o->size)
     {
+    default:
     case RX_AnySize:
       rx_abort ();
 
     case RX_AnySize:
       rx_abort ();
 
@@ -469,6 +526,7 @@ put_op (const RX_Opcode_Decoded *rd, int i, int v)
 
   switch (o->size)
     {
 
   switch (o->size)
     {
+    default:
     case RX_AnySize:
       if (o->type != RX_Operand_Register)
        rx_abort ();
     case RX_AnySize:
       if (o->type != RX_Operand_Register)
        rx_abort ();
@@ -525,6 +583,7 @@ put_op (const RX_Opcode_Decoded *rd, int i, int v)
       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
       /* fall through */
     case RX_Operand_Postinc:   /* [Rn+] */
       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
       /* fall through */
     case RX_Operand_Postinc:   /* [Rn+] */
+    case RX_Operand_Zero_Indirect:     /* [Rn + 0] */
     case RX_Operand_Indirect:  /* [Rn + addend] */
     case RX_Operand_TwoReg:    /* [Rn + scale * R2] */
 
     case RX_Operand_Indirect:  /* [Rn + addend] */
     case RX_Operand_TwoReg:    /* [Rn + scale * R2] */
 
@@ -548,6 +607,7 @@ put_op (const RX_Opcode_Decoded *rd, int i, int v)
 
       switch (o->size)
        {
 
       switch (o->size)
        {
+       default:
        case RX_AnySize:
          rx_abort ();
 
        case RX_AnySize:
          rx_abort ();
 
@@ -683,8 +743,7 @@ poppc()
       c = val & carry_mask; \
       val OP 1; \
     } \
       c = val & carry_mask; \
       val OP 1; \
     } \
-  if (count) \
-    set_oszc (val, 4, c); \
+  set_oszc (val, 4, c); \
   PD (val); \
 }
 
   PD (val); \
 }
 
@@ -1038,10 +1097,10 @@ decode_opcode ()
       break;
 
     case RXO_branchrel:
       break;
 
     case RXO_branchrel:
-      if (GS())
+      if (opcode->op[1].type == RX_Operand_None || GS())
        {
          int delta = GD();
        {
          int delta = GD();
-         regs.r_pc += delta;
+         regs.r_pc = opcode_pc + delta;
 #ifdef CYCLE_ACCURATE
          /* Note: specs say 3, chip says 2.  */
          if (delta >= 0 && delta < 16
 #ifdef CYCLE_ACCURATE
          /* Note: specs say 3, chip says 2.  */
          if (delta >= 0 && delta < 16
@@ -1126,6 +1185,7 @@ decode_opcode ()
        {
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
        {
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
+         cycles (3);
        }
       else
        {
        }
       else
        {
@@ -1133,9 +1193,8 @@ decode_opcode ()
          tprintf("%d\n", v);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          tprintf("%d\n", v);
          set_flags (FLAGBIT_O, 0);
          PD (v);
+         div_cycles (mb, ma);
        }
        }
-      /* Note: spec says 3 to 22 cycles, we are pessimistic.  */
-      cycles (22);
       break;
 
     case RXO_divu: /* d = d / s */
       break;
 
     case RXO_divu: /* d = d / s */
@@ -1146,6 +1205,7 @@ decode_opcode ()
        {
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
        {
          tprintf("#NAN\n");
          set_flags (FLAGBIT_O, FLAGBIT_O);
+         cycles (2);
        }
       else
        {
        }
       else
        {
@@ -1153,9 +1213,8 @@ decode_opcode ()
          tprintf("%u\n", v);
          set_flags (FLAGBIT_O, 0);
          PD (v);
          tprintf("%u\n", v);
          set_flags (FLAGBIT_O, 0);
          PD (v);
+         divu_cycles (umb, uma);
        }
        }
-      /* Note: spec says 2 to 20 cycles, we are pessimistic.  */
-      cycles (20);
       break;
 
     case RXO_emul:
       break;
 
     case RXO_emul:
@@ -1232,7 +1291,9 @@ decode_opcode ()
       v = GS ();
       if (v == 255)
        {
       v = GS ();
       if (v == 255)
        {
-         DO_RETURN (rx_syscall (regs.r[5]));
+         int rc = rx_syscall (regs.r[5]);
+         if (! RX_STEPPED (rc))
+           DO_RETURN (rc);
        }
       else
        {
        }
       else
        {
@@ -1328,6 +1389,14 @@ decode_opcode ()
     case RXO_mov:
       v = GS ();
 
     case RXO_mov:
       v = GS ();
 
+      if (opcode->op[1].type == RX_Operand_Register
+         && opcode->op[1].reg == 17 /* PC */)
+       {
+         /* Special case.  We want the address of the insn, not the
+            address of the next insn.  */
+         v = opcode_pc;
+       }
+
       if (opcode->op[0].type == RX_Operand_Register
          && opcode->op[0].reg == 16 /* PSW */)
        {
       if (opcode->op[0].type == RX_Operand_Register
          && opcode->op[0].reg == 16 /* PSW */)
        {
@@ -1446,6 +1515,10 @@ decode_opcode ()
     case RXO_nop:
     case RXO_nop2:
     case RXO_nop3:
     case RXO_nop:
     case RXO_nop2:
     case RXO_nop3:
+    case RXO_nop4:
+    case RXO_nop5:
+    case RXO_nop6:
+    case RXO_nop7:
       E1;
       break;
 
       E1;
       break;
 
@@ -1743,6 +1816,22 @@ decode_opcode ()
       E1;
       break;
 
       E1;
       break;
 
+    case RXO_satr:
+      if (FLAG_O && ! FLAG_S)
+       {
+         put_reg (6, 0x0);
+         put_reg (5, 0x7fffffff);
+         put_reg (4, 0xffffffff);
+       }
+      else if (FLAG_O && FLAG_S)
+       {
+         put_reg (6, 0xffffffff);
+         put_reg (5, 0x80000000);
+         put_reg (4, 0x0);
+       }
+      E1;
+      break;
+      
     case RXO_sbb:
       MATH_OP (-, ! carry);
       break;
     case RXO_sbb:
       MATH_OP (-, ! carry);
       break;
@@ -1904,7 +1993,7 @@ decode_opcode ()
     case RXO_suntil:
       RL(3);
 #ifdef CYCLE_ACCURATE
     case RXO_suntil:
       RL(3);
 #ifdef CYCLE_ACCURATE
-      tx = regs.r[3];
+      tx = 0;
 #endif
       if (regs.r[3] == 0)
        {
 #endif
       if (regs.r[3] == 0)
        {
@@ -1920,10 +2009,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb == uma)
                break;
            }
              if (umb == uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * tx);
          cycles (3 + 3 * tx);
+#endif
          break;
        case RX_Word:
          uma = get_reg (2) & 0xffff;
          break;
        case RX_Word:
          uma = get_reg (2) & 0xffff;
@@ -1932,10 +2026,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb == uma)
                break;
            }
              if (umb == uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
          cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
+#endif
          break;
        case RX_Byte:
          uma = get_reg (2) & 0xff;
          break;
        case RX_Byte:
          uma = get_reg (2) & 0xff;
@@ -1944,10 +2043,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb == uma)
                break;
            }
              if (umb == uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
          cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
+#endif
          break;
        default:
          abort();
          break;
        default:
          abort();
@@ -1961,7 +2065,7 @@ decode_opcode ()
     case RXO_swhile:
       RL(3);
 #ifdef CYCLE_ACCURATE
     case RXO_swhile:
       RL(3);
 #ifdef CYCLE_ACCURATE
-      tx = regs.r[3];
+      tx = 0;
 #endif
       if (regs.r[3] == 0)
        break;
 #endif
       if (regs.r[3] == 0)
        break;
@@ -1974,10 +2078,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
              regs.r[3] --;
              umb = mem_get_si (get_reg (1));
              regs.r[1] += 4;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb != uma)
                break;
            }
              if (umb != uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * tx);
          cycles (3 + 3 * tx);
+#endif
          break;
        case RX_Word:
          uma = get_reg (2) & 0xffff;
          break;
        case RX_Word:
          uma = get_reg (2) & 0xffff;
@@ -1986,10 +2095,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
              regs.r[3] --;
              umb = mem_get_hi (get_reg (1));
              regs.r[1] += 2;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb != uma)
                break;
            }
              if (umb != uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
          cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
+#endif
          break;
        case RX_Byte:
          uma = get_reg (2) & 0xff;
          break;
        case RX_Byte:
          uma = get_reg (2) & 0xff;
@@ -1998,10 +2112,15 @@ decode_opcode ()
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
              regs.r[3] --;
              umb = mem_get_qi (regs.r[1]);
              regs.r[1] += 1;
+#ifdef CYCLE_ACCURATE
+             tx ++;
+#endif
              if (umb != uma)
                break;
            }
              if (umb != uma)
                break;
            }
+#ifdef CYCLE_ACCURATE
          cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
          cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
+#endif
          break;
        default:
          abort();
          break;
        default:
          abort();
This page took 0.027926 seconds and 4 git commands to generate.