/* Handle a break interrupt.  */
void
frv_break_interrupt (
  SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
)
{
  IADDR new_pc;

  /* BPCSR=PC
     BPSR.BS=PSR.S
     BPSR.BET=PSR.ET
     PSR.S=1
     PSR.ET=0
     TBR.TT=0xff
     PC=TBR
  */
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
  SET_H_BPSR_BS (GET_H_PSR_S ());
  SET_H_BPSR_BET (GET_H_PSR_ET ());
  SET_H_PSR_S (1);
  SET_H_PSR_ET (0);
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
  SET_H_SPR (H_SPR_BPCSR, current_pc);

  /* Set the new PC in the TBR.  */
  SET_H_TBR_TT (interrupt->handler_offset);
  new_pc = GET_H_SPR (H_SPR_TBR);
  SET_H_PC (new_pc);

  CPU_DEBUG_STATE (current_cpu) = 1;
}
/* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle
   the appropriate reset interrupt.  */
static int
check_reset (SIM_CPU *current_cpu, IADDR pc)
{
  int hsr0;
  int hr;
  int sr;
  SI rstr;
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  IADDR address = RSTR_ADDRESS;

  /* We don't want this to show up in the cache statistics, so read the
     cache passively.  */
  if (! frv_cache_read_passive_SI (cache, address, & rstr))
    rstr = sim_core_read_unaligned_4 (current_cpu, pc, read_map, address);

  hr = GET_RSTR_HR (rstr);
  sr = GET_RSTR_SR (rstr);

  if (! hr && ! sr)
    return 0; /* no reset.  */

  /* Reinitialize the machine state.  */
  if (hr)
    frv_hardware_reset (current_cpu);
  else
    frv_software_reset (current_cpu);

  /* Branch to the reset address.  */
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_SA (hsr0))
    SET_H_PC (0xff000000);
  else
    SET_H_PC (0);

  return 1; /* reset */
}
/* Handle a program interrupt or a software interrupt.  */
void
frv_program_or_software_interrupt (
  SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
)
{
  USI new_pc;
  int original_psr_et;

  /* PCSR=PC
     PSR.PS=PSR.S
     PSR.ET=0
     PSR.S=1
     if PSR.ESR==1
       SR0 through SR3=GR4 through GR7
       TBR.TT=interrupt handler offset
       PC=TBR
  */
  original_psr_et = GET_H_PSR_ET ();

  SET_H_PSR_PS (GET_H_PSR_S ());
  SET_H_PSR_ET (0);
  SET_H_PSR_S (1);

  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
  /* The PCSR depends on the precision of the interrupt.  */
  if (interrupt->precise)
    SET_H_SPR (H_SPR_PCSR, previous_vliw_pc);
  else
    SET_H_SPR (H_SPR_PCSR, current_pc);

  /* Set the new PC in the TBR.  */
  SET_H_TBR_TT (interrupt->handler_offset);
  new_pc = GET_H_SPR (H_SPR_TBR);
  SET_H_PC (new_pc);

  /* If PSR.ET was not originally set, then enter the stopped state.  */
  if (! original_psr_et)
    {
      SIM_DESC sd = CPU_STATE (current_cpu);
      frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc);
      sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT);
    }
}
/* Handle a program interrupt or a software interrupt.  */
void
frv_external_interrupt (
  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, IADDR pc
)
{
  USI new_pc;
  struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];

  /* Don't process the interrupt if PSR.ET is not set or if it is masked.
     Interrupt 15 is processed even if it appears to be masked.  */
  if (! GET_H_PSR_ET ()
      || (interrupt->kind != FRV_INTERRUPT_LEVEL_15
	  && interrupt->kind < GET_H_PSR_PIL ()))
    return; /* Leave it for later.  */

  /* Remove the interrupt from the queue.  */
  --frv_interrupt_state.queue_index;

  /* PCSR=PC
     PSR.PS=PSR.S
     PSR.ET=0
     PSR.S=1
     if PSR.ESR==1
       SR0 through SR3=GR4 through GR7
       TBR.TT=interrupt handler offset
       PC=TBR
  */
  SET_H_PSR_PS (GET_H_PSR_S ());
  SET_H_PSR_ET (0);
  SET_H_PSR_S (1);
  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
  SET_H_SPR (H_SPR_PCSR, GET_H_PC ());

  /* Set the new PC in the TBR.  */
  SET_H_TBR_TT (interrupt->handler_offset);
  new_pc = GET_H_SPR (H_SPR_TBR);
  SET_H_PC (new_pc);
}
Ejemplo n.º 5
0
static SEM_PC
SEM_FN_NAME (lm32bf,x_invalid) (SIM_CPU *current_cpu, SEM_ARG sem_arg)
{
#define FLD(f) abuf->fields.sfmt_empty.f
  ARGBUF *abuf = SEM_ARGBUF (sem_arg);
  int UNUSED written = 0;
  IADDR UNUSED pc = abuf->addr;
  SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, 0);

  {
    /* Update the recorded pc in the cpu state struct.
       Only necessary for WITH_SCACHE case, but to avoid the
       conditional compilation ....  */
    SET_H_PC (pc);
    /* Virtual insns have zero size.  Overwrite vpc with address of next insn
       using the default-insn-bitsize spec.  When executing insns in parallel
       we may want to queue the fault and continue execution.  */
    vpc = SEM_NEXT_VPC (sem_arg, pc, 4);
    vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
  }

  return vpc;
#undef FLD
}
Ejemplo n.º 6
0
void
iq2000bf_h_pc_set (SIM_CPU *current_cpu, USI newval)
{
  SET_H_PC (newval);
}
Ejemplo n.º 7
0
void
crisv10f_h_pc_set (SIM_CPU *current_cpu, USI newval)
{
  SET_H_PC (newval);
}