📄 interp.c
字号:
unsigned long *phys, void *regcache, unsigned long (*imap_register) (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)) { /* 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 (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;}unsigned longsim_d10v_translate_addr (unsigned long memaddr, int nr_bytes, unsigned long *targ_addr, void *regcache, unsigned long (*dmap_register) (void *regcache, int reg_nr), unsigned long (*imap_register) (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) { 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; } } 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 (off, nr_bytes, &phys, regcache, dmap_register); break; case 0x11: /* in logical instruction address segment */ nr_bytes = sim_d10v_translate_imap_addr (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. */uint8 *map_memory (unsigned phys_addr){ 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"; return State.mem.fault; } if (*memory == NULL) { *memory = calloc (1, SEGMENT_SIZE); if (*memory == NULL) { (*d10v_callback->printf_filtered) (d10v_callback, "Malloc failed.\n"); return State.mem.fault; } } 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. */static intxfer_mem (SIM_ADDR virt, unsigned char *buffer, int size, int write_p){ uint8 *memory; unsigned long phys; int phys_size; phys_size = sim_d10v_translate_addr (virt, size, &phys, NULL, dmap_register, imap_register); if (phys_size == 0) return 0; memory = map_memory (phys);#ifdef DEBUG if ((d10v_debug & DEBUG_INSTRUCTION) != 0) { (*d10v_callback->printf_filtered) (d10v_callback, "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;}intsim_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);}intsim_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_DESCsim_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; /* 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 else if (strcmp (*p, "-t") == 0) d10v_debug = DEBUG; else if (strncmp (*p, "-t", 2) == 0) d10v_debug = atoi (*p + 2);#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.mem.data[0]) sim_size (1); sim_create_inferior ((SIM_DESC) 1, NULL, NULL, NULL); /* Fudge our descriptor. */ return (SIM_DESC) 1;}voidsim_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; }}voidsim_set_profile (n) int n;{ (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n);}voidsim_set_profile_size (n) int n;{ (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n);}uint8 *dmem_addr (uint16 offset){ 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 (offset, 1, &phys, NULL, dmap_register); if (phys_size == 0) { mem = State.mem.fault; } else mem = map_memory (phys);#ifdef DEBUG if ((d10v_debug & DEBUG_MEMORY)) { (*d10v_callback->printf_filtered) (d10v_callback, "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;}uint8 *imem_addr (uint32 offset){ unsigned long phys; uint8 *mem; int phys_size = sim_d10v_translate_imap_addr (offset, 1, &phys, NULL, imap_register); if (phys_size == 0) { return State.mem.fault; } mem = map_memory (phys); #ifdef DEBUG if ((d10v_debug & DEBUG_MEMORY)) { (*d10v_callback->printf_filtered) (d10v_callback, "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;}static int stop_simulator = 0;intsim_stop (sd) SIM_DESC sd;{ stop_simulator = 1; return 1;}/* Run (or resume) the program. */voidsim_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); switch (siggnal) { case 0: break;#ifdef SIGBUS case SIGBUS:#endif case SIGSEGV: 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 SIGILL: 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; } do { iaddr = imem_addr ((uint32)PC << 2); if (iaddr == State.mem.fault) { State.exception = SIGBUS; break; } inst = get_longword( iaddr ); State.pc_changed = 0; ins_type_counters[ (int)INS_CYCLES ]++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -