X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fd10v%2Finterp.c;h=cb8c6cf61f5c800c64624d810450f09e004b7b3b;hb=8b8c7c9f49992750f66f81b4601d593a3858d98c;hp=1a1ede976b99c9360ddeaf54e52aa3db944c9043;hpb=7eebfc6296f0830a435a21be0ab37a076c8566bd;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/d10v/interp.c b/sim/d10v/interp.c index 1a1ede976b..cb8c6cf61f 100644 --- a/sim/d10v/interp.c +++ b/sim/d10v/interp.c @@ -1,39 +1,63 @@ +#include "config.h" +#include #include -#include "sysdep.h" #include "bfd.h" -#include "remote-sim.h" +#include "gdb/callback.h" +#include "gdb/remote-sim.h" -#include "d10v_sim.h" +#include "sim-main.h" +#include "sim-options.h" -#define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */ -#define DMEM_SIZE 16 /* Data memory */ +#include "gdb/sim-d10v.h" +#include "gdb/signals.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif /* HAVE_STRING_H */ +#endif /* HAVE_STRINGS_H */ + +#ifdef HAVE_STDLIB_H +#include +#endif enum _leftright { LEFT_FIRST, RIGHT_FIRST }; int d10v_debug; -host_callback *d10v_callback; -long ins_type_counters[ (int)INS_MAX ]; -long left_nops, right_nops; + +/* Set this to true to get the previous segment layout. */ + +int old_segment_mapping; + +unsigned long ins_type_counters[ (int)INS_MAX ]; uint16 OP[4]; -static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); +static long hash (long insn, int format); +static struct hash_entry *lookup_hash (SIM_DESC, SIM_CPU *, uint32 ins, int size); +static void get_operands (struct simops *s, uint32 ins); +static void do_long (SIM_DESC, SIM_CPU *, uint32 ins); +static void do_2_short (SIM_DESC, SIM_CPU *, uint16 ins1, uint16 ins2, enum _leftright leftright); +static void do_parallel (SIM_DESC, SIM_CPU *, uint16 ins1, uint16 ins2); +static char *add_commas (char *buf, int sizeof_buf, unsigned long value); +static INLINE uint8 *map_memory (SIM_DESC, SIM_CPU *, unsigned phys_addr); #define MAX_HASH 63 struct hash_entry { struct hash_entry *next; - long opcode; - long mask; + uint32 opcode; + uint32 mask; + int size; struct simops *ops; }; struct hash_entry hash_table[MAX_HASH+1]; -static long -hash(insn, format) - long insn; - int format; +INLINE static long +hash (long insn, int format) { if (format & LONG_OPCODE) return ((insn & 0x3F000000) >> 24); @@ -41,10 +65,8 @@ hash(insn, format) return((insn & 0x7E00) >> 9); } -static struct hash_entry * -lookup_hash (ins, size) - uint32 ins; - int size; +INLINE static struct hash_entry * +lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint32 ins, int size) { struct hash_entry *h; @@ -53,82 +75,16 @@ lookup_hash (ins, size) else h = &hash_table[(ins & 0x7E00) >> 9]; - while ( (ins & h->mask) != h->opcode) + while ((ins & h->mask) != h->opcode || h->size != size) { if (h->next == NULL) - { - (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC); - exit(1); - } + sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGILL); h = h->next; } return (h); } -uint32 -get_longword (x) - uint8 *x; -{ - uint8 *a = x; - return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + (a[3]); -} - -int64 -get_longlong (x) - uint8 *x; -{ - uint8 *a = x; - return ((int64)a[0]<<56) + ((int64)a[1]<<48) + ((int64)a[2]<<40) + ((int64)a[3]<<32) + - ((int64)a[4]<< 24) + ((int64)a[5]<<16) + ((int64)a[6]<<8) + (int64)a[7]; -} - -uint16 -get_word (x) - uint8 *x; -{ - uint8 *a = x; - return ((uint16)a[0]<<8) + a[1]; -} - - -void -write_word (addr, data) - uint8 *addr; - uint16 data; -{ - uint8 *a = addr; - a[0] = data >> 8; - a[1] = data & 0xff; -} - -void -write_longword (addr, data) - uint8 *addr; - uint32 data; -{ - addr[0] = (data >> 24) & 0xff; - addr[1] = (data >> 16) & 0xff; - addr[2] = (data >> 8) & 0xff; - addr[3] = data & 0xff; -} - -void -write_longlong (addr, data) - uint8 *addr; - int64 data; -{ - uint8 *a = addr; - a[0] = data >> 56; - a[1] = (data >> 48) & 0xff; - a[2] = (data >> 40) & 0xff; - a[3] = (data >> 32) & 0xff; - a[4] = (data >> 24) & 0xff; - a[5] = (data >> 16) & 0xff; - a[6] = (data >> 8) & 0xff; - a[7] = data & 0xff; -} - -static void +INLINE static void get_operands (struct simops *s, uint32 ins) { int i, shift, bits, flags; @@ -141,407 +97,1273 @@ get_operands (struct simops *s, uint32 ins) mask = 0x7FFFFFFF >> (31 - bits); OP[i] = (ins >> shift) & mask; } + /* FIXME: for tracing, update values that need to be updated each + instruction decode cycle */ + State.trace.psw = PSW; } static void -do_long (ins) - uint32 ins; +do_long (SIM_DESC sd, SIM_CPU *cpu, uint32 ins) { struct hash_entry *h; #ifdef DEBUG if ((d10v_debug & DEBUG_INSTRUCTION) != 0) - (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins); + sim_io_printf (sd, "do_long 0x%x\n", ins); #endif - h = lookup_hash (ins, 1); + h = lookup_hash (sd, cpu, ins, 1); + if (h == NULL) + return; get_operands (h->ops, ins); State.ins_type = INS_LONG; ins_type_counters[ (int)State.ins_type ]++; - (h->ops->func)(); + (h->ops->func) (sd, cpu); } + static void -do_2_short (ins1, ins2, leftright) - uint16 ins1, ins2; - enum _leftright leftright; +do_2_short (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2, enum _leftright leftright) { struct hash_entry *h; + enum _ins_type first, second; + #ifdef DEBUG if ((d10v_debug & DEBUG_INSTRUCTION) != 0) - (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n", - ins1, (leftright) ? "left" : "right", ins2); + sim_io_printf (sd, "do_2_short 0x%x (%s) -> 0x%x\n", ins1, + leftright ? "left" : "right", ins2); #endif - /* printf ("do_2_short %x -> %x\n",ins1,ins2); */ - h = lookup_hash (ins1, 0); + + if (leftright == LEFT_FIRST) + { + first = INS_LEFT; + second = INS_RIGHT; + ins_type_counters[ (int)INS_LEFTRIGHT ]++; + } + else + { + first = INS_RIGHT; + second = INS_LEFT; + ins_type_counters[ (int)INS_RIGHTLEFT ]++; + } + + /* Issue the first instruction */ + h = lookup_hash (sd, cpu, ins1, 0); + if (h == NULL) + return; get_operands (h->ops, ins1); - State.ins_type = (leftright == LEFT_FIRST) ? INS_LEFT : INS_RIGHT; + State.ins_type = first; ins_type_counters[ (int)State.ins_type ]++; - (h->ops->func)(); - h = lookup_hash (ins2, 0); - get_operands (h->ops, ins2); - State.ins_type = (leftright == LEFT_FIRST) ? INS_RIGHT : INS_LEFT; - ins_type_counters[ (int)State.ins_type ]++; - (h->ops->func)(); + (h->ops->func) (sd, cpu); + + /* Issue the second instruction (if the PC hasn't changed) */ + if (!State.pc_changed) + { + /* finish any existing instructions */ + SLOT_FLUSH (); + h = lookup_hash (sd, cpu, ins2, 0); + if (h == NULL) + return; + get_operands (h->ops, ins2); + State.ins_type = second; + ins_type_counters[ (int)State.ins_type ]++; + ins_type_counters[ (int)INS_CYCLES ]++; + (h->ops->func) (sd, cpu); + } + else + ins_type_counters[ (int)INS_COND_JUMP ]++; } + static void -do_parallel (ins1, ins2) - uint16 ins1, ins2; +do_parallel (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2) { struct hash_entry *h1, *h2; #ifdef DEBUG if ((d10v_debug & DEBUG_INSTRUCTION) != 0) - (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2); + sim_io_printf (sd, "do_parallel 0x%x || 0x%x\n", ins1, ins2); #endif - h1 = lookup_hash (ins1, 0); - h2 = lookup_hash (ins2, 0); + ins_type_counters[ (int)INS_PARALLEL ]++; + h1 = lookup_hash (sd, cpu, ins1, 0); + if (h1 == NULL) + return; + h2 = lookup_hash (sd, cpu, ins2, 0); + if (h2 == NULL) + return; if (h1->ops->exec_type == PARONLY) { get_operands (h1->ops, ins1); - State.ins_type = INS_LEFT; + State.ins_type = INS_LEFT_COND_TEST; ins_type_counters[ (int)State.ins_type ]++; - (h1->ops->func)(); + (h1->ops->func) (sd, cpu); if (State.exe) { + ins_type_counters[ (int)INS_COND_TRUE ]++; get_operands (h2->ops, ins2); - State.ins_type = INS_RIGHT; - (h2->ops->func)(); + State.ins_type = INS_RIGHT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func) (sd, cpu); } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; } else if (h2->ops->exec_type == PARONLY) { get_operands (h2->ops, ins2); - State.ins_type = INS_RIGHT; + State.ins_type = INS_RIGHT_COND_TEST; ins_type_counters[ (int)State.ins_type ]++; - (h2->ops->func)(); + (h2->ops->func) (sd, cpu); if (State.exe) { + ins_type_counters[ (int)INS_COND_TRUE ]++; get_operands (h1->ops, ins1); - State.ins_type = INS_LEFT; - (h1->ops->func)(); + State.ins_type = INS_LEFT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func) (sd, cpu); } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; } else { get_operands (h1->ops, ins1); State.ins_type = INS_LEFT_PARALLEL; ins_type_counters[ (int)State.ins_type ]++; - (h1->ops->func)(); + (h1->ops->func) (sd, cpu); get_operands (h2->ops, ins2); State.ins_type = INS_RIGHT_PARALLEL; ins_type_counters[ (int)State.ins_type ]++; - (h2->ops->func)(); + (h2->ops->func) (sd, cpu); } } +static char * +add_commas (char *buf, int sizeof_buf, unsigned long value) +{ + int comma = 3; + char *endbuf = buf + sizeof_buf - 1; -void -sim_size (power) - int power; + *--endbuf = '\0'; + do { + if (comma-- == 0) + { + *--endbuf = ','; + comma = 2; + } + *--endbuf = (value % 10) + '0'; + } while ((value /= 10) != 0); + + return endbuf; +} + +static void +sim_size (int power) { - if (State.imem) + int i; + for (i = 0; i < IMEM_SEGMENTS; i++) + { + if (State.mem.insn[i]) + free (State.mem.insn[i]); + } + for (i = 0; i < DMEM_SEGMENTS; i++) { - free (State.imem); - free (State.dmem); + if (State.mem.data[i]) + free (State.mem.data[i]); } + for (i = 0; i < UMEM_SEGMENTS; i++) + { + if (State.mem.unif[i]) + free (State.mem.unif[i]); + } + /* Always allocate dmem segment 0. This contains the IMAP and DMAP + registers. */ + State.mem.data[0] = calloc (1, SEGMENT_SIZE); +} + +/* For tracing - leave info on last access around. */ +static char *last_segname = "invalid"; +static char *last_from = "invalid"; +static char *last_to = "invalid"; - State.imem = (uint8 *)calloc(1,1<printf_filtered) (d10v_callback, "Memory allocation failed.\n"); - exit(1); + sim_io_printf (sd, "mem: dmap%d=0x%04lx\n", reg_nr, value); } +#endif +} +static unsigned long +dmap_register (SIM_DESC sd, SIM_CPU *cpu, void *regcache, int reg_nr) +{ + uint8 *raw = map_memory (sd, cpu, SIM_D10V_MEMORY_DATA + + DMAP0_OFFSET + 2 * reg_nr); + return READ_16 (raw); +} + +static void +set_imap_register (SIM_DESC sd, int reg_nr, unsigned long value) +{ + uint8 *raw = map_memory (sd, NULL, SIM_D10V_MEMORY_DATA + + IMAP0_OFFSET + 2 * reg_nr); + WRITE_16 (raw, value); #ifdef DEBUG - if ((d10v_debug & DEBUG_MEMSIZE) != 0) + if ((d10v_debug & DEBUG_MEMORY)) { - (*d10v_callback->printf_filtered) (d10v_callback, "Allocated %d bytes instruction memory and\n",1<printf_filtered) (d10v_callback, " %d bytes data memory.\n", 1<printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%x\n",size,addr); */ - for (i = 0; i < size; i++) +static unsigned long +sim_d10v_translate_dmap_addr (SIM_DESC sd, + SIM_CPU *cpu, + unsigned long offset, + int nr_bytes, + unsigned long *phys, + void *regcache, + unsigned long (*dmap_register) (SIM_DESC, + SIM_CPU *, + void *regcache, + int reg_nr)) +{ + short map; + int regno; + last_from = "logical-data"; + if (offset >= DMAP_BLOCK_SIZE * SIM_D10V_NR_DMAP_REGS) { - State.imem[i+addr] = buffer[i]; + /* Logical address out side of data segments, not supported */ + return 0; } - return size; + regno = (offset / DMAP_BLOCK_SIZE); + offset = (offset % DMAP_BLOCK_SIZE); + if ((offset % DMAP_BLOCK_SIZE) + nr_bytes > DMAP_BLOCK_SIZE) + { + /* Don't cross a BLOCK boundary */ + nr_bytes = DMAP_BLOCK_SIZE - (offset % DMAP_BLOCK_SIZE); + } + map = dmap_register (sd, cpu, regcache, regno); + if (regno == 3) + { + /* Always maps to data memory */ + int iospi = (offset / 0x1000) % 4; + int iosp = (map >> (4 * (3 - iospi))) % 0x10; + last_to = "io-space"; + *phys = (SIM_D10V_MEMORY_DATA + (iosp * 0x10000) + 0xc000 + offset); + } + else + { + int sp = ((map & 0x3000) >> 12); + int segno = (map & 0x3ff); + switch (sp) + { + case 0: /* 00: Unified memory */ + *phys = SIM_D10V_MEMORY_UNIFIED + (segno * DMAP_BLOCK_SIZE) + offset; + last_to = "unified"; + break; + case 1: /* 01: Instruction Memory */ + *phys = SIM_D10V_MEMORY_INSN + (segno * DMAP_BLOCK_SIZE) + offset; + last_to = "chip-insn"; + break; + case 2: /* 10: Internal data memory */ + *phys = SIM_D10V_MEMORY_DATA + (segno << 16) + (regno * DMAP_BLOCK_SIZE) + offset; + last_to = "chip-data"; + break; + case 3: /* 11: Reserved */ + return 0; + } + } + return nr_bytes; } -void -sim_open (args) - char *args; -{ - struct simops *s; - struct hash_entry *h, *prev; - if (args != NULL) - (*d10v_callback->printf_filtered) (d10v_callback, "sim_open %s\n",args); +/* Given a virtual address in the IMAP address space, translate it + into a physical address. */ - /* put all the opcodes in the hash table */ - for (s = Simops; s->func; s++) +static unsigned long +sim_d10v_translate_imap_addr (SIM_DESC sd, + SIM_CPU *cpu, + unsigned long offset, + int nr_bytes, + unsigned long *phys, + void *regcache, + unsigned long (*imap_register) (SIM_DESC, + SIM_CPU *, + void *regcache, + int reg_nr)) +{ + short map; + int regno; + int sp; + int segno; + last_from = "logical-insn"; + if (offset >= (IMAP_BLOCK_SIZE * SIM_D10V_NR_IMAP_REGS)) { - h = &hash_table[hash(s->opcode,s->format)]; - - /* go to the last entry in the chain */ - while (h->next) - h = h->next; + /* Logical address outside of IMAP segments, not supported */ + return 0; + } + regno = (offset / IMAP_BLOCK_SIZE); + offset = (offset % IMAP_BLOCK_SIZE); + if (offset + nr_bytes > IMAP_BLOCK_SIZE) + { + /* Don't cross a BLOCK boundary */ + nr_bytes = IMAP_BLOCK_SIZE - offset; + } + map = imap_register (sd, cpu, regcache, regno); + sp = (map & 0x3000) >> 12; + segno = (map & 0x007f); + switch (sp) + { + case 0: /* 00: unified memory */ + *phys = SIM_D10V_MEMORY_UNIFIED + (segno << 17) + offset; + last_to = "unified"; + break; + case 1: /* 01: instruction memory */ + *phys = SIM_D10V_MEMORY_INSN + (IMAP_BLOCK_SIZE * regno) + offset; + last_to = "chip-insn"; + break; + case 2: /*10*/ + /* Reserved. */ + return 0; + case 3: /* 11: for testing - instruction memory */ + offset = (offset % 0x800); + *phys = SIM_D10V_MEMORY_INSN + offset; + if (offset + nr_bytes > 0x800) + /* don't cross VM boundary */ + nr_bytes = 0x800 - offset; + last_to = "test-insn"; + break; + } + return nr_bytes; +} - if (h->ops) +static unsigned long +sim_d10v_translate_addr (SIM_DESC sd, + SIM_CPU *cpu, + unsigned long memaddr, + int nr_bytes, + unsigned long *targ_addr, + void *regcache, + unsigned long (*dmap_register) (SIM_DESC, + SIM_CPU *, + void *regcache, + int reg_nr), + unsigned long (*imap_register) (SIM_DESC, + SIM_CPU *, + void *regcache, + int reg_nr)) +{ + unsigned long phys; + unsigned long seg; + unsigned long off; + + last_from = "unknown"; + last_to = "unknown"; + + seg = (memaddr >> 24); + off = (memaddr & 0xffffffL); + + /* However, if we've asked to use the previous generation of segment + mapping, rearrange the segments as follows. */ + + if (old_segment_mapping) + { + switch (seg) { - h->next = calloc(1,sizeof(struct hash_entry)); - h = h->next; + case 0x00: /* DMAP translated memory */ + seg = 0x10; + break; + case 0x01: /* IMAP translated memory */ + seg = 0x11; + break; + case 0x10: /* On-chip data memory */ + seg = 0x02; + break; + case 0x11: /* On-chip insn memory */ + seg = 0x01; + break; + case 0x12: /* Unified memory */ + seg = 0x00; + break; } - h->ops = s; - h->mask = s->mask; - h->opcode = s->opcode; } + + switch (seg) + { + case 0x00: /* Physical unified memory */ + last_from = "phys-unified"; + last_to = "unified"; + phys = SIM_D10V_MEMORY_UNIFIED + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x01: /* Physical instruction memory */ + last_from = "phys-insn"; + last_to = "chip-insn"; + phys = SIM_D10V_MEMORY_INSN + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x02: /* Physical data memory segment */ + last_from = "phys-data"; + last_to = "chip-data"; + phys = SIM_D10V_MEMORY_DATA + off; + if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE) + nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE); + break; + + case 0x10: /* in logical data address segment */ + nr_bytes = sim_d10v_translate_dmap_addr (sd, cpu, off, nr_bytes, &phys, + regcache, dmap_register); + break; + + case 0x11: /* in logical instruction address segment */ + nr_bytes = sim_d10v_translate_imap_addr (sd, cpu, off, nr_bytes, &phys, + regcache, imap_register); + break; + + default: + return 0; + } + + *targ_addr = phys; + return nr_bytes; } +/* Return a pointer into the raw buffer designated by phys_addr. It + is assumed that the client has already ensured that the access + isn't going to cross a segment boundary. */ -void -sim_close (quitting) - int quitting; +uint8 * +map_memory (SIM_DESC sd, SIM_CPU *cpu, unsigned phys_addr) { - /* nothing to do */ + uint8 **memory; + uint8 *raw; + unsigned offset; + int segment = ((phys_addr >> 24) & 0xff); + + switch (segment) + { + + case 0x00: /* Unified memory */ + { + memory = &State.mem.unif[(phys_addr / SEGMENT_SIZE) % UMEM_SEGMENTS]; + last_segname = "umem"; + break; + } + + case 0x01: /* On-chip insn memory */ + { + memory = &State.mem.insn[(phys_addr / SEGMENT_SIZE) % IMEM_SEGMENTS]; + last_segname = "imem"; + break; + } + + case 0x02: /* On-chip data memory */ + { + if ((phys_addr & 0xff00) == 0xff00) + { + phys_addr = (phys_addr & 0xffff); + if (phys_addr == DMAP2_SHADDOW) + { + phys_addr = DMAP2_OFFSET; + last_segname = "dmap"; + } + else + last_segname = "reg"; + } + else + last_segname = "dmem"; + memory = &State.mem.data[(phys_addr / SEGMENT_SIZE) % DMEM_SEGMENTS]; + break; + } + + default: + /* OOPS! */ + last_segname = "scrap"; + sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS); + } + + if (*memory == NULL) + *memory = xcalloc (1, SEGMENT_SIZE); + + offset = (phys_addr % SEGMENT_SIZE); + raw = *memory + offset; + return raw; } + +/* Transfer data to/from simulated memory. Since a bug in either the + simulated program or in gdb or the simulator itself may cause a + bogus address to be passed in, we need to do some sanity checking + on addresses to make sure they are within bounds. When an address + fails the bounds check, treat it as a zero length read/write rather + than aborting the entire run. */ -void -sim_set_profile (n) - int n; +static int +xfer_mem (SIM_DESC sd, + SIM_ADDR virt, + unsigned char *buffer, + int size, + int write_p) { - (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n); + uint8 *memory; + unsigned long phys; + int phys_size; + phys_size = sim_d10v_translate_addr (sd, NULL, virt, size, &phys, NULL, + dmap_register, imap_register); + if (phys_size == 0) + return 0; + + memory = map_memory (sd, NULL, phys); + +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + { + sim_io_printf + (sd, + "sim_%s %d bytes: 0x%08lx (%s) -> 0x%08lx (%s) -> 0x%08lx (%s)\n", + write_p ? "write" : "read", + phys_size, virt, last_from, + phys, last_to, + (long) memory, last_segname); + } +#endif + + if (write_p) + { + memcpy (memory, buffer, phys_size); + } + else + { + memcpy (buffer, memory, phys_size); + } + + return phys_size; } -void -sim_set_profile_size (n) - int n; + +int +sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size) { - (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n); + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem (sd, addr, buffer, size, 1); } -void -sim_resume (step, siggnal) - int step, siggnal; +int +sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size) { - uint32 inst; - int i; - reg_t oldpc; + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem (sd, addr, buffer, size, 0); +} -/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */ +static sim_cia +d10v_pc_get (sim_cpu *cpu) +{ + return PC; +} - if (step) - State.exception = SIGTRAP; - else - State.exception = 0; - - do - { - inst = RLW (PC << 2); - oldpc = PC; - switch (inst & 0xC0000000) - { - case 0xC0000000: - /* long instruction */ - do_long (inst & 0x3FFFFFFF); - break; - case 0x80000000: - /* R -> L */ - do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0); - break; - case 0x40000000: - /* L -> R */ - do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1); - break; - case 0: - do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); - break; - } - - if (State.RP && PC == RPT_E) - { - RPT_C -= 1; - if (RPT_C == 0) - State.RP = 0; - else - PC = RPT_S; - } - - /* FIXME */ - if (PC == oldpc) - PC++; - } - while (!State.exception); +static void +d10v_pc_set (sim_cpu *cpu, sim_cia pc) +{ + SIM_DESC sd = CPU_STATE (cpu); + SET_PC (pc); } -int -sim_trace () +static void +free_state (SIM_DESC sd) { -#ifdef DEBUG - d10v_debug = DEBUG; -#endif - sim_resume (0, 0); - return 1; + if (STATE_MODULES (sd) != NULL) + sim_module_uninstall (sd); + sim_cpu_free_all (sd); + sim_state_free (sd); } -void -sim_info (verbose) - int verbose; +static int d10v_reg_fetch (SIM_CPU *, int, unsigned char *, int); +static int d10v_reg_store (SIM_CPU *, int, unsigned char *, int); + +SIM_DESC +sim_open (SIM_OPEN_KIND kind, host_callback *cb, + struct bfd *abfd, char * const *argv) { - char buf[40]; - int size; - long total = (ins_type_counters[ (int)INS_LONG ] - + ins_type_counters[ (int)INS_LEFT ] - + ins_type_counters[ (int)INS_LEFT_PARALLEL ] - + ins_type_counters[ (int)INS_RIGHT ] - + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]); + struct simops *s; + struct hash_entry *h; + static int init_p = 0; + char **p; + int i; + SIM_DESC sd = sim_state_alloc (kind, cb); + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* The cpu data is kept in a separately allocated chunk of memory. */ + if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + { + free_state (sd); + return 0; + } - sprintf (buf, "%ld", total); - size = strlen (buf); + /* The parser will print an error message for us, so we silently return. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + /* Check for/establish the a reference program image. */ + if (sim_analyze_program (sd, + (STATE_PROG_ARGV (sd) != NULL + ? *STATE_PROG_ARGV (sd) + : NULL), abfd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + /* Configure/verify the target byte order and other runtime + configuration options. */ + if (sim_config (sd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } - (*d10v_callback->printf_filtered) (d10v_callback, - "executed %*ld instructions in the left container, %*ld parallel, %*ld nops\n", - size, ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_PARALLEL ], - size, ins_type_counters[ (int)INS_LEFT_PARALLEL ], - size, left_nops); + if (sim_post_argv_init (sd) != SIM_RC_OK) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } - (*d10v_callback->printf_filtered) (d10v_callback, - "executed %*ld instructions in the right container, %*ld parallel, %*ld nops\n", - size, ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_PARALLEL ], - size, ins_type_counters[ (int)INS_RIGHT_PARALLEL ], - size, right_nops); + /* CPU specific initialization. */ + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); - (*d10v_callback->printf_filtered) (d10v_callback, - "executed %*ld long instructions\n", - size, ins_type_counters[ (int)INS_LONG ]); + CPU_REG_FETCH (cpu) = d10v_reg_fetch; + CPU_REG_STORE (cpu) = d10v_reg_store; + CPU_PC_FETCH (cpu) = d10v_pc_get; + CPU_PC_STORE (cpu) = d10v_pc_set; + } - (*d10v_callback->printf_filtered) (d10v_callback, - "executed %*ld total instructions\n", - size, total); -} + old_segment_mapping = 0; -void -sim_create_inferior (start_address, argv, env) - SIM_ADDR start_address; - char **argv; - char **env; -{ + /* NOTE: This argument parsing is only effective when this function + is called by GDB. Standalone argument parsing is handled by + sim/common/run.c. */ + for (p = argv + 1; *p; ++p) + { + if (strcmp (*p, "-oldseg") == 0) + old_segment_mapping = 1; #ifdef DEBUG - if (d10v_debug) - (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%x\n", start_address); + else if (strcmp (*p, "-t") == 0) + d10v_debug = DEBUG; + else if (strncmp (*p, "-t", 2) == 0) + d10v_debug = atoi (*p + 2); #endif - PC = start_address >> 2; -} + } + + /* put all the opcodes in the hash table */ + if (!init_p++) + { + for (s = Simops; s->func; s++) + { + h = &hash_table[hash(s->opcode,s->format)]; + + /* go to the last entry in the chain */ + while (h->next) + h = h->next; + if (h->ops) + { + h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry)); + if (!h->next) + perror ("malloc failure"); -void -sim_kill () + h = h->next; + } + h->ops = s; + h->mask = s->mask; + h->opcode = s->opcode; + h->size = s->is_long; + } + } + + /* reset the processor state */ + if (!State.mem.data[0]) + sim_size (1); + + return sd; +} + +uint8 * +dmem_addr (SIM_DESC sd, SIM_CPU *cpu, uint16 offset) { - /* nothing to do */ + unsigned long phys; + uint8 *mem; + int phys_size; + + /* Note: DMEM address range is 0..0x10000. Calling code can compute + things like ``0xfffe + 0x0e60 == 0x10e5d''. Since offset's type + is uint16 this is modulo'ed onto 0x0e5d. */ + + phys_size = sim_d10v_translate_dmap_addr (sd, cpu, offset, 1, &phys, NULL, + dmap_register); + if (phys_size == 0) + sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS); + mem = map_memory (sd, cpu, phys); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + sim_io_printf + (sd, + "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n", + offset, last_from, + phys, phys_size, last_to, + (long) mem, last_segname); + } +#endif + return mem; } -void -sim_set_callbacks(p) - host_callback *p; +uint8 * +imem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset) { -/* printf ("sim_set_callbacks\n"); */ - d10v_callback = p; + unsigned long phys; + uint8 *mem; + int phys_size = sim_d10v_translate_imap_addr (sd, cpu, offset, 1, &phys, NULL, + imap_register); + if (phys_size == 0) + sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS); + mem = map_memory (sd, cpu, phys); +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMORY)) + { + sim_io_printf + (sd, + "mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n", + offset, last_from, + phys, phys_size, last_to, + (long) mem, last_segname); + } +#endif + return mem; } -void -sim_stop_reason (reason, sigrc) - enum sim_stop *reason; - int *sigrc; +static void +step_once (SIM_DESC sd, SIM_CPU *cpu) { -/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */ + uint32 inst; + uint8 *iaddr; - if (State.exception == SIGQUIT) + /* TODO: Unindent this block. */ { - *reason = sim_exited; - *sigrc = State.exception; + iaddr = imem_addr (sd, cpu, (uint32)PC << 2); + + inst = get_longword( iaddr ); + + State.pc_changed = 0; + ins_type_counters[ (int)INS_CYCLES ]++; + + switch (inst & 0xC0000000) + { + case 0xC0000000: + /* long instruction */ + do_long (sd, cpu, inst & 0x3FFFFFFF); + break; + case 0x80000000: + /* R -> L */ + do_2_short (sd, cpu, inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST); + break; + case 0x40000000: + /* L -> R */ + do_2_short (sd, cpu, (inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST); + break; + case 0: + do_parallel (sd, cpu, (inst & 0x3FFF8000) >> 15, inst & 0x7FFF); + break; + } + + /* If the PC of the current instruction matches RPT_E then + schedule a branch to the loop start. If one of those + instructions happens to be a branch, than that instruction + will be ignored */ + if (!State.pc_changed) + { + if (PSW_RP && PC == RPT_E) + { + /* Note: The behavour of a branch instruction at RPT_E + is implementation dependant, this simulator takes the + branch. Branching to RPT_E is valid, the instruction + must be executed before the loop is taken. */ + if (RPT_C == 1) + { + SET_PSW_RP (0); + SET_RPT_C (0); + SET_PC (PC + 1); + } + else + { + SET_RPT_C (RPT_C - 1); + SET_PC (RPT_S); + } + } + else + SET_PC (PC + 1); + } + + /* Check for a breakpoint trap on this instruction. This + overrides any pending branches or loops */ + if (PSW_DB && PC == IBA) + { + SET_BPC (PC); + SET_BPSW (PSW); + SET_PSW (PSW & PSW_SM_BIT); + SET_PC (SDBT_VECTOR_START); + } + + /* Writeback all the DATA / PC changes */ + SLOT_FLUSH (); } - else - { - *reason = sim_stopped; - *sigrc = State.exception; - } } void -sim_fetch_register (rn, memory) - int rn; - unsigned char *memory; +sim_engine_run (SIM_DESC sd, + int next_cpu_nr, /* ignore */ + int nr_cpus, /* ignore */ + int siggnal) { - if (rn > 31) + sim_cpu *cpu; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + cpu = STATE_CPU (sd, 0); + + switch (siggnal) { - WRITE_64 (memory, State.a[rn-32]); - /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */ + case 0: + break; + case GDB_SIGNAL_BUS: + SET_BPC (PC); + SET_BPSW (PSW); + SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (AE_VECTOR_START); + SLOT_FLUSH (); + break; + case GDB_SIGNAL_ILL: + SET_BPC (PC); + SET_BPSW (PSW); + SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (RIE_VECTOR_START); + SLOT_FLUSH (); + break; + default: + /* just ignore it */ + break; } - else + + while (1) { - WRITE_16 (memory, State.regs[rn]); - /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */ + step_once (sd, cpu); + if (sim_events_tick (sd)) + sim_events_process (sd); } } - + void -sim_store_register (rn, memory) - int rn; - unsigned char *memory; +sim_info (SIM_DESC sd, int verbose) { - if (rn > 31) + char buf1[40]; + char buf2[40]; + char buf3[40]; + char buf4[40]; + char buf5[40]; + unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ]; + unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ]; + unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ]; + unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ]; + unsigned long left_total = left + left_parallel + left_cond + left_nops; + + unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ]; + unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ]; + unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ]; + unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ]; + unsigned long right_total = right + right_parallel + right_cond + right_nops; + + unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ]; + unsigned long ins_long = ins_type_counters[ (int)INS_LONG ]; + unsigned long parallel = ins_type_counters[ (int)INS_PARALLEL ]; + unsigned long leftright = ins_type_counters[ (int)INS_LEFTRIGHT ]; + unsigned long rightleft = ins_type_counters[ (int)INS_RIGHTLEFT ]; + unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ]; + unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ]; + unsigned long cond_jump = ins_type_counters[ (int)INS_COND_JUMP ]; + unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ]; + unsigned long total = (unknown + left_total + right_total + ins_long); + + int size = strlen (add_commas (buf1, sizeof (buf1), total)); + int parallel_size = strlen (add_commas (buf1, sizeof (buf1), + (left_parallel > right_parallel) ? left_parallel : right_parallel)); + int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond)); + int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops)); + int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right)); + + sim_io_printf (sd, + "executed %*s left instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), left_total), + normal_size, add_commas (buf2, sizeof (buf2), left), + parallel_size, add_commas (buf3, sizeof (buf3), left_parallel), + cond_size, add_commas (buf4, sizeof (buf4), left_cond), + nop_size, add_commas (buf5, sizeof (buf5), left_nops)); + + sim_io_printf (sd, + "executed %*s right instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), right_total), + normal_size, add_commas (buf2, sizeof (buf2), right), + parallel_size, add_commas (buf3, sizeof (buf3), right_parallel), + cond_size, add_commas (buf4, sizeof (buf4), right_cond), + nop_size, add_commas (buf5, sizeof (buf5), right_nops)); + + if (ins_long) + sim_io_printf (sd, + "executed %*s long instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), ins_long)); + + if (parallel) + sim_io_printf (sd, + "executed %*s parallel instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), parallel)); + + if (leftright) + sim_io_printf (sd, + "executed %*s instruction(s) encoded L->R\n", + size, add_commas (buf1, sizeof (buf1), leftright)); + + if (rightleft) + sim_io_printf (sd, + "executed %*s instruction(s) encoded R->L\n", + size, add_commas (buf1, sizeof (buf1), rightleft)); + + if (unknown) + sim_io_printf (sd, + "executed %*s unknown instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), unknown)); + + if (cond_true) + sim_io_printf (sd, + "executed %*s instruction(s) due to EXExxx condition being true\n", + size, add_commas (buf1, sizeof (buf1), cond_true)); + + if (cond_false) + sim_io_printf (sd, + "skipped %*s instruction(s) due to EXExxx condition being false\n", + size, add_commas (buf1, sizeof (buf1), cond_false)); + + if (cond_jump) + sim_io_printf (sd, + "skipped %*s instruction(s) due to conditional branch succeeding\n", + size, add_commas (buf1, sizeof (buf1), cond_jump)); + + sim_io_printf (sd, + "executed %*s cycle(s)\n", + size, add_commas (buf1, sizeof (buf1), cycles)); + + sim_io_printf (sd, + "executed %*s total instructions\n", + size, add_commas (buf1, sizeof (buf1), total)); +} + +SIM_RC +sim_create_inferior (SIM_DESC sd, struct bfd *abfd, + char * const *argv, char * const *env) +{ + bfd_vma start_address; + + /* reset all state information */ + memset (&State.regs, 0, (uintptr_t)&State.mem - (uintptr_t)&State.regs); + + /* There was a hack here to copy the values of argc and argv into r0 + and r1. The values were also saved into some high memory that + won't be overwritten by the stack (0x7C00). The reason for doing + this was to allow the 'run' program to accept arguments. Without + the hack, this is not possible anymore. If the simulator is run + from the debugger, arguments cannot be passed in, so this makes + no difference. */ + + /* set PC */ + if (abfd != NULL) + start_address = bfd_get_start_address (abfd); + else + start_address = 0xffc0 << 2; +#ifdef DEBUG + if (d10v_debug) + sim_io_printf (sd, "sim_create_inferior: PC=0x%lx\n", (long) start_address); +#endif + { + SIM_CPU *cpu = STATE_CPU (sd, 0); + SET_CREG (PC_CR, start_address >> 2); + } + + /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board + initializes imap0 and imap1 to 0x1000 as part of its ROM + initialization. */ + if (old_segment_mapping) { - State.a[rn-32] = READ_64 (memory) & MASK40; - /* (*d10v_callback->printf_filtered) (d10v_callback, "store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */ + /* External memory startup. This is the HARD reset state. */ + set_imap_register (sd, 0, 0x0000); + set_imap_register (sd, 1, 0x007f); + set_dmap_register (sd, 0, 0x2000); + set_dmap_register (sd, 1, 0x2000); + set_dmap_register (sd, 2, 0x0000); /* Old DMAP */ + set_dmap_register (sd, 3, 0x0000); } else { - State.regs[rn]= READ_16 (memory); - /* (*d10v_callback->printf_filtered) (d10v_callback, "store: r%d=0x%x\n",rn,State.regs[rn]); */ + /* Internal memory startup. This is the ROM intialized state. */ + set_imap_register (sd, 0, 0x1000); + set_imap_register (sd, 1, 0x1000); + set_dmap_register (sd, 0, 0x2000); + set_dmap_register (sd, 1, 0x2000); + set_dmap_register (sd, 2, 0x2000); /* DMAP2 initial internal value is + 0x2000 on the new board. */ + set_dmap_register (sd, 3, 0x0000); } + + SLOT_FLUSH (); + return SIM_RC_OK; } -sim_read (addr, buffer, size) - SIM_ADDR addr; - unsigned char *buffer; - int size; +static int +d10v_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { - int i; - for (i = 0; i < size; i++) + SIM_DESC sd = CPU_STATE (cpu); + int size; + switch ((enum sim_d10v_regs) rn) { - buffer[i] = State.imem[addr + i]; + case SIM_D10V_R0_REGNUM: + case SIM_D10V_R1_REGNUM: + case SIM_D10V_R2_REGNUM: + case SIM_D10V_R3_REGNUM: + case SIM_D10V_R4_REGNUM: + case SIM_D10V_R5_REGNUM: + case SIM_D10V_R6_REGNUM: + case SIM_D10V_R7_REGNUM: + case SIM_D10V_R8_REGNUM: + case SIM_D10V_R9_REGNUM: + case SIM_D10V_R10_REGNUM: + case SIM_D10V_R11_REGNUM: + case SIM_D10V_R12_REGNUM: + case SIM_D10V_R13_REGNUM: + case SIM_D10V_R14_REGNUM: + case SIM_D10V_R15_REGNUM: + WRITE_16 (memory, GPR (rn - SIM_D10V_R0_REGNUM)); + size = 2; + break; + case SIM_D10V_CR0_REGNUM: + case SIM_D10V_CR1_REGNUM: + case SIM_D10V_CR2_REGNUM: + case SIM_D10V_CR3_REGNUM: + case SIM_D10V_CR4_REGNUM: + case SIM_D10V_CR5_REGNUM: + case SIM_D10V_CR6_REGNUM: + case SIM_D10V_CR7_REGNUM: + case SIM_D10V_CR8_REGNUM: + case SIM_D10V_CR9_REGNUM: + case SIM_D10V_CR10_REGNUM: + case SIM_D10V_CR11_REGNUM: + case SIM_D10V_CR12_REGNUM: + case SIM_D10V_CR13_REGNUM: + case SIM_D10V_CR14_REGNUM: + case SIM_D10V_CR15_REGNUM: + WRITE_16 (memory, CREG (rn - SIM_D10V_CR0_REGNUM)); + size = 2; + break; + case SIM_D10V_A0_REGNUM: + case SIM_D10V_A1_REGNUM: + WRITE_64 (memory, ACC (rn - SIM_D10V_A0_REGNUM)); + size = 8; + break; + case SIM_D10V_SPI_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + WRITE_16 (memory, spi_register ()); + size = 2; + break; + case SIM_D10V_SPU_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + WRITE_16 (memory, spu_register ()); + size = 2; + break; + case SIM_D10V_IMAP0_REGNUM: + case SIM_D10V_IMAP1_REGNUM: + WRITE_16 (memory, imap_register (sd, cpu, NULL, rn - SIM_D10V_IMAP0_REGNUM)); + size = 2; + break; + case SIM_D10V_DMAP0_REGNUM: + case SIM_D10V_DMAP1_REGNUM: + case SIM_D10V_DMAP2_REGNUM: + case SIM_D10V_DMAP3_REGNUM: + WRITE_16 (memory, dmap_register (sd, cpu, NULL, rn - SIM_D10V_DMAP0_REGNUM)); + size = 2; + break; + case SIM_D10V_TS2_DMAP_REGNUM: + size = 0; + break; + default: + size = 0; + break; } return size; -} - -void -sim_do_command (cmd) - char *cmd; -{ - (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd); } - -int -sim_load (prog, from_tty) - char *prog; - int from_tty; + +static int +d10v_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { - /* Return nonzero so GDB will handle it. */ - return 1; -} + SIM_DESC sd = CPU_STATE (cpu); + int size; + switch ((enum sim_d10v_regs) rn) + { + case SIM_D10V_R0_REGNUM: + case SIM_D10V_R1_REGNUM: + case SIM_D10V_R2_REGNUM: + case SIM_D10V_R3_REGNUM: + case SIM_D10V_R4_REGNUM: + case SIM_D10V_R5_REGNUM: + case SIM_D10V_R6_REGNUM: + case SIM_D10V_R7_REGNUM: + case SIM_D10V_R8_REGNUM: + case SIM_D10V_R9_REGNUM: + case SIM_D10V_R10_REGNUM: + case SIM_D10V_R11_REGNUM: + case SIM_D10V_R12_REGNUM: + case SIM_D10V_R13_REGNUM: + case SIM_D10V_R14_REGNUM: + case SIM_D10V_R15_REGNUM: + SET_GPR (rn - SIM_D10V_R0_REGNUM, READ_16 (memory)); + size = 2; + break; + case SIM_D10V_CR0_REGNUM: + case SIM_D10V_CR1_REGNUM: + case SIM_D10V_CR2_REGNUM: + case SIM_D10V_CR3_REGNUM: + case SIM_D10V_CR4_REGNUM: + case SIM_D10V_CR5_REGNUM: + case SIM_D10V_CR6_REGNUM: + case SIM_D10V_CR7_REGNUM: + case SIM_D10V_CR8_REGNUM: + case SIM_D10V_CR9_REGNUM: + case SIM_D10V_CR10_REGNUM: + case SIM_D10V_CR11_REGNUM: + case SIM_D10V_CR12_REGNUM: + case SIM_D10V_CR13_REGNUM: + case SIM_D10V_CR14_REGNUM: + case SIM_D10V_CR15_REGNUM: + SET_CREG (rn - SIM_D10V_CR0_REGNUM, READ_16 (memory)); + size = 2; + break; + case SIM_D10V_A0_REGNUM: + case SIM_D10V_A1_REGNUM: + SET_ACC (rn - SIM_D10V_A0_REGNUM, READ_64 (memory) & MASK40); + size = 8; + break; + case SIM_D10V_SPI_REGNUM: + /* PSW_SM indicates that the current SP is the USER + stack-pointer. */ + set_spi_register (READ_16 (memory)); + size = 2; + break; + case SIM_D10V_SPU_REGNUM: + set_spu_register (READ_16 (memory)); + size = 2; + break; + case SIM_D10V_IMAP0_REGNUM: + case SIM_D10V_IMAP1_REGNUM: + set_imap_register (sd, rn - SIM_D10V_IMAP0_REGNUM, READ_16(memory)); + size = 2; + break; + case SIM_D10V_DMAP0_REGNUM: + case SIM_D10V_DMAP1_REGNUM: + case SIM_D10V_DMAP2_REGNUM: + case SIM_D10V_DMAP3_REGNUM: + set_dmap_register (sd, rn - SIM_D10V_DMAP0_REGNUM, READ_16(memory)); + size = 2; + break; + case SIM_D10V_TS2_DMAP_REGNUM: + size = 0; + break; + default: + size = 0; + break; + } + SLOT_FLUSH (); + return size; +}