X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Frx%2Frx.c;h=f6f93966b97278fc3103a33d7822be1622477440;hb=a1d1fa3e417b4bd8e79e2a731f9c6089e2d5f747;hp=19b896bc127c23bc1545916734575b6aba6c659a;hpb=be380a3ea061110105f734192593b3e5472f3941;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/rx/rx.c b/sim/rx/rx.c index 19b896bc12..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; @@ -1818,6 +1907,9 @@ decode_opcode () break; case RXO_smovu: +#ifdef CYCLE_ACCURATE + tx = regs.r[3]; +#endif while (regs.r[3] != 0) { uma = mem_get_qi (regs.r[2] ++); @@ -1826,6 +1918,7 @@ decode_opcode () if (uma == 0) break; } + cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4)); break; case RXO_shar: /* d = ma >> mb */ @@ -1900,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) { @@ -1916,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; @@ -1928,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; @@ -1940,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(); @@ -1957,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; @@ -1970,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; @@ -1982,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; @@ -1994,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();