#include #include "sysdep.h" #include "bfd.h" #include "callback.h" #include "remote-sim.h" #include "d10v_sim.h" #define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */ #define DMEM_SIZE 16 /* Data memory is 64K (but only 32K internal RAM) */ #define UMEM_SIZE 17 /* Each unified memory segment is 17 bits */ #define UMEM_SEGMENTS 128 /* Number of segments in unified memory region */ enum _leftright { LEFT_FIRST, RIGHT_FIRST }; static char *myname; static SIM_OPEN_KIND sim_kind; int d10v_debug; /* Set this to true to get the previous segment layout. */ int old_segment_mapping; host_callback *d10v_callback; unsigned long ins_type_counters[ (int)INS_MAX ]; uint16 OP[4]; static int init_text_p = 0; /* non-zero if we opened prog_bfd */ static int prog_bfd_was_opened_p; bfd *prog_bfd; asection *text; bfd_vma text_start; bfd_vma text_end; static long hash PARAMS ((long insn, int format)); static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); static void get_operands PARAMS ((struct simops *s, uint32 ins)); static void do_long PARAMS ((uint32 ins)); static void do_2_short PARAMS ((uint16 ins1, uint16 ins2, enum _leftright leftright)); static void do_parallel PARAMS ((uint16 ins1, uint16 ins2)); static char *add_commas PARAMS ((char *buf, int sizeof_buf, unsigned long value)); extern void sim_set_profile PARAMS ((int n)); extern void sim_set_profile_size PARAMS ((int n)); #ifdef NEED_UI_LOOP_HOOK /* How often to run the ui_loop update, when in use */ #define UI_LOOP_POLL_INTERVAL 0x14000 /* Counter for the ui_loop_hook update */ static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; /* Actual hook to call to run through gdb's gui event loop */ extern int (*ui_loop_hook) PARAMS ((int signo)); #endif /* NEED_UI_LOOP_HOOK */ #ifndef INLINE #if defined(__GNUC__) && defined(__OPTIMIZE__) #define INLINE __inline__ #else #define INLINE #endif #endif #define MAX_HASH 63 struct hash_entry { struct hash_entry *next; uint32 opcode; uint32 mask; int size; struct simops *ops; }; struct hash_entry hash_table[MAX_HASH+1]; INLINE static long hash(insn, format) long insn; int format; { if (format & LONG_OPCODE) return ((insn & 0x3F000000) >> 24); else return((insn & 0x7E00) >> 9); } INLINE static struct hash_entry * lookup_hash (ins, size) uint32 ins; int size; { struct hash_entry *h; if (size) h = &hash_table[(ins & 0x3F000000) >> 24]; else h = &hash_table[(ins & 0x7E00) >> 9]; 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); } h = h->next; } return (h); } INLINE static void get_operands (struct simops *s, uint32 ins) { int i, shift, bits, flags; uint32 mask; for (i=0; i < s->numops; i++) { shift = s->operands[3*i]; bits = s->operands[3*i+1]; flags = s->operands[3*i+2]; 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; } bfd_vma decode_pc () { asection *s; if (!init_text_p && prog_bfd != NULL) { init_text_p = 1; for (s = prog_bfd->sections; s; s = s->next) if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) { text = s; text_start = bfd_get_section_vma (prog_bfd, s); text_end = text_start + bfd_section_size (prog_bfd, s); break; } } return (PC << 2) + text_start; } static void do_long (ins) 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); #endif h = lookup_hash (ins, 1); get_operands (h->ops, ins); State.ins_type = INS_LONG; ins_type_counters[ (int)State.ins_type ]++; (h->ops->func)(); } static void do_2_short (ins1, ins2, leftright) uint16 ins1, 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); #endif 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 (ins1, 0); get_operands (h->ops, ins1); State.ins_type = first; ins_type_counters[ (int)State.ins_type ]++; (h->ops->func)(); /* Issue the second instruction (if the PC hasn't changed) */ if (!State.pc_changed && !State.exception) { /* finish any existing instructions */ SLOT_FLUSH (); h = lookup_hash (ins2, 0); 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)(); } else if (!State.exception) ins_type_counters[ (int)INS_COND_JUMP ]++; } static void do_parallel (ins1, ins2) uint16 ins1, 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); #endif ins_type_counters[ (int)INS_PARALLEL ]++; h1 = lookup_hash (ins1, 0); h2 = lookup_hash (ins2, 0); if (h1->ops->exec_type == PARONLY) { get_operands (h1->ops, ins1); State.ins_type = INS_LEFT_COND_TEST; ins_type_counters[ (int)State.ins_type ]++; (h1->ops->func)(); if (State.exe) { ins_type_counters[ (int)INS_COND_TRUE ]++; get_operands (h2->ops, ins2); State.ins_type = INS_RIGHT_COND_EXE; ins_type_counters[ (int)State.ins_type ]++; (h2->ops->func)(); } 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_COND_TEST; ins_type_counters[ (int)State.ins_type ]++; (h2->ops->func)(); if (State.exe) { ins_type_counters[ (int)INS_COND_TRUE ]++; get_operands (h1->ops, ins1); State.ins_type = INS_LEFT_COND_EXE; ins_type_counters[ (int)State.ins_type ]++; (h1->ops->func)(); } 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)(); if (!State.exception) { get_operands (h2->ops, ins2); State.ins_type = INS_RIGHT_PARALLEL; ins_type_counters[ (int)State.ins_type ]++; (h2->ops->func)(); } } } static char * add_commas(buf, sizeof_buf, value) char *buf; int sizeof_buf; unsigned long value; { int comma = 3; char *endbuf = buf + sizeof_buf - 1; *--endbuf = '\0'; do { if (comma-- == 0) { *--endbuf = ','; comma = 2; } *--endbuf = (value % 10) + '0'; } while ((value /= 10) != 0); return endbuf; } void sim_size (power) int power; { int i; if (State.imem) { for (i=0;iprintf_filtered) (d10v_callback, "Memory allocation failed.\n"); exit(1); } #ifdef DEBUG if ((d10v_debug & DEBUG_MEMSIZE) != 0) { char buffer[20]; (*d10v_callback->printf_filtered) (d10v_callback, "Allocated %s bytes instruction memory and\n", add_commas (buffer, sizeof (buffer), (1UL<printf_filtered) (d10v_callback, " %s bytes data memory.\n", add_commas (buffer, sizeof (buffer), (1UL<> 24) & 0xff); addr = (addr & 0x00ffffff); #ifdef DEBUG if ((d10v_debug & DEBUG_INSTRUCTION) != 0) { if (write_p) { (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%02x:%06x\n", size, segment, addr); } else { (*d10v_callback->printf_filtered) (d10v_callback, "sim_read %d bytes from 0x%2x:%6x\n", size, segment, addr); } } #endif /* To access data, we use the following mappings: 0x00xxxxxx: Physical unified memory segment (Unified memory) 0x01xxxxxx: Physical instruction memory segment (On-chip insn memory) 0x02xxxxxx: Physical data memory segment (On-chip data memory) 0x10xxxxxx: Logical data address segment (DMAP translated memory) 0x11xxxxxx: Logical instruction address segment (IMAP translated memory) Alternatively, the "old segment mapping" is still available by setting old_segment_mapping to 1. It looks like this: 0x00xxxxxx: Logical data address segment (DMAP translated memory) 0x01xxxxxx: Logical instruction address segment (IMAP translated memory) 0x10xxxxxx: Physical data memory segment (On-chip data memory) 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory) 0x12xxxxxx: Physical unified memory segment (Unified memory) */ /* However, if we've asked to use the previous generation of segment mapping, rearrange the segments as follows. */ if (old_segment_mapping) { switch (segment) { case 0x00: /* DMAP translated memory */ segment = 0x10; break; case 0x01: /* IMAP translated memory */ segment = 0x11; break; case 0x10: /* On-chip data memory */ segment = 0x02; break; case 0x11: /* On-chip insn memory */ segment = 0x01; break; case 0x12: /* Unified memory */ segment = 0x00; break; } } switch (segment) { case 0x10: /* DMAP translated memory */ { int byte; for (byte = 0; byte < size; byte++) { uint8 *mem = dmem_addr (addr + byte); if (mem == NULL) return byte; else if (write_p) *mem = buffer[byte]; else buffer[byte] = *mem; } return byte; } case 0x11: /* IMAP translated memory */ { int byte; for (byte = 0; byte < size; byte++) { uint8 *mem = imem_addr (addr + byte); if (mem == NULL) return byte; else if (write_p) *mem = buffer[byte]; else buffer[byte] = *mem; } return byte; } case 0x02: /* On-chip data memory */ { addr &= ((1 << DMEM_SIZE) - 1); if ((addr + size) > (1 << DMEM_SIZE)) { (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: data address 0x%x is outside range 0-0x%x.\n", addr + size - 1, (1 << DMEM_SIZE) - 1); return (0); } memory = State.dmem + addr; break; } case 0x01: /* On-chip insn memory */ { addr &= ((1 << IMEM_SIZE) - 1); if ((addr + size) > (1 << IMEM_SIZE)) { (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: instruction address 0x%x is outside range 0-0x%x.\n", addr + size - 1, (1 << IMEM_SIZE) - 1); return (0); } memory = State.imem + addr; break; } case 0x00: /* Unified memory */ { int startsegment, startoffset; /* Segment and offset within segment where xfer starts */ int endsegment, endoffset; /* Segment and offset within segment where xfer ends */ startsegment = addr >> UMEM_SIZE; startoffset = addr & ((1 << UMEM_SIZE) - 1); endsegment = (addr + size) >> UMEM_SIZE; endoffset = (addr + size) & ((1 << UMEM_SIZE) - 1); /* FIXME: We do not currently implement xfers across segments, so detect this case and fail gracefully. */ if ((startsegment != endsegment) && !((endsegment == (startsegment + 1)) && endoffset == 0)) { (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: Unimplemented support for transfers across unified memory segment boundaries\n"); return (0); } if (!State.umem[startsegment]) { #ifdef DEBUG if ((d10v_debug & DEBUG_MEMSIZE) != 0) { (*d10v_callback->printf_filtered) (d10v_callback,"Allocating %s bytes unified memory to region %d\n", add_commas (buffer, sizeof (buffer), (1UL<printf_filtered) (d10v_callback, "ERROR: Memory allocation of 0x%x bytes failed.\n", 1<printf_filtered) (d10v_callback, "ERROR: address 0x%lx is not in valid range\n", (long) addr); if (old_segment_mapping) { (*d10v_callback->printf_filtered) (d10v_callback, "0x00xxxxxx: Logical data address segment (DMAP translated memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x01xxxxxx: Logical instruction address segment (IMAP translated memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x10xxxxxx: Physical data memory segment (On-chip data memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x12xxxxxx: Phisical unified memory segment (Unified memory)\n"); } else { (*d10v_callback->printf_filtered) (d10v_callback, "0x00xxxxxx: Physical unified memory segment (Unified memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x01xxxxxx: Physical instruction memory segment (On-chip insn memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x02xxxxxx: Physical data memory segment (On-chip data memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x10xxxxxx: Logical data address segment (DMAP translated memory)\n"); (*d10v_callback->printf_filtered) (d10v_callback, "0x11xxxxxx: Logical instruction address segment (IMAP translated memory)\n"); } return (0); } } if (write_p) { memcpy (memory, buffer, size); } else { memcpy (buffer, memory, size); } return size; } int sim_write (sd, addr, buffer, size) SIM_DESC sd; SIM_ADDR addr; unsigned char *buffer; int size; { /* FIXME: this should be performing a virtual transfer */ return xfer_mem( addr, buffer, size, 1); } int sim_read (sd, addr, buffer, size) SIM_DESC sd; SIM_ADDR addr; unsigned char *buffer; int size; { /* FIXME: this should be performing a virtual transfer */ return xfer_mem( addr, buffer, size, 0); } SIM_DESC sim_open (kind, callback, abfd, argv) SIM_OPEN_KIND kind; host_callback *callback; struct _bfd *abfd; char **argv; { struct simops *s; struct hash_entry *h; static int init_p = 0; char **p; sim_kind = kind; d10v_callback = callback; myname = argv[0]; old_segment_mapping = 0; for (p = argv + 1; *p; ++p) { if (strcmp (*p, "-oldseg") == 0) old_segment_mapping = 1; #ifdef DEBUG else if (strcmp (*p, "-t") == 0) d10v_debug = DEBUG; #endif else (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",*p); } /* 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"); 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.imem) sim_size(1); sim_create_inferior ((SIM_DESC) 1, NULL, NULL, NULL); /* Fudge our descriptor. */ return (SIM_DESC) 1; } void sim_close (sd, quitting) SIM_DESC sd; int quitting; { if (prog_bfd != NULL && prog_bfd_was_opened_p) { bfd_close (prog_bfd); prog_bfd = NULL; prog_bfd_was_opened_p = 0; } } void sim_set_profile (n) int n; { (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n); } void sim_set_profile_size (n) int n; { (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n); } uint8 * dmem_addr( addr ) uint32 addr; { int seg; addr &= 0xffff; if (addr > 0xbfff) { if ( (addr & 0xfff0) != 0xff00) { (*d10v_callback->printf_filtered) (d10v_callback, "Data address 0x%lx is in I/O space, pc = 0x%lx.\n", (long)addr, (long)decode_pc ()); State.exception = SIGBUS; } return State.dmem + addr; } if (addr > 0x7fff) { if (DMAP & 0x1000) { /* instruction memory */ return (DMAP & 0xf) * 0x4000 + State.imem + (addr - 0x8000); } else { /* unified memory */ /* this is ugly because we allocate unified memory in 128K segments and */ /* dmap addresses 16k segments */ seg = (DMAP & 0x3ff) >> 3; if (State.umem[seg] == NULL) { #ifdef DEBUG (*d10v_callback->printf_filtered) (d10v_callback,"Allocating %d bytes unified memory to region %d\n", 1<printf_filtered) (d10v_callback, "ERROR: alloc failed. unified memory region %d unmapped, pc = 0x%lx\n", seg, (long)decode_pc ()); State.exception = SIGBUS; } } return State.umem[seg] + (DMAP & 7) * 0x4000 + (addr - 0x8000); } } return State.dmem + addr; } uint8 * imem_addr (uint32 pc) { uint16 imap; if (pc & 0x20000) imap = IMAP1; else imap = IMAP0; if (imap & 0x1000) return State.imem + pc; if (State.umem[imap & 0xff] == NULL) return 0; /* Discard upper bit(s) of PC in case IMAP1 selects unified memory. */ pc &= (1 << UMEM_SIZE) - 1; return State.umem[imap & 0xff] + pc; } static int stop_simulator = 0; int sim_stop (sd) SIM_DESC sd; { stop_simulator = 1; return 1; } /* Run (or resume) the program. */ void sim_resume (sd, step, siggnal) SIM_DESC sd; int step, siggnal; { uint32 inst; uint8 *iaddr; /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */ State.exception = 0; if (step) sim_stop (sd); do { iaddr = imem_addr ((uint32)PC << 2); if (iaddr == NULL) { State.exception = SIGBUS; break; } inst = get_longword( iaddr ); State.pc_changed = 0; ins_type_counters[ (int)INS_CYCLES ]++; switch (inst & 0xC0000000) { case 0xC0000000: /* long instruction */ do_long (inst & 0x3FFFFFFF); break; case 0x80000000: /* R -> L */ do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST); break; case 0x40000000: /* L -> R */ do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST); break; case 0: do_parallel ((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 (); #ifdef NEED_UI_LOOP_HOOK if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0) { ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; ui_loop_hook (0); } #endif /* NEED_UI_LOOP_HOOK */ } while ( !State.exception && !stop_simulator); if (step && !State.exception) State.exception = SIGTRAP; } int sim_trace (sd) SIM_DESC sd; { #ifdef DEBUG d10v_debug = DEBUG; #endif sim_resume (sd, 0, 0); return 1; } void sim_info (sd, verbose) SIM_DESC sd; int verbose; { 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)); (*d10v_callback->printf_filtered) (d10v_callback, "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)); (*d10v_callback->printf_filtered) (d10v_callback, "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) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s long instruction(s)\n", size, add_commas (buf1, sizeof (buf1), ins_long)); if (parallel) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s parallel instruction(s)\n", size, add_commas (buf1, sizeof (buf1), parallel)); if (leftright) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s instruction(s) encoded L->R\n", size, add_commas (buf1, sizeof (buf1), leftright)); if (rightleft) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s instruction(s) encoded R->L\n", size, add_commas (buf1, sizeof (buf1), rightleft)); if (unknown) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s unknown instruction(s)\n", size, add_commas (buf1, sizeof (buf1), unknown)); if (cond_true) (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s instruction(s) due to EXExxx condition being true\n", size, add_commas (buf1, sizeof (buf1), cond_true)); if (cond_false) (*d10v_callback->printf_filtered) (d10v_callback, "skipped %*s instruction(s) due to EXExxx condition being false\n", size, add_commas (buf1, sizeof (buf1), cond_false)); if (cond_jump) (*d10v_callback->printf_filtered) (d10v_callback, "skipped %*s instruction(s) due to conditional branch succeeding\n", size, add_commas (buf1, sizeof (buf1), cond_jump)); (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s cycle(s)\n", size, add_commas (buf1, sizeof (buf1), cycles)); (*d10v_callback->printf_filtered) (d10v_callback, "executed %*s total instructions\n", size, add_commas (buf1, sizeof (buf1), total)); } SIM_RC sim_create_inferior (sd, abfd, argv, env) SIM_DESC sd; struct _bfd *abfd; char **argv; char **env; { bfd_vma start_address; /* reset all state information */ memset (&State.regs, 0, (int)&State.imem - (int)&State.regs[0]); if (argv) { /* a hack to set r0/r1 with argc/argv */ /* some high memory that won't be overwritten by the stack soon */ bfd_vma addr = 0x7C00; int p = 20; int i = 0; while (argv[i]) { int size = strlen (argv[i]) + 1; SW (addr + 2*i, addr + p); sim_write (sd, addr + 0, argv[i], size); p += size; i++; } SET_GPR (0, addr); SET_GPR (1, i); } /* set PC */ if (abfd != NULL) start_address = bfd_get_start_address (abfd); else start_address = 0xffc0 << 2; #ifdef DEBUG if (d10v_debug) (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%lx\n", (long) start_address); #endif SET_CREG (PC_CR, start_address >> 2); /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board */ /* resets imap0 and imap1 to 0x1000. */ if (old_segment_mapping) { SET_IMAP0 (0x0000); SET_IMAP1 (0x007f); SET_DMAP (0x0000); } else { SET_IMAP0 (0x1000); SET_IMAP1 (0x1000); SET_DMAP(0); } SLOT_FLUSH (); return SIM_RC_OK; } void sim_set_callbacks (p) host_callback *p; { d10v_callback = p; } void sim_stop_reason (sd, reason, sigrc) SIM_DESC sd; enum sim_stop *reason; int *sigrc; { /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */ switch (State.exception) { case SIG_D10V_STOP: /* stop instruction */ *reason = sim_exited; *sigrc = 0; break; case SIG_D10V_EXIT: /* exit trap */ *reason = sim_exited; *sigrc = GPR (0); break; default: /* some signal */ *reason = sim_stopped; if (stop_simulator && !State.exception) *sigrc = SIGINT; else *sigrc = State.exception; break; } stop_simulator = 0; } int sim_fetch_register (sd, rn, memory, length) SIM_DESC sd; int rn; unsigned char *memory; int length; { if (rn > 34) WRITE_64 (memory, ACC (rn-35)); else if (rn == 32) WRITE_16 (memory, IMAP0); else if (rn == 33) WRITE_16 (memory, IMAP1); else if (rn == 34) WRITE_16 (memory, DMAP); else if (rn >= 16) WRITE_16 (memory, CREG (rn - 16)); else WRITE_16 (memory, GPR (rn)); return -1; } int sim_store_register (sd, rn, memory, length) SIM_DESC sd; int rn; unsigned char *memory; int length; { if (rn > 34) SET_ACC (rn-35, READ_64 (memory) & MASK40); else if (rn == 34) SET_DMAP( READ_16(memory) ); else if (rn == 33) SET_IMAP1( READ_16(memory) ); else if (rn == 32) SET_IMAP0( READ_16(memory) ); else if (rn >= 16) SET_CREG (rn - 16, READ_16 (memory)); else SET_GPR (rn, READ_16 (memory)); SLOT_FLUSH (); return -1; } void sim_do_command (sd, cmd) SIM_DESC sd; char *cmd; { (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd); } SIM_RC sim_load (sd, prog, abfd, from_tty) SIM_DESC sd; char *prog; bfd *abfd; int from_tty; { extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ if (prog_bfd != NULL && prog_bfd_was_opened_p) { bfd_close (prog_bfd); prog_bfd_was_opened_p = 0; } prog_bfd = sim_load_file (sd, myname, d10v_callback, prog, abfd, sim_kind == SIM_OPEN_DEBUG, 1/*LMA*/, sim_write); if (prog_bfd == NULL) return SIM_RC_FAIL; prog_bfd_was_opened_p = abfd == NULL; return SIM_RC_OK; }