aboutsummaryrefslogtreecommitdiff
path: root/sim/mn10300/interp.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1996-12-06 21:19:37 +0000
committerJeff Law <law@redhat.com>1996-12-06 21:19:37 +0000
commitd2523010290da3f2aabace669a8d508ceb02bc92 (patch)
treeefcea2360b7cc5822f033ea01c8e3a318b168be0 /sim/mn10300/interp.c
parent1bcfe5fa30bb4f745189f6d5055ce2088aaae839 (diff)
downloadfsf-binutils-gdb-d2523010290da3f2aabace669a8d508ceb02bc92.zip
fsf-binutils-gdb-d2523010290da3f2aabace669a8d508ceb02bc92.tar.gz
fsf-binutils-gdb-d2523010290da3f2aabace669a8d508ceb02bc92.tar.bz2
* gencode.c (write_header): Add "insn" and "extension" arguments
to the OP_* declarations. (write_template): Similarly for function templates. * interp.c (insn, extension): Remove global variables. Instead pass them as arguments to the OP_* functions. * mn10300_sim.h: Remove decls for "insn" and "extension". * simops.c (OP_*): Accept "insn" and "extension" as arguments instead of using globals. Starting to clean things up.
Diffstat (limited to 'sim/mn10300/interp.c')
-rw-r--r--sim/mn10300/interp.c228
1 files changed, 217 insertions, 11 deletions
diff --git a/sim/mn10300/interp.c b/sim/mn10300/interp.c
index cf0d713..a85c265 100644
--- a/sim/mn10300/interp.c
+++ b/sim/mn10300/interp.c
@@ -17,10 +17,9 @@ int mn10300_debug;
uint32 OP[4];
-static struct hash_entry *lookup_hash PARAMS ((uint32 ins));
+static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int));
static long hash PARAMS ((long));
static void init_system PARAMS ((void));
-
#define MAX_HASH 63
struct hash_entry
@@ -34,22 +33,83 @@ struct hash_entry
struct hash_entry hash_table[MAX_HASH+1];
+/* This probably doesn't do a very good job at bucket filling, but
+ it's simple... */
static INLINE long
hash(insn)
long insn;
{
-/* XXX */
+ /* These are one byte insns. */
+ if ((insn & 0xffffff00) == 0)
+ {
+ if ((insn & 0xf0) == 0x00
+ || (insn & 0xf0) == 0x40)
+ return (insn & 0xf3) & 0x3f;
+
+ if ((insn & 0xf0) == 0x10
+ || (insn & 0xf0) == 0x30
+ || (insn & 0xf0) == 0x50)
+ return (insn & 0xfc) & 0x3f;
+
+ if ((insn & 0xf0) == 0x60
+ || (insn & 0xf0) == 0x70
+ || (insn & 0xf0) == 0x80
+ || (insn & 0xf0) == 0x90
+ || (insn & 0xf0) == 0xa0
+ || (insn & 0xf0) == 0xb0
+ || (insn & 0xf0) == 0xe0)
+ return (insn & 0xf0) & 0x3f;
+
+ return (insn & 0xff) & 0x3f;
+ }
+
+ /* These are two byte insns */
+ if ((insn & 0xffff0000) == 0)
+ {
+ if ((insn & 0xf000) == 0x2000
+ || (insn & 0xf000) == 0x5000)
+ return ((insn & 0xfc00) >> 8) & 0x3f;
+
+ if ((insn & 0xf000) == 0x4000)
+ return ((insn & 0xf300) >> 8) & 0x3f;
+
+ if ((insn & 0xf000) == 0x8000
+ || (insn & 0xf000) == 0x9000
+ || (insn & 0xf000) == 0xa000
+ || (insn & 0xf000) == 0xb000)
+ return ((insn & 0xf000) >> 8) & 0x3f;
+
+ return ((insn & 0xff00) >> 8) & 0x3f;
+ }
+
+ /* These are three byte insns. */
+ if ((insn & 0xff000000) == 0)
+ {
+ if ((insn & 0xf00000) == 0x000000)
+ return ((insn & 0xf30000) >> 16) & 0x3f;
+
+ if ((insn & 0xf00000) == 0x200000
+ || (insn & 0xf00000) == 0x300000)
+ return ((insn & 0xfc0000) >> 16) & 0x3f;
+
+ return ((insn & 0xff0000) >> 16) & 0x3f;
+ }
+
+ /* These are four byte or larger insns. */
+ return ((insn & 0xff000000) >> 24) & 0x3f;
}
static struct hash_entry *
-lookup_hash (ins)
+lookup_hash (ins, length)
uint32 ins;
+ int length;
{
struct hash_entry *h;
h = &hash_table[hash(ins)];
- while ((ins & h->mask) != h->opcode)
+ while ((ins & h->mask) != h->opcode
+ || (length != h->ops->length))
{
if (h->next == NULL)
{
@@ -120,6 +180,28 @@ put_word (addr, data)
uint32
+load_mem_big (addr, len)
+ SIM_ADDR addr;
+ int len;
+{
+ uint8 *p = addr + State.mem;
+
+ switch (len)
+ {
+ case 1:
+ return p[0];
+ case 2:
+ return p[0] << 8 | p[1];
+ case 3:
+ return p[0] << 16 | p[1] << 8 | p[2];
+ case 4:
+ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ default:
+ abort ();
+ }
+}
+
+uint32
load_mem (addr, len)
SIM_ADDR addr;
int len;
@@ -132,6 +214,8 @@ load_mem (addr, len)
return p[0];
case 2:
return p[1] << 8 | p[0];
+ case 3:
+ return p[2] << 16 | p[1] << 8 | p[0];
case 4:
return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
default:
@@ -270,7 +354,7 @@ sim_resume (step, siggnal)
{
uint32 inst, opcode;
reg_t oldpc;
- struct interrupt_generator *intgen;
+ struct hash_entry *h;
if (step)
State.exception = SIGTRAP;
@@ -279,15 +363,137 @@ sim_resume (step, siggnal)
do
{
+ unsigned long insn, extension;
+
/* Fetch the current instruction. */
- inst = RLW (PC);
+ inst = load_mem_big (PC, 1);
oldpc = PC;
- opcode = (inst & 0x07e0) >> 5;
- /* Decode the opcode field. */
- if ((opcode & 0x30) == 0
- || (opcode & 0x38) == 0x10)
+ /* These are one byte insns. */
+ if ((inst & 0xf3) == 0x00
+ || (inst & 0xf0) == 0x10
+ || (inst & 0xfc) == 0x3c
+ || (inst & 0xf3) == 0x41
+ || (inst & 0xf3) == 0x40
+ || (inst & 0xfc) == 0x50
+ || (inst & 0xfc) == 0x54
+ || (inst & 0xf0) == 0x60
+ || (inst & 0xf0) == 0x70
+ || ((inst & 0xf0) == 0x80
+ && (inst & 0x0c) >> 2 != (inst & 0x03))
+ || ((inst & 0xf0) == 0x90
+ && (inst & 0x0c) >> 2 != (inst & 0x03))
+ || ((inst & 0xf0) == 0xa0
+ && (inst & 0x0c) >> 2 != (inst & 0x03))
+ || ((inst & 0xf0) == 0xb0
+ && (inst & 0x0c) >> 2 != (inst & 0x03))
+ || (inst & 0xff) == 0xcb
+ || (inst & 0xfc) == 0xd0
+ || (inst & 0xfc) == 0xd4
+ || (inst & 0xfc) == 0xd8
+ || (inst & 0xf0) == 0xe0)
+ {
+ insn = inst;
+ h = lookup_hash (insn, 1);
+ extension = 0;
+ (h->ops->func)(insn, extension);
+ PC += 1;
+ }
+
+ /* These are two byte insns. */
+ else if ((inst & 0xf0) == 0x80
+ || (inst & 0xf0) == 0x90
+ || (inst & 0xf0) == 0xa0
+ || (inst & 0xf0) == 0xb0
+ || (inst & 0xfc) == 0x20
+ || (inst & 0xfc) == 0x28
+ || (inst & 0xf3) == 0x43
+ || (inst & 0xf3) == 0x42
+ || (inst & 0xfc) == 0x58
+ || (inst & 0xfc) == 0x5c
+ || ((inst & 0xf0) == 0xc0
+ && (inst & 0xff) != 0xcb
+ && (inst & 0xff) != 0xcc
+ && (inst & 0xff) != 0xcd)
+ || (inst & 0xff) == 0xf0
+ || (inst & 0xff) == 0xf1
+ || (inst & 0xff) == 0xf2
+ || (inst & 0xff) == 0xf3
+ || (inst & 0xff) == 0xf4
+ || (inst & 0xff) == 0xf5
+ || (inst & 0xff) == 0xf6)
+ {
+ insn = load_mem_big (PC, 2);
+ h = lookup_hash (insn, 2);
+ extension = 0;
+ (h->ops->func)(insn, extension);
+ PC += 2;
+ }
+
+ /* These are three byte insns. */
+ else if ((inst & 0xff) == 0xf8
+ || (inst & 0xff) == 0xcc
+ || (inst & 0xff) == 0xf9
+ || (inst & 0xf3) == 0x01
+ || (inst & 0xf3) == 0x02
+ || (inst & 0xf3) == 0x03
+ || (inst & 0xfc) == 0x24
+ || (inst & 0xfc) == 0x2c
+ || (inst & 0xfc) == 0x30
+ || (inst & 0xfc) == 0x34
+ || (inst & 0xfc) == 0x38
+ || (inst & 0xff) == 0xde
+ || (inst & 0xff) == 0xdf
+ || (inst & 0xff) == 0xcc)
+ {
+ insn = load_mem_big (PC, 3);
+ h = lookup_hash (insn, 3);
+ extension = 0;
+ (h->ops->func)(insn, extension);
+ PC += 3;
+ }
+
+ /* These are four byte insns. */
+ else if ((inst & 0xff) == 0xfa
+ || (inst & 0xff) == 0xfb)
+ {
+ insn = load_mem_big (PC, 4);
+ h = lookup_hash (insn, 4);
+ extension = 0;
+ (h->ops->func)();
+ PC += 4;
+ }
+
+ /* These are five byte insns. */
+ else if ((inst & 0xff) == 0xcd
+ || (inst & 0xff) == 0xdc)
+ {
+ insn = load_mem_big (PC, 4);
+ h = lookup_hash (insn, 5);
+ extension = load_mem_big (PC + 4, 1);
+ (h->ops->func)(insn, extension);
+ PC += 5;
+ }
+
+ /* These are six byte insns. */
+ else if ((inst & 0xff) == 0xfd
+ || (inst & 0xff) == 0xfc)
+ {
+ insn = load_mem_big (PC, 4);
+ h = lookup_hash (insn, 6);
+ extension = load_mem_big (PC + 4, 2);
+ (h->ops->func)(insn, extension);
+ PC += 6;
+ }
+
+ /* Else its a seven byte insns (in theory). */
+ else
{
+ insn = load_mem_big (PC, 4);
+ h = lookup_hash (insn, 7);
+ extension = load_mem_big (PC + 4, 3);
+ (h->ops->func)(insn, extension);
+ PC += 7;
}
}
while (!State.exception);