void mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception) { ASSERT(cpu != NULL); if(exception == 0 && State.exc_suspended > 0) { if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */ sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n", State.exc_suspended); } else if(exception != 0 && State.exc_suspended > 0) { if(exception != State.exc_suspended) sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n", State.exc_suspended, exception); memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs)); CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */ } else if(exception != 0 && State.exc_suspended == 0) { sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception); } State.exc_suspended = 0; }
void sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int signal) { micromips_m32_instruction_word instruction_0; sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr); micromips32_instruction_address cia = CPU_PC_GET (cpu); sd->isa_mode = ISA_MODE_MIPS32; while (1) { micromips32_instruction_address nia; /* Allow us to switch back from MIPS32 to microMIPS This covers two cases: 1. Setting the correct isa mode based on the start address from the elf header. 2. Setting the correct isa mode after a MIPS32 jump or branch instruction. */ if ((sd->isa_mode == ISA_MODE_MIPS32) && ((cia & 0x1) == ISA_MODE_MICROMIPS)) { sd->isa_mode = ISA_MODE_MICROMIPS; cia = cia & ~0x1; } #if defined (ENGINE_ISSUE_PREFIX_HOOK) ENGINE_ISSUE_PREFIX_HOOK (); #endif switch (sd->isa_mode) { case ISA_MODE_MICROMIPS: nia = micromips_instruction_decode (sd, cpu, cia, MICROMIPS_DELAYSLOT_SIZE_ANY); break; case ISA_MODE_MIPS32: instruction_0 = IMEM32 (cia); nia = micromips_m32_idecode_issue (sd, instruction_0, cia); break; default: nia = NULL_CIA; } #if defined (ENGINE_ISSUE_POSTFIX_HOOK) ENGINE_ISSUE_POSTFIX_HOOK (); #endif /* Update the instruction address */ cia = nia; /* process any events */ if (sim_events_tick (sd)) { CPU_PC_SET (cpu, cia); sim_events_process (sd); cia = CPU_PC_GET (cpu); } } }
void mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia) { ASSERT(cpu != NULL); if(State.exc_suspended > 0) sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended); CPU_PC_SET (cpu, cia); memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs)); State.exc_suspended = 0; }
void mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception) { ASSERT(cpu != NULL); if(State.exc_suspended > 0) sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", State.exc_suspended, exception); memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs)); memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs)); CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */ State.exc_suspended = exception; }
void sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, /* ignore */ int siggnal) /* ignore */ { sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr); address_word cia = CPU_PC_GET (cpu); while (1) { address_word nia; #if defined (ENGINE_ISSUE_PREFIX_HOOK) ENGINE_ISSUE_PREFIX_HOOK (); #endif if ((cia & 1)) { m16_instruction_word instruction_0 = IMEM16 (cia); nia = m16_idecode_issue (sd, instruction_0, cia); } else { m32_instruction_word instruction_0 = IMEM32 (cia); nia = m32_idecode_issue (sd, instruction_0, cia); } #if defined (ENGINE_ISSUE_POSTFIX_HOOK) ENGINE_ISSUE_POSTFIX_HOOK (); #endif /* Update the instruction address */ cia = nia; /* process any events */ if (sim_events_tick (sd)) { CPU_PC_SET (CPU, cia); sim_events_process (sd); cia = CPU_PC_GET (CPU); } } }
void program_interrupt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, SIM_SIGNAL sig) { int status; struct hw *device; static int in_interrupt = 0; #ifdef SIM_CPU_EXCEPTION_TRIGGER SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia); #endif /* avoid infinite recursion */ if (in_interrupt) { (*mn10300_callback->printf_filtered) (mn10300_callback, "ERROR: recursion in program_interrupt during software exception dispatch."); } else { in_interrupt = 1; /* copy NMI handler code from dv-mn103cpu.c */ store_word (SP - 4, CPU_PC_GET (cpu)); store_half (SP - 8, PSW); /* Set the SYSEF flag in NMICR by backdoor method. See dv-mn103int.c:write_icr(). This is necessary because software exceptions are not modelled by actually talking to the interrupt controller, so it cannot set its own SYSEF flag. */ if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0)) store_byte (0x34000103, 0x04); } PSW &= ~PSW_IE; SP = SP - 8; CPU_PC_SET (cpu, 0x40000008); in_interrupt = 0; sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig); }
SIM_RC sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env) { memset (&State, 0, sizeof (State)); if (prog_bfd != NULL) { PC = bfd_get_start_address (prog_bfd); } else { PC = 0; } CPU_PC_SET (STATE_CPU (sd, 0), (unsigned64) PC); if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2) PSW |= PSW_FE; return SIM_RC_OK; }
void sim_engine_run (SIM_DESC sd, int next_cpu_nr, /* ignore */ int nr_cpus, /* ignore */ int siggnal) /* ignore */ { sim_cia cia; sim_cpu *cpu; SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); cpu = STATE_CPU (sd, 0); cia = CPU_PC_GET (cpu); while (1) { instruction_word insn = IMEM32 (cia); cia = idecode_issue (sd, insn, cia); /* process any events */ if (sim_events_tick (sd)) { CPU_PC_SET (cpu, cia); sim_events_process (sd); } } }
static void deliver_mn103cpu_interrupt (struct hw *me, void *data) { struct mn103cpu *controller = hw_data (me); SIM_DESC simulator = hw_system (me); sim_cpu *cpu = STATE_CPU (simulator, 0); if (controller->pending_reset) { controller->pending_reset = 0; /* need to clear all registers et.al! */ HW_TRACE ((me, "Reset!")); hw_abort (me, "Reset!"); } else if (controller->pending_nmi) { controller->pending_nmi = 0; store_word (SP - 4, CPU_PC_GET (cpu)); store_half (SP - 8, PSW); PSW &= ~PSW_IE; SP = SP - 8; CPU_PC_SET (cpu, 0x40000008); HW_TRACE ((me, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx", (long) CPU_PC_GET (cpu), (unsigned) PSW, (long) SP)); } else if ((controller->pending_level < EXTRACT_PSW_LM) && (PSW & PSW_IE)) { /* Don't clear pending level. Request continues to be pending until the interrupt controller clears/changes it */ store_word (SP - 4, CPU_PC_GET (cpu)); store_half (SP - 8, PSW); PSW &= ~PSW_IE; PSW &= ~PSW_LM; PSW |= INSERT_PSW_LM (controller->pending_level); SP = SP - 8; CPU_PC_SET (cpu, 0x40000000 + controller->interrupt_vector[controller->pending_level]); HW_TRACE ((me, "port-out ack %d", controller->pending_level)); hw_port_event (me, ACK_PORT, controller->pending_level); HW_TRACE ((me, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx", controller->pending_level, (long) CPU_PC_GET (cpu), (unsigned) PSW, (long) SP)); } if (controller->pending_level < 7) /* FIXME */ { /* As long as there is the potential need to deliver an interrupt we keep rescheduling this routine. */ if (controller->pending_handler != NULL) controller->pending_handler = hw_event_queue_schedule (me, 1, deliver_mn103cpu_interrupt, NULL); } else { /* Don't bother re-scheduling the interrupt handler as there is nothing to deliver */ controller->pending_handler = NULL; } }
/* Execute a write stored on the write queue. */ void cgen_write_queue_element_execute (SIM_CPU *cpu, CGEN_WRITE_QUEUE_ELEMENT *item) { IADDR pc; switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item)) { case CGEN_BI_WRITE: *item->kinds.bi_write.target = item->kinds.bi_write.value; break; case CGEN_QI_WRITE: *item->kinds.qi_write.target = item->kinds.qi_write.value; break; case CGEN_SI_WRITE: *item->kinds.si_write.target = item->kinds.si_write.value; break; case CGEN_SF_WRITE: *item->kinds.sf_write.target = item->kinds.sf_write.value; break; case CGEN_PC_WRITE: CPU_PC_SET (cpu, item->kinds.pc_write.value); break; case CGEN_FN_HI_WRITE: item->kinds.fn_hi_write.function (cpu, item->kinds.fn_hi_write.regno, item->kinds.fn_hi_write.value); break; case CGEN_FN_SI_WRITE: item->kinds.fn_si_write.function (cpu, item->kinds.fn_si_write.regno, item->kinds.fn_si_write.value); break; case CGEN_FN_SF_WRITE: item->kinds.fn_sf_write.function (cpu, item->kinds.fn_sf_write.regno, item->kinds.fn_sf_write.value); break; case CGEN_FN_DI_WRITE: item->kinds.fn_di_write.function (cpu, item->kinds.fn_di_write.regno, item->kinds.fn_di_write.value); break; case CGEN_FN_DF_WRITE: item->kinds.fn_df_write.function (cpu, item->kinds.fn_df_write.regno, item->kinds.fn_df_write.value); break; case CGEN_FN_XI_WRITE: item->kinds.fn_xi_write.function (cpu, item->kinds.fn_xi_write.regno, item->kinds.fn_xi_write.value); break; case CGEN_FN_PC_WRITE: item->kinds.fn_pc_write.function (cpu, item->kinds.fn_pc_write.value); break; case CGEN_MEM_QI_WRITE: pc = item->insn_address; SETMEMQI (cpu, pc, item->kinds.mem_qi_write.address, item->kinds.mem_qi_write.value); break; case CGEN_MEM_HI_WRITE: pc = item->insn_address; SETMEMHI (cpu, pc, item->kinds.mem_hi_write.address, item->kinds.mem_hi_write.value); break; case CGEN_MEM_SI_WRITE: pc = item->insn_address; SETMEMSI (cpu, pc, item->kinds.mem_si_write.address, item->kinds.mem_si_write.value); break; case CGEN_MEM_DI_WRITE: pc = item->insn_address; SETMEMDI (cpu, pc, item->kinds.mem_di_write.address, item->kinds.mem_di_write.value); break; case CGEN_MEM_DF_WRITE: pc = item->insn_address; SETMEMDF (cpu, pc, item->kinds.mem_df_write.address, item->kinds.mem_df_write.value); break; case CGEN_MEM_XI_WRITE: pc = item->insn_address; SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address, item->kinds.mem_xi_write.value[0]); SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 4, item->kinds.mem_xi_write.value[1]); SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 8, item->kinds.mem_xi_write.value[2]); SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 12, item->kinds.mem_xi_write.value[3]); break; case CGEN_FN_MEM_QI_WRITE: pc = item->insn_address; item->kinds.fn_mem_qi_write.function (cpu, pc, item->kinds.fn_mem_qi_write.address, item->kinds.fn_mem_qi_write.value); break; case CGEN_FN_MEM_HI_WRITE: pc = item->insn_address; item->kinds.fn_mem_hi_write.function (cpu, pc, item->kinds.fn_mem_hi_write.address, item->kinds.fn_mem_hi_write.value); break; case CGEN_FN_MEM_SI_WRITE: pc = item->insn_address; item->kinds.fn_mem_si_write.function (cpu, pc, item->kinds.fn_mem_si_write.address, item->kinds.fn_mem_si_write.value); break; case CGEN_FN_MEM_DI_WRITE: pc = item->insn_address; item->kinds.fn_mem_di_write.function (cpu, pc, item->kinds.fn_mem_di_write.address, item->kinds.fn_mem_di_write.value); break; case CGEN_FN_MEM_DF_WRITE: pc = item->insn_address; item->kinds.fn_mem_df_write.function (cpu, pc, item->kinds.fn_mem_df_write.address, item->kinds.fn_mem_df_write.value); break; case CGEN_FN_MEM_XI_WRITE: pc = item->insn_address; item->kinds.fn_mem_xi_write.function (cpu, pc, item->kinds.fn_mem_xi_write.address, item->kinds.fn_mem_xi_write.value); break; default: abort (); break; /* FIXME: for now....print message later. */ } }