/* 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 }
static int fr550_check_insn_acc_range (frv_insn *insn, int low, int hi) { int acc; switch (CGEN_INSN_NUM (insn->insn)) { case FRV_INSN_MADDACCS: case FRV_INSN_MSUBACCS: case FRV_INSN_MDADDACCS: case FRV_INSN_MDSUBACCS: case FRV_INSN_MASACCS: case FRV_INSN_MDASACCS: acc = insn->fields.f_ACC40Si; if (acc < low || acc > hi) return 1; /* out of range */ acc = insn->fields.f_ACC40Sk; if (acc < low || acc > hi) return 1; /* out of range */ break; case FRV_INSN_MMULHS: case FRV_INSN_MMULHU: case FRV_INSN_MMULXHS: case FRV_INSN_MMULXHU: case FRV_INSN_CMMULHS: case FRV_INSN_CMMULHU: case FRV_INSN_MQMULHS: case FRV_INSN_MQMULHU: case FRV_INSN_MQMULXHS: case FRV_INSN_MQMULXHU: case FRV_INSN_CMQMULHS: case FRV_INSN_CMQMULHU: case FRV_INSN_MMACHS: case FRV_INSN_MMRDHS: case FRV_INSN_CMMACHS: case FRV_INSN_MQMACHS: case FRV_INSN_CMQMACHS: case FRV_INSN_MQXMACHS: case FRV_INSN_MQXMACXHS: case FRV_INSN_MQMACXHS: case FRV_INSN_MCPXRS: case FRV_INSN_MCPXIS: case FRV_INSN_CMCPXRS: case FRV_INSN_CMCPXIS: case FRV_INSN_MQCPXRS: case FRV_INSN_MQCPXIS: acc = insn->fields.f_ACC40Sk; if (acc < low || acc > hi) return 1; /* out of range */ break; case FRV_INSN_MMACHU: case FRV_INSN_MMRDHU: case FRV_INSN_CMMACHU: case FRV_INSN_MQMACHU: case FRV_INSN_CMQMACHU: case FRV_INSN_MCPXRU: case FRV_INSN_MCPXIU: case FRV_INSN_CMCPXRU: case FRV_INSN_CMCPXIU: case FRV_INSN_MQCPXRU: case FRV_INSN_MQCPXIU: acc = insn->fields.f_ACC40Uk; if (acc < low || acc > hi) return 1; /* out of range */ break; default: break; } return 0; /* all is ok */ }