diff options
author | Jeff Law <law@redhat.com> | 1996-12-06 21:19:37 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1996-12-06 21:19:37 +0000 |
commit | d2523010290da3f2aabace669a8d508ceb02bc92 (patch) | |
tree | efcea2360b7cc5822f033ea01c8e3a318b168be0 /sim/mn10300/interp.c | |
parent | 1bcfe5fa30bb4f745189f6d5055ce2088aaae839 (diff) | |
download | gdb-d2523010290da3f2aabace669a8d508ceb02bc92.zip gdb-d2523010290da3f2aabace669a8d508ceb02bc92.tar.gz 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.c | 228 |
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); |