/* Record the current VLIW slot in the given interrupt queue element. */ void frv_set_interrupt_queue_slot ( SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item ) { FRV_VLIW *vliw = CPU_VLIW (current_cpu); int slot = vliw->next_slot - 1; item->slot = (*vliw->current_vliw)[slot]; }
/* Check for interrupts caused by illegal insn access. These conditions are checked in the order specified by the fr400 and fr500 LSI specs. */ void frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc) { const CGEN_INSN *insn = sc->argbuf.idesc->idata; SIM_DESC sd = CPU_STATE (current_cpu); FRV_VLIW *vliw = CPU_VLIW (current_cpu); /* Check for vliw constraints. */ if (vliw->constraint_violation) frv_queue_illegal_instruction_interrupt (current_cpu, insn); /* Check for non-excepting insns. */ else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING) && ! GET_H_PSR_NEM ()) frv_queue_non_implemented_instruction_interrupt (current_cpu, insn); /* Check for conditional insns. */ else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL) && ! GET_H_PSR_CM ()) frv_queue_non_implemented_instruction_interrupt (current_cpu, insn); /* Make sure floating point support is enabled. */ else if (! GET_H_PSR_EF ()) { /* Generate fp_disabled if it is a floating point insn or if PSR.EM is off and the insns accesses a fp register. */ if (frv_is_float_insn (insn) || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS) && ! GET_H_PSR_EM ())) frv_queue_float_disabled_interrupt (current_cpu); } /* Make sure media support is enabled. */ else if (! GET_H_PSR_EM ()) { /* Generate mp_disabled if it is a media insn. */ if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP) frv_queue_media_disabled_interrupt (current_cpu); } /* Check for privileged insns. */ else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) && ! GET_H_PSR_S ()) frv_queue_privileged_instruction_interrupt (current_cpu, insn); #if 0 /* disable for now until we find out how FSR0.QNE gets reset. */ else { /* Enter the halt state if FSR0.QNE is set and we are executing a floating point insn, a media insn or an insn which access a FR register. */ SI fsr0 = GET_FSR (0); if (GET_FSR_QNE (fsr0) && (frv_is_float_insn (insn) || frv_is_media_insn (insn) || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS))) { sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped, SIM_SIGINT); } } #endif }
/* Record the current VLIW slot on the element at the top of the write queue. */ void frv_set_write_queue_slot (SIM_CPU *current_cpu) { FRV_VLIW *vliw = CPU_VLIW (current_cpu); int slot = vliw->next_slot - 1; CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1; CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix); CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot]; }
/* Record state for media exception. */ void frv_set_mp_exception_registers ( SIM_CPU *current_cpu, enum frv_msr_mtt mtt, int sie ) { /* Record the interrupt factor in MSR0. */ SI msr0 = GET_MSR (0); if (GET_MSR_MTT (msr0) == MTT_NONE) SET_MSR_MTT (msr0, mtt); /* Also set the OVF bit in the appropriate MSR as well as MSR0.AOVF. */ if (mtt == MTT_OVERFLOW) { FRV_VLIW *vliw = CPU_VLIW (current_cpu); int slot = vliw->next_slot - 1; SIM_DESC sd = CPU_STATE (current_cpu); /* If this insn is in the M2 slot, then set MSR1.OVF and MSR1.SIE, otherwise set MSR0.OVF and MSR0.SIE. */ if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550 && (*vliw->current_vliw)[slot] == UNIT_FM1) { SI msr = GET_MSR (1); OR_MSR_SIE (msr, sie); SET_MSR_OVF (msr); SET_MSR (1, msr); } else { OR_MSR_SIE (msr0, sie); SET_MSR_OVF (msr0); } /* Generate the interrupt now if MSR0.MPEM is set on fr550 */ if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550 && GET_MSR_MPEM (msr0)) frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION); else { /* Regardless of the slot, set MSR0.AOVF. */ SET_MSR_AOVF (msr0); } } SET_MSR (0, msr0); }
void frv_vliw_setup_insn (SIM_CPU *current_cpu, const CGEN_INSN *insn) { FRV_VLIW *vliw; int index; /* Always clear the NE index which indicates the target register of a non excepting insn. This will be reset by the insn if necessary. */ frv_interrupt_state.ne_index = NE_NOFLAG; vliw = CPU_VLIW (current_cpu); index = vliw->next_slot - 1; if (frv_is_float_insn (insn)) { /* If the insn is to be added and is a floating point insn and it is the first floating point insn in the vliw, then clear FSR0.FTT. */ int i; for (i = 0; i < index; ++i) if (frv_is_float_major (vliw->major[i], vliw->mach)) break; /* found float insn. */ if (i >= index) { SI fsr0 = GET_FSR (0); SET_FSR_FTT (fsr0, FTT_NONE); SET_FSR (0, fsr0); } } else if (frv_is_media_insn (insn)) { /* Clear the appropriate MSR fields depending on which slot this insn is in. */ CGEN_ATTR_VALUE_ENUM_TYPE preserve_ovf; SI msr0 = GET_MSR (0); preserve_ovf = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRESERVE_OVF); if ((*vliw->current_vliw)[index] == UNIT_FM0) { if (! preserve_ovf) { /* Clear MSR0.OVF and MSR0.SIE. */ CLEAR_MSR_SIE (msr0); CLEAR_MSR_OVF (msr0); } } else { if (! preserve_ovf) { /* Clear MSR1.OVF and MSR1.SIE. */ SI msr1 = GET_MSR (1); CLEAR_MSR_SIE (msr1); CLEAR_MSR_OVF (msr1); SET_MSR (1, msr1); } } SET_MSR (0, msr0); } /* Insn is a media insns. */ COUNT_INSNS_IN_SLOT ((*vliw->current_vliw)[index]); }