/* 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
}
Exemple #2
0
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 */
}