/* 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
}
コード例 #3
0
/* 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);
}
コード例 #5
0
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]);
}