diff options
Diffstat (limited to 'sim/v850/interp.c')
-rw-r--r-- | sim/v850/interp.c | 459 |
1 files changed, 120 insertions, 339 deletions
diff --git a/sim/v850/interp.c b/sim/v850/interp.c index 49b2996..e77cb48 100644 --- a/sim/v850/interp.c +++ b/sim/v850/interp.c @@ -17,13 +17,24 @@ #include "bfd.h" +#ifndef INLINE +#ifdef __GNUC__ +#define INLINE inline +#else +#define INLINE +#endif +#endif + /* For compatibility */ SIM_DESC simulator; + + +/* v850 interrupt model */ + enum interrupt_type { - int_none, int_reset, int_nmi, int_intov1, @@ -35,26 +46,7 @@ enum interrupt_type num_int_types }; -enum interrupt_cond_type -{ - int_cond_none, - int_cond_pc, - int_cond_time -}; - -struct interrupt_generator -{ - enum interrupt_type type; - enum interrupt_cond_type cond_type; - int number; - SIM_ADDR address; - unsigned long time; - int enabled; - struct interrupt_generator *next; -}; - char *interrupt_names[] = { - "", "reset", "nmi", "intov1", @@ -66,20 +58,82 @@ char *interrupt_names[] = { NULL }; -struct interrupt_generator *intgen_list; - -/* True if a non-maskable (such as NMI or reset) interrupt generator - is present. */ - -static int have_nm_generator; - -#ifndef INLINE -#ifdef __GNUC__ -#define INLINE inline -#else -#define INLINE -#endif -#endif +static void +do_interrupt (sd, data) + SIM_DESC sd; + void *data; +{ + enum interrupt_type inttype = *(int*)data; + /* Disable further interrupts. */ + PSW |= PSW_ID; + /* Indicate that we're doing interrupt not exception processing. */ + PSW &= ~PSW_EP; + if (inttype == int_reset) + { + PC = 0; + PSW = 0x20; + ECR = 0; + /* (Might be useful to init other regs with random values.) */ + } + else if (inttype == int_nmi) + { + if (PSW & PSW_NP) + { + /* We're already working on an NMI, so this one must wait + around until the previous one is done. The processor + ignores subsequent NMIs, so we don't need to count them. */ + State.pending_nmi = 1; + } + else + { + FEPC = PC; + FEPSW = PSW; + /* Set the FECC part of the ECR. */ + ECR &= 0x0000ffff; + ECR |= 0x10; + PSW |= PSW_NP; + PC = 0x10; + } + } + else + { + EIPC = PC; + EIPSW = PSW; + /* Clear the EICC part of the ECR, will set below. */ + ECR &= 0xffff0000; + switch (inttype) + { + case int_intov1: + PC = 0x80; + ECR |= 0x80; + break; + case int_intp10: + PC = 0x90; + ECR |= 0x90; + break; + case int_intp11: + PC = 0xa0; + ECR |= 0xa0; + break; + case int_intp12: + PC = 0xb0; + ECR |= 0xb0; + break; + case int_intp13: + PC = 0xc0; + ECR |= 0xc0; + break; + case int_intcm4: + PC = 0xd0; + ECR |= 0xd0; + break; + default: + /* Should never be possible. */ + abort (); + break; + } + } +} /* These default values correspond to expected usage for the chip. */ @@ -87,7 +141,6 @@ int v850_debug; uint32 OP[4]; -static struct hash_entry *lookup_hash PARAMS ((SIM_DESC sd, uint32 ins)); static long hash PARAMS ((long)); #if 0 static void do_format_1_2 PARAMS ((uint32)); @@ -134,6 +187,7 @@ hash(insn) return (insn & 0x07e0) >> 5; } +#if 0 static struct hash_entry * lookup_hash (sd, ins) SIM_DESC sd; @@ -154,6 +208,7 @@ lookup_hash (sd, ins) } return (h); } +#endif SIM_DESC sim_open (kind, cb, abfd, argv) @@ -164,12 +219,20 @@ sim_open (kind, cb, abfd, argv) { char *buf; SIM_DESC sd = sim_state_alloc (kind, cb); +#if 0 struct simops *s; struct hash_entry *h; +#endif /* for compatibility */ simulator = sd; + /* FIXME: should be better way of setting up interrupts */ + STATE_WATCHPOINTS (sd)->pc = &(PC); + STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); + STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt; + STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names; + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) return 0; @@ -224,6 +287,7 @@ sim_open (kind, cb, abfd, argv) return 0; } +#if 0 /* put all the opcodes in the hash table */ for (s = Simops; s->func; s++) { @@ -242,6 +306,7 @@ sim_open (kind, cb, abfd, argv) h->mask = s->mask; h->opcode = s->opcode; } +#endif return sd; } @@ -255,8 +320,6 @@ sim_close (sd, quitting) sim_module_uninstall (sd); } -static void do_interrupt PARAMS ((SIM_DESC sd, enum interrupt_type)); - int sim_stop (sd) SIM_DESC sd; @@ -264,25 +327,17 @@ sim_stop (sd) return 0; } +#if 0 void -sim_resume (sd, step, siggnal) +sim_engine_run (sd, next_cpu_nr, siggnal) SIM_DESC sd; - int step, siggnal; + int next_cpu_nr; + int siggnal; { - SIM_ELAPSED_TIME start_time; uint32 inst; SIM_ADDR oldpc; - struct interrupt_generator *intgen; - - if (step) - State.exception = SIGTRAP; - else - State.exception = 0; - - start_time = sim_elapsed_time_get (); - - do + while (1) { struct hash_entry * h; /* Fetch the current instruction. */ @@ -311,118 +366,15 @@ sim_resume (sd, step, siggnal) break; } - /* Check for and handle pending interrupts. */ - if (intgen_list && (have_nm_generator || !(PSW & PSW_ID))) - { - intgen = NULL; - for (intgen = intgen_list; intgen != NULL; intgen = intgen->next) - { - if (intgen->cond_type == int_cond_pc - && oldpc == intgen->address - && intgen->enabled) - { - break; - } - else if (intgen->cond_type == int_cond_time - && intgen->enabled) - { - SIM_ELAPSED_TIME delta; - delta = sim_elapsed_time_since (start_time); - if (delta > intgen->time) - { - intgen->enabled = 0; - break; - } - } - } - if (intgen) - do_interrupt (sd, intgen->type); - } - else if (State.pending_nmi) - { - State.pending_nmi = 0; - do_interrupt (sd, int_nmi); - } - } - while (!State.exception); -} - -static void -do_interrupt (sd, inttype) - SIM_DESC sd; - enum interrupt_type inttype; -{ - /* Disable further interrupts. */ - PSW |= PSW_ID; - /* Indicate that we're doing interrupt not exception processing. */ - PSW &= ~PSW_EP; - if (inttype == int_reset) - { - PC = 0; - PSW = 0x20; - ECR = 0; - /* (Might be useful to init other regs with random values.) */ - } - else if (inttype == int_nmi) - { - if (PSW & PSW_NP) - { - /* We're already working on an NMI, so this one must wait - around until the previous one is done. The processor - ignores subsequent NMIs, so we don't need to count them. */ - State.pending_nmi = 1; - } - else - { - FEPC = PC; - FEPSW = PSW; - /* Set the FECC part of the ECR. */ - ECR &= 0x0000ffff; - ECR |= 0x10; - PSW |= PSW_NP; - PC = 0x10; - } - } - else - { - EIPC = PC; - EIPSW = PSW; - /* Clear the EICC part of the ECR, will set below. */ - ECR &= 0xffff0000; - switch (inttype) + if (sim_events_tick (sd)) { - case int_intov1: - PC = 0x80; - ECR |= 0x80; - break; - case int_intp10: - PC = 0x90; - ECR |= 0x90; - break; - case int_intp11: - PC = 0xa0; - ECR |= 0xa0; - break; - case int_intp12: - PC = 0xb0; - ECR |= 0xb0; - break; - case int_intp13: - PC = 0xc0; - ECR |= 0xc0; - break; - case int_intcm4: - PC = 0xd0; - ECR |= 0xd0; - break; - default: - /* Should never be possible. */ - abort (); - break; + sim_events_process (sd); } } } +#endif +#if 0 int sim_trace (sd) SIM_DESC sd; @@ -433,13 +385,14 @@ sim_trace (sd) sim_resume (sd, 0, 0); return 1; } +#endif void sim_info (sd, verbose) SIM_DESC sd; int verbose; { - sim_io_printf (sd, "sim_info\n"); + /* do nothing */ } SIM_RC @@ -455,28 +408,6 @@ sim_create_inferior (sd, prog_bfd, argv, env) return SIM_RC_OK; } -/* All the code for exiting, signals, etc needs to be revamped. - - This is enough to get c-torture limping though. */ - -void -sim_stop_reason (sd, reason, sigrc) - SIM_DESC sd; - enum sim_stop *reason; - int *sigrc; -{ - if (State.exception == SIG_V850_EXIT) - { - *reason = sim_exited; - *sigrc = State.regs[7]; - } - else - { - *reason = sim_stopped; - *sigrc = State.exception; - } -} - void sim_fetch_register (sd, rn, memory) SIM_DESC sd; @@ -495,156 +426,6 @@ sim_store_register (sd, rn, memory) State.regs[rn] = T2H_4 (*(unsigned32*)memory); } -static int -sim_parse_number (str, rest) - char *str, **rest; -{ - if (str[0] == '0' && str[1] == 'x') - return strtoul (str, rest, 16); - else if (str[0] == '0') - return strtoul (str, rest, 16); - else - return strtoul (str, rest, 10); -} - -int current_intgen_number = 1; - -static void -sim_set_interrupt (sd, spec) - SIM_DESC sd; - char *spec; -{ - int i, num; - char **argv; - struct interrupt_generator *intgen, *tmpgen; - extern char **buildargv (); - - argv = buildargv (spec); - - if (*argv && ! strcmp (*argv, "add")) - { - /* Create a new interrupt generator object. */ - intgen = (struct interrupt_generator *) - malloc (sizeof(struct interrupt_generator)); - intgen->type = int_none; - intgen->cond_type = int_cond_none; - intgen->address = 0; - intgen->time = 0; - intgen->enabled = 0; - ++argv; - /* Match on interrupt type name. */ - for (i = 0; i < num_int_types; ++i) - { - if (*argv && ! strcmp (*argv, interrupt_names[i])) - { - intgen->type = i; - break; - } - } - if (intgen->type == int_none) - { - sim_io_printf (sd, "Interrupt type unknown; known types are\n"); - for (i = 0; i < num_int_types; ++i) - { - sim_io_printf (sd, " %s", interrupt_names[i]); - } - sim_io_printf (sd, "\n"); - free (intgen); - return; - } - ++argv; - intgen->address = 0; - intgen->time = 0; - if (*argv && ! strcmp (*argv, "pc")) - { - intgen->cond_type = int_cond_pc; - ++argv; - intgen->address = sim_parse_number (*argv, NULL); - } - else if (*argv && ! strcmp (*argv, "time")) - { - intgen->cond_type = int_cond_time; - ++argv; - intgen->time = sim_parse_number (*argv, NULL); - } - else - { - sim_io_printf (sd, "Condition type must be `pc' or `time'.\n"); - free (intgen); - return; - } - /* We now have a valid interrupt generator. Number it and add - to the list of generators. */ - intgen->number = current_intgen_number++; - intgen->enabled = 1; - intgen->next = intgen_list; - intgen_list = intgen; - sim_io_printf (sd, "Interrupt generator %d (NMI) at pc=0x%x, time=%ld.\n", intgen_list->number, intgen_list->address, intgen_list->time); - } - else if (*argv && !strcmp (*argv, "remove")) - { - ++argv; - num = sim_parse_number (*argv, NULL); - tmpgen = NULL; - if (intgen_list) - { - if (intgen_list->number == num) - { - tmpgen = intgen_list; - intgen_list = intgen_list->next; - } - else - { - for (intgen = intgen_list; intgen != NULL; intgen = intgen->next) - { - if (intgen->next != NULL && intgen->next->number == num) - { - tmpgen = intgen->next; - intgen->next = intgen->next->next; - break; - } - } - } - if (tmpgen) - free (tmpgen); - else - sim_io_printf (sd, "No interrupt generator numbered %d, ignoring.\n", num); - } - } - else if (*argv && !strcmp (*argv, "info")) - { - if (intgen_list) - { - for (intgen = intgen_list; intgen != NULL; intgen = intgen->next) - sim_io_printf (sd, "Interrupt generator %d (%s) at pc=0x%lx/time=%ld%s.\n", - intgen->number, - interrupt_names[intgen->type], - (long) intgen->address, - intgen->time, - (intgen->enabled ? "" : " (disabled)")); - } - else - { - sim_io_printf (sd, "No interrupt generators defined.\n"); - } - - } - else - { - sim_io_printf (sd, "Invalid interrupt command, must be one of `add', `remove', or `info'.\n"); - } - /* Cache the presence of a non-maskable generator. */ - have_nm_generator = 0; - for (intgen = intgen_list; intgen != NULL; intgen = intgen->next) - { - if (intgen->type == int_nmi || intgen->type == int_reset) - { - have_nm_generator = 1; - break; - } - } -} - void sim_do_command (sd, cmd) SIM_DESC sd; @@ -653,13 +434,13 @@ sim_do_command (sd, cmd) char *mm_cmd = "memory-map"; char *int_cmd = "interrupt"; - if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0)) - sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n"); - - else if (! strncmp (cmd, int_cmd, strlen (int_cmd)) - && strchr (" ", cmd[strlen(int_cmd)])) - sim_set_interrupt (sd, cmd + strlen(int_cmd) + 1); - - else if (sim_args_command (sd, cmd) != SIM_RC_OK) - sim_io_eprintf (sd, "Unknown command `%s'\n", cmd); + if (sim_args_command (sd, cmd) != SIM_RC_OK) + { + if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0)) + sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n"); + else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0) + sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n"); + else + sim_io_eprintf (sd, "Unknown command `%s'\n", cmd); + } } |