⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interrupts.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    {	      frvbf_perform_writeback (current_cpu);	      writeback_done = 1;	      continue;	    }	  frv_external_interrupt (current_cpu, item, pc);	  return;	case FRV_SOFTWARE_INTERRUPT:	  frv_interrupt_state.queue_index = index;	  frv_software_interrupt (current_cpu, item, pc);	  return;	case FRV_PROGRAM_INTERRUPT:	  /* If the program interrupt is not strict (imprecise), then perform	     writeback first. This may, in turn, cause a higher priority	     interrupt.  */	  if (! interrupt->precise && ! writeback_done)	    {	      frv_interrupt_state.imprecise_interrupt = item;	      frvbf_perform_writeback (current_cpu);	      writeback_done = 1;	      continue;	    }	  frv_interrupt_state.queue_index = index;	  frv_program_interrupt (current_cpu, item, pc);	  return;	case FRV_BREAK_INTERRUPT:	  frv_interrupt_state.queue_index = index;	  frv_break_interrupt (current_cpu, interrupt, pc);	  return;	case FRV_RESET_INTERRUPT:	  break;	default:	  break;	}      frv_interrupt_state.queue_index = index;      break; /* out of loop.  */    }  /* We should never get here.  */  {    SIM_DESC sd = CPU_STATE (current_cpu);    sim_engine_abort (sd, current_cpu, pc,		      "interrupt class not supported %d\n",		      interrupt->iclass);  }}/* Check to see the if the RSTR.HR or RSTR.SR bits have been set.  If so, handle   the appropriate reset interrupt.  */static intcheck_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 */}/* Process any pending interrupt(s) after a group of parallel insns.  */voidfrv_process_interrupts (SIM_CPU *current_cpu){  SI NE_flags[2];  /* Need to save the pc here because writeback may change it (due to a     branch).  */  IADDR pc = CPU_PC_GET (current_cpu);  /* Check for a reset before anything else.  */  if (check_reset (current_cpu, pc))    return;  /* First queue the writes for any accumulated NE flags.  */  if (frv_interrupt_state.f_ne_flags[0] != 0      || frv_interrupt_state.f_ne_flags[1] != 0)    {      GET_NE_FLAGS (NE_flags, H_SPR_FNER0);      NE_flags[0] |= frv_interrupt_state.f_ne_flags[0];      NE_flags[1] |= frv_interrupt_state.f_ne_flags[1];      SET_NE_FLAGS (H_SPR_FNER0, NE_flags);    }  /* If there is no interrupt pending, then perform parallel writeback.  This     may cause an interrupt.  */  if (frv_interrupt_state.queue_index <= 0)    frvbf_perform_writeback (current_cpu);  /* If there is an interrupt pending, then process it.  */  if (frv_interrupt_state.queue_index > 0)    handle_interrupt (current_cpu, pc);}/* Find the next available ESR and return its index */static intesr_for_data_access_exception (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  SIM_DESC sd = CPU_STATE (current_cpu);  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)    return 8; /* Use ESR8, EPCR8.  */  if (item->slot == UNIT_I0)    return 8; /* Use ESR8, EPCR8, EAR8, EDR8.  */  return 9; /* Use ESR9, EPCR9, EAR9.  */}/* Set the next available EDR register with the data which was to be stored   and return the index of the register.  */static intset_edr_register (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item, int edr_index){  /* EDR0, EDR4 and EDR8 are available as blocks of 4.       SI data uses EDR3, EDR7 and EDR11       DI data uses EDR2, EDR6 and EDR10       XI data uses EDR0, EDR4 and EDR8.  */  int i;  edr_index += 4 - item->u.data_written.length;  for (i = 0; i < item->u.data_written.length; ++i)    SET_EDR (edr_index + i, item->u.data_written.words[i]);  return edr_index;};/* Clear ESFR0, EPCRx, ESRx, EARx and EDRx.  */static voidclear_exception_status_registers (SIM_CPU *current_cpu){  int i;  /* It is only necessary to clear the flag bits indicating which registers     are valid.  */  SET_ESFR (0, 0);  SET_ESFR (1, 0);  for (i = 0; i <= 2; ++i)    {      SI esr = GET_ESR (i);      CLEAR_ESR_VALID (esr);      SET_ESR (i, esr);    }  for (i = 8; i <= 15; ++i)    {      SI esr = GET_ESR (i);      CLEAR_ESR_VALID (esr);      SET_ESR (i, esr);    }}/* Record state for media exception.  */voidfrv_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);}/* Determine the correct FQ register to use for the given exception.   Return -1 if a register is not available.  */static intfq_for_exception (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  SI fq;  struct frv_fp_exception_info *fp_info = & item->u.fp_info;  /* For fp_exception overflow, underflow or inexact, use FQ0 or FQ1.  */  if (fp_info->ftt == FTT_IEEE_754_EXCEPTION      && (fp_info->fsr_mask & (FSR_OVERFLOW | FSR_UNDERFLOW | FSR_INEXACT)))    {      fq = GET_FQ (0);      if (! GET_FQ_VALID (fq))	return 0; /* FQ0 is available.  */      fq = GET_FQ (1);      if (! GET_FQ_VALID (fq))	return 1; /* FQ1 is available.  */      /* No FQ register is available */      {	SIM_DESC sd = CPU_STATE (current_cpu);	IADDR pc = CPU_PC_GET (current_cpu);	sim_engine_abort (sd, current_cpu, pc, "No FQ register available\n");      }      return -1;    }  /* For other exceptions, use FQ2 if the insn was in slot F0/I0 and FQ3     otherwise.  */  if (item->slot == UNIT_FM0 || item->slot == UNIT_I0)    return 2;  return 3;}/* Set FSR0, FQ0-FQ9, depending on the interrupt.  */static voidset_fp_exception_registers (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  int fq_index;  SI fq;  SI insn;  SI fsr0;  IADDR pc;  struct frv_fp_exception_info *fp_info;  SIM_DESC sd = CPU_STATE (current_cpu);  /* No FQ registers on fr550 */  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)    {      /* Update the fsr.  */      fp_info = & item->u.fp_info;      fsr0 = GET_FSR (0);      SET_FSR_FTT (fsr0, fp_info->ftt);      SET_FSR (0, fsr0);      return;    }  /* Select an FQ and update it with the exception information.  */  fq_index = fq_for_exception (current_cpu, item);  if (fq_index == -1)    return;  fp_info = & item->u.fp_info;  fq = GET_FQ (fq_index);  SET_FQ_MIV (fq, MIV_FLOAT);  SET_FQ_SIE (fq, SIE_NIL);  SET_FQ_FTT (fq, fp_info->ftt);  SET_FQ_CEXC (fq, fp_info->fsr_mask);  SET_FQ_VALID (fq);  SET_FQ (fq_index, fq);  /* Write the failing insn into FQx.OPC.  */  pc = item->vpc;  insn = GETMEMSI (current_cpu, pc, pc);  SET_FQ_OPC (fq_index, insn);  /* Update the fsr.  */  fsr0 = GET_FSR (0);  SET_FSR_QNE (fsr0); /* FQ not empty */  SET_FSR_FTT (fsr0, fp_info->ftt);  SET_FSR (0, fsr0);}/* Record the state of a division exception in the ISR.  */static voidset_isr_exception_fields (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  USI isr = GET_ISR ();  int dtt = GET_ISR_DTT (isr);  dtt |= item->u.dtt;  SET_ISR_DTT (isr, dtt);  SET_ISR (isr);}/* Set ESFR0, EPCRx, ESRx, EARx and EDRx, according to the given program   interrupt.  */static voidset_exception_status_registers (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  struct frv_interrupt *interrupt = & frv_interrupt_table[item->kind];  int slot = (item->vpc - previous_vliw_pc) / 4;  int reg_index = -1;  int set_ear = 0;  int set_edr = 0;  int set_daec = 0;  int set_epcr = 0;  SI esr = 0;  SIM_DESC sd = CPU_STATE (current_cpu);  /* If the interrupt is strict (precise) or the interrupt is on the insns     in the I0 pipe, then set the 0 registers.  */  if (interrupt->precise)    {      reg_index = 0;      if (interrupt->kind == FRV_REGISTER_EXCEPTION)	SET_ESR_REC (esr, item->u.rec);      else if (interrupt->kind == FRV_INSTRUCTION_ACCESS_EXCEPTION)	SET_ESR_IAEC (esr, item->u.iaec);      /* For fr550, don't set epcr for precise interrupts.  */      if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)	set_epcr = 1;    }  else    {      switch (interrupt->kind)	{	case FRV_DIVISION_EXCEPTION:	  set_isr_exception_fields (current_cpu, item);	  /* fall thru to set reg_index.  */	case FRV_COMMIT_EXCEPTION:	  /* For fr550, always use ESR0.  */	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)	    reg_index = 0;	  else if (item->slot == UNIT_I0)	    reg_index = 0;	  else if (item->slot == UNIT_I1)	    reg_index = 1;	  set_epcr = 1;	  break;	case FRV_DATA_STORE_ERROR:	  reg_index = 14; /* Use ESR14.  */	  break;	case FRV_DATA_ACCESS_ERROR:	  reg_index = 15; /* Use ESR15, EPCR15.  */	  set_ear = 1;	  break;	case FRV_DATA_ACCESS_EXCEPTION:	  set_daec = 1;	  /* fall through */	case FRV_DATA_ACCESS_MMU_MISS:	case FRV_MEM_ADDRESS_NOT_ALIGNED:	  /* Get the appropriate ESR, EPCR, EAR and EDR.	     EAR will be set. EDR will not be set if this is a store insn.  */	  set_ear = 1;	  /* For fr550, never use EDRx.  */	  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)	    if (item->u.data_written.length != 0)	      set_edr = 1;	  reg_index = esr_for_data_access_exception (current_cpu, item);	  set_epcr = 1;	  break;	case FRV_MP_EXCEPTION:	  /* For fr550, use EPCR2 and ESR2.  */	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)	    {	      reg_index = 2;	      set_epcr = 1;	    }	  break; /* MSR0-1, FQ0-9 are already set.  */	case FRV_FP_EXCEPTION:	  set_fp_exception_registers (current_cpu, item);	  /* For fr550, use EPCR2 and ESR2.  */	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)	    {	      reg_index = 2;	      set_epcr = 1;	    }	  break;	default:	  {	    SIM_DESC sd = CPU_STATE (current_cpu);	    IADDR pc = CPU_PC_GET (current_cpu);	    sim_engine_abort (sd, current_cpu, pc,			      "invalid non-strict program interrupt kind: %d\n",			      interrupt->kind);	    break;	  }	}    } /* non-strict (imprecise) interrupt */  /* Now fill in the selected exception status registers.  */  if (reg_index != -1)    {      /* Now set the exception status registers.  */      SET_ESFR_FLAG (reg_index);      SET_ESR_EC (esr, interrupt->ec);      if (set_epcr)	{	  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)	    SET_EPCR (reg_index, previous_vliw_pc);	  else	    SET_EPCR (reg_index, item->vpc);	}      if (set_ear)	{	  SET_EAR (reg_index, item->eaddress);	  SET_ESR_EAV (esr);	}      else	CLEAR_ESR_EAV (esr);      if (set_edr)	{	  int edn = set_edr_register (current_cpu, item, 0/* EDR0-3 */);	  SET_ESR_EDN (esr, edn);	  SET_ESR_EDV (esr);	}      else	CLEAR_ESR_EDV (esr);      if (set_daec)	SET_ESR_DAEC (esr, item->u.daec);      SET_ESR_VALID (esr);      SET_ESR (reg_index, esr);    }}/* Check for compound interrupts.   Returns NULL if no interrupt is to be processed.  */static struct frv_interrupt *check_for_compound_interrupt (  SIM_CPU *current_cpu, struct frv_interrupt_queue_element *item){  struct frv_interrupt *interrupt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -