X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Frx%2Frx.c;h=f6f93966b97278fc3103a33d7822be1622477440;hb=a1d1fa3e417b4bd8e79e2a731f9c6089e2d5f747;hp=17f5b46f4af23a4b8563b796c88d4b4cb6fe8764;hpb=e537977262c187604a7bf352617df6524330fb90;p=deliverable%2Fbinutils-gdb.git
diff --git a/sim/rx/rx.c b/sim/rx/rx.c
index 17f5b46f4a..f6f93966b9 100644
--- a/sim/rx/rx.c
+++ b/sim/rx/rx.c
@@ -1,6 +1,6 @@
/* 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.
@@ -23,6 +23,7 @@ along with this program. If not, see . */
#include
#include
#include
+#include "libiberty.h"
#include "opcode/rx.h"
#include "cpu.h"
@@ -80,6 +81,10 @@ static const char * id_names[] = {
"RXO_nop",
"RXO_nop2",
"RXO_nop3",
+ "RXO_nop4",
+ "RXO_nop5",
+ "RXO_nop6",
+ "RXO_nop7",
"RXO_scmpu",
"RXO_smovu",
@@ -136,7 +141,7 @@ static const char * id_names[] = {
};
static const char * optype_names[] = {
- " ",
+ " - ",
"#Imm", /* #addend */
" Rn ", /* Rn */
"[Rn]", /* [Rn + addend] */
@@ -147,9 +152,9 @@ static const char * optype_names[] = {
"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;
@@ -264,6 +269,52 @@ cycles (int throughput)
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)
@@ -274,6 +325,9 @@ cycles (int throughput)
#define RL(r)
#define RLD(r)
+#define divu_cycles(n,d)
+#define div_cycles(n,d)
+
#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+] */
+ case RX_Operand_Zero_Indirect: /* [Rn + 0] */
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)
{
+ default:
case RX_AnySize:
rx_abort ();
@@ -424,6 +480,7 @@ get_op (const RX_Opcode_Decoded *rd, int i)
to the size. */
switch (o->size)
{
+ default:
case RX_AnySize:
rx_abort ();
@@ -469,6 +526,7 @@ put_op (const RX_Opcode_Decoded *rd, int i, int v)
switch (o->size)
{
+ default:
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+] */
+ case RX_Operand_Zero_Indirect: /* [Rn + 0] */
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)
{
+ default:
case RX_AnySize:
rx_abort ();
@@ -683,8 +743,7 @@ poppc()
c = val & carry_mask; \
val OP 1; \
} \
- if (count) \
- set_oszc (val, 4, c); \
+ set_oszc (val, 4, c); \
PD (val); \
}
@@ -1038,10 +1097,10 @@ decode_opcode ()
break;
case RXO_branchrel:
- if (GS())
+ if (opcode->op[1].type == RX_Operand_None || GS())
{
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
@@ -1126,6 +1185,7 @@ decode_opcode ()
{
tprintf("#NAN\n");
set_flags (FLAGBIT_O, FLAGBIT_O);
+ cycles (3);
}
else
{
@@ -1133,9 +1193,8 @@ decode_opcode ()
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 */
@@ -1146,6 +1205,7 @@ decode_opcode ()
{
tprintf("#NAN\n");
set_flags (FLAGBIT_O, FLAGBIT_O);
+ cycles (2);
}
else
{
@@ -1153,9 +1213,8 @@ decode_opcode ()
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:
@@ -1232,7 +1291,9 @@ decode_opcode ()
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
{
@@ -1328,6 +1389,14 @@ decode_opcode ()
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 */)
{
@@ -1446,6 +1515,10 @@ decode_opcode ()
case RXO_nop:
case RXO_nop2:
case RXO_nop3:
+ case RXO_nop4:
+ case RXO_nop5:
+ case RXO_nop6:
+ case RXO_nop7:
E1;
break;
@@ -1743,6 +1816,22 @@ decode_opcode ()
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;
@@ -1904,7 +1993,7 @@ decode_opcode ()
case RXO_suntil:
RL(3);
#ifdef CYCLE_ACCURATE
- tx = regs.r[3];
+ tx = 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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb == uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * tx);
+#endif
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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb == uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
+#endif
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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb == uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
+#endif
break;
default:
abort();
@@ -1961,7 +2065,7 @@ decode_opcode ()
case RXO_swhile:
RL(3);
#ifdef CYCLE_ACCURATE
- tx = regs.r[3];
+ tx = 0;
#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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb != uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * tx);
+#endif
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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb != uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
+#endif
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;
+#ifdef CYCLE_ACCURATE
+ tx ++;
+#endif
if (umb != uma)
break;
}
+#ifdef CYCLE_ACCURATE
cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
+#endif
break;
default:
abort();