📄 interp.c
字号:
#include <signal.h>#include "sysdep.h"#include "bfd.h"#include "gdb/callback.h"#include "gdb/remote-sim.h"#include "d10v_sim.h"#include "gdb/sim-d10v.h"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));static INLINE uint8 *map_memory (unsigned phys_addr);#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 (*deprecated_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 63struct 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) { State.exception = SIGILL; State.pc_changed = 1; /* Don't increment the PC. */ return NULL; } h = h->next; } return (h);}INLINE static voidget_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_vmadecode_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 voiddo_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); if (h == NULL) return; get_operands (h->ops, ins); State.ins_type = INS_LONG; ins_type_counters[ (int)State.ins_type ]++; (h->ops->func)();}static voiddo_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); if (h == NULL) return; 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); 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)(); } else if (!State.exception) ins_type_counters[ (int)INS_COND_JUMP ]++;}static voiddo_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); if (h1 == NULL) return; h2 = lookup_hash (ins2, 0); if (h2 == NULL) return; 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;}voidsim_size (power) int power;{ 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++) { 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";enum { IMAP0_OFFSET = 0xff00, DMAP0_OFFSET = 0xff08, DMAP2_SHADDOW = 0xff04, DMAP2_OFFSET = 0xff0c };static voidset_dmap_register (int reg_nr, unsigned long value){ uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + DMAP0_OFFSET + 2 * reg_nr); WRITE_16 (raw, value);#ifdef DEBUG if ((d10v_debug & DEBUG_MEMORY)) { (*d10v_callback->printf_filtered) (d10v_callback, "mem: dmap%d=0x%04lx\n", reg_nr, value); }#endif}static unsigned longdmap_register (void *regcache, int reg_nr){ uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + DMAP0_OFFSET + 2 * reg_nr); return READ_16 (raw);}static voidset_imap_register (int reg_nr, unsigned long value){ uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + IMAP0_OFFSET + 2 * reg_nr); WRITE_16 (raw, value);#ifdef DEBUG if ((d10v_debug & DEBUG_MEMORY)) { (*d10v_callback->printf_filtered) (d10v_callback, "mem: imap%d=0x%04lx\n", reg_nr, value); }#endif}static unsigned longimap_register (void *regcache, int reg_nr){ uint8 *raw = map_memory (SIM_D10V_MEMORY_DATA + IMAP0_OFFSET + 2 * reg_nr); return READ_16 (raw);}enum { HELD_SPI_IDX = 0, HELD_SPU_IDX = 1 };static unsigned longspu_register (void){ if (PSW_SM) return GPR (SP_IDX); else return HELD_SP (HELD_SPU_IDX);}static unsigned longspi_register (void){ if (!PSW_SM) return GPR (SP_IDX); else return HELD_SP (HELD_SPI_IDX);}static voidset_spi_register (unsigned long value){ if (!PSW_SM) SET_GPR (SP_IDX, value); SET_HELD_SP (HELD_SPI_IDX, value);}static voidset_spu_register (unsigned long value){ if (PSW_SM) SET_GPR (SP_IDX, value); SET_HELD_SP (HELD_SPU_IDX, value);}/* Given a virtual address in the DMAP address space, translate it into a physical address. */unsigned longsim_d10v_translate_dmap_addr (unsigned long offset, int nr_bytes, unsigned long *phys, void *regcache, unsigned long (*dmap_register) (void *regcache, int reg_nr)){ short map; int regno; last_from = "logical-data"; if (offset >= DMAP_BLOCK_SIZE * SIM_D10V_NR_DMAP_REGS) { /* Logical address out side of data segments, not supported */ return 0; } 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 (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;}/* Given a virtual address in the IMAP address space, translate it into a physical address. */unsigned longsim_d10v_translate_imap_addr (unsigned long offset, int nr_bytes,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -