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

📄 traps.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* NECR, NESR, NEEAR are only implemented for the full frv machine.  */  if (do_elos)    {      ne_index = next_available_nesr (current_cpu, NO_NESR);      if (ne_index == NO_NESR)	{	  IADDR pc = GET_H_PC ();	  sim_engine_abort (sd, current_cpu, pc, 			    "No available NESR register\n");	}      /* Fill in the basic fields of the NESR.  */      nesr = GET_NESR (ne_index);      SET_NESR_VALID (nesr);      SET_NESR_EAV (nesr);      SET_NESR_DRN (nesr, target_index);      SET_NESR_SIZE (nesr, data_size);      SET_NESR_NEAN (nesr, ne_index);      if (is_float)	SET_NESR_FR (nesr);      else	CLEAR_NESR_FR (nesr);      /* Set the corresponding NEEAR.  */      SET_NEEAR (ne_index, address);        SET_NESR_DAEC (nesr, 0);      SET_NESR_REC (nesr, 0);      SET_NESR_EC (nesr, 0);    }  /* Set the NE flag corresponding to the target register if an interrupt     factor was detected.      daec is not checked here yet, but is declared for future reference.  */  if (is_float)    NE_base = H_SPR_FNER0;  else    NE_base = H_SPR_GNER0;  GET_NE_FLAGS (NE_flags, NE_base);  if (rec)    {      SET_NE_FLAG (NE_flags, target_index);      if (do_elos)	SET_NESR_REC (nesr, NESR_REGISTER_NOT_ALIGNED);    }  if (ec)    {      SET_NE_FLAG (NE_flags, target_index);      if (do_elos)	SET_NESR_EC (nesr, NESR_MEM_ADDRESS_NOT_ALIGNED);    }  if (do_elos)    SET_NESR (ne_index, nesr);  /* If no interrupt factor was detected then set the NE flag on the     target register if the NE flag on one of the input registers     is already set.  */  if (! rec && ! ec && ! daec)    {      BI ne_flag = GET_NE_FLAG (NE_flags, base_index);      if (disp_index >= 0)	ne_flag |= GET_NE_FLAG (NE_flags, disp_index);      if (ne_flag)	{	  SET_NE_FLAG (NE_flags, target_index);	  rc = 0; /* Do not perform the load.  */	}      else	CLEAR_NE_FLAG (NE_flags, target_index);    }  SET_NE_FLAGS (NE_base, NE_flags);  return rc; /* perform the load?  */}/* Record state for media exception: media_cr_not_aligned.  */voidfrvbf_media_cr_not_aligned (SIM_CPU *current_cpu){  SIM_DESC sd = CPU_STATE (current_cpu);  /* On some machines this generates an illegal_instruction interrupt.  */  switch (STATE_ARCHITECTURE (sd)->mach)    {      /* Note: there is a discrepancy between V2.2 of the FR400	 instruction manual and the various FR4xx LSI specs.  The former	 claims that unaligned registers cause an mp_exception while the	 latter say it's an illegal_instruction.  The LSI specs appear	 to be correct since MTT is fixed at 1.  */    case bfd_mach_fr400:    case bfd_mach_fr450:    case bfd_mach_fr550:      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);      break;    default:      frv_set_mp_exception_registers (current_cpu, MTT_CR_NOT_ALIGNED, 0);      break;    }}/* Record state for media exception: media_acc_not_aligned.  */voidfrvbf_media_acc_not_aligned (SIM_CPU *current_cpu){  SIM_DESC sd = CPU_STATE (current_cpu);  /* On some machines this generates an illegal_instruction interrupt.  */  switch (STATE_ARCHITECTURE (sd)->mach)    {      /* See comment in frvbf_cr_not_aligned().  */    case bfd_mach_fr400:    case bfd_mach_fr450:    case bfd_mach_fr550:      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);      break;    default:      frv_set_mp_exception_registers (current_cpu, MTT_ACC_NOT_ALIGNED, 0);      break;    }}/* Record state for media exception: media_register_not_aligned.  */voidfrvbf_media_register_not_aligned (SIM_CPU *current_cpu){  SIM_DESC sd = CPU_STATE (current_cpu);  /* On some machines this generates an illegal_instruction interrupt.  */  switch (STATE_ARCHITECTURE (sd)->mach)    {      /* See comment in frvbf_cr_not_aligned().  */    case bfd_mach_fr400:    case bfd_mach_fr450:    case bfd_mach_fr550:      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);      break;    default:      frv_set_mp_exception_registers (current_cpu, MTT_INVALID_FR, 0);      break;    }}/* Record state for media exception: media_overflow.  */voidfrvbf_media_overflow (SIM_CPU *current_cpu, int sie){  frv_set_mp_exception_registers (current_cpu, MTT_OVERFLOW, sie);}/* Queue a division exception.  */enum frv_dttfrvbf_division_exception (SIM_CPU *current_cpu, enum frv_dtt dtt,			  int target_index, int non_excepting){  /* If there was an overflow and it is masked, then record it in     ISR.AEXC.  */  USI isr = GET_ISR ();  if ((dtt & FRV_DTT_OVERFLOW) && GET_ISR_EDE (isr))    {      dtt &= ~FRV_DTT_OVERFLOW;      SET_ISR_AEXC (isr);      SET_ISR (isr);    }  if (dtt != FRV_DTT_NO_EXCEPTION)    {      if (non_excepting)	{	  /* Non excepting instruction, simply set the NE flag for the target	     register.  */	  SI NE_flags[2];	  GET_NE_FLAGS (NE_flags, H_SPR_GNER0);	  SET_NE_FLAG (NE_flags, target_index);	  SET_NE_FLAGS (H_SPR_GNER0, NE_flags);	}      else	frv_queue_division_exception_interrupt (current_cpu, dtt);    }  return dtt;}voidfrvbf_check_recovering_store (  SIM_CPU *current_cpu, PCADDR address, SI regno, int size, int is_float){  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);  int reg_ix;  CPU_RSTR_INVALIDATE(current_cpu) = 0;  for (reg_ix = next_valid_nesr (current_cpu, NO_NESR);       reg_ix != NO_NESR;       reg_ix = next_valid_nesr (current_cpu, reg_ix))    {      if (address == GET_H_SPR (H_SPR_NEEAR0 + reg_ix))	{	  SI nesr = GET_NESR (reg_ix);	  int nesr_drn = GET_NESR_DRN (nesr);	  BI nesr_fr = GET_NESR_FR (nesr);	  SI remain;	  /* Invalidate cache block containing this address.	     If we need to count cycles, then the cache operation will be	     initiated from the model profiling functions.	     See frvbf_model_....  */	  if (model_insn)	    {	      CPU_RSTR_INVALIDATE(current_cpu) = 1;	      CPU_LOAD_ADDRESS (current_cpu) = address;	    }	  else	    frv_cache_invalidate (cache, address, 1/* flush */);	  /* Copy the stored value to the register indicated by NESR.DRN.  */	  for (remain = size; remain > 0; remain -= 4)	    {	      SI value;	      if (is_float)		value = GET_H_FR (regno);	      else		value = GET_H_GR (regno);	      switch (size)		{		case 1:		  value &= 0xff;		  break;		case 2:		  value &= 0xffff;		  break;		default:		  break;		}	      if (nesr_fr)		sim_queue_fn_sf_write (current_cpu, frvbf_h_fr_set, nesr_drn,				       value);	      else		sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, nesr_drn,				       value);	      nesr_drn++;	      regno++;	    }	  break; /* Only consider the first matching register.  */	}    } /* loop over active neear registers.  */}SIfrvbf_check_acc_range (SIM_CPU *current_cpu, SI regno){  /* Only applicable to fr550 */  SIM_DESC sd = CPU_STATE (current_cpu);  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)    return;  /* On the fr550, media insns in slots 0 and 2 can only access     accumulators acc0-acc3. Insns in slots 1 and 3 can only access     accumulators acc4-acc7 */  switch (frv_current_fm_slot)    {    case UNIT_FM0:    case UNIT_FM2:      if (regno <= 3)	return 1; /* all is ok */      break;    case UNIT_FM1:    case UNIT_FM3:      if (regno >= 4)	return 1; /* all is ok */      break;    }    /* The specified accumulator is out of range. Queue an illegal_instruction     interrupt.  */  frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);  return 0;}voidfrvbf_check_swap_address (SIM_CPU *current_cpu, SI address){  /* Only applicable to fr550 */  SIM_DESC sd = CPU_STATE (current_cpu);  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)    return;  /* Adress must be aligned on a word boundary.  */  if (address & 0x3)    frv_queue_data_access_exception_interrupt (current_cpu);}static voidclear_nesr_neear (SIM_CPU *current_cpu, SI target_index, BI is_float){  int reg_ix;  /* Only implemented for full frv.  */  SIM_DESC sd = CPU_STATE (current_cpu);  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_frv)    return;  /* Clear the appropriate NESR and NEEAR registers.  */  for (reg_ix = next_valid_nesr (current_cpu, NO_NESR);       reg_ix != NO_NESR;       reg_ix = next_valid_nesr (current_cpu, reg_ix))    {      SI nesr;      /* The register is available, now check if it is active.  */      nesr = GET_NESR (reg_ix);      if (GET_NESR_FR (nesr) == is_float)	{	  if (target_index < 0 || GET_NESR_DRN (nesr) == target_index)	    {	      SET_NESR (reg_ix, 0);	      SET_NEEAR (reg_ix, 0);	    }	}    }}static voidclear_ne_flags (  SIM_CPU *current_cpu,  SI target_index,  int hi_available,  int lo_available,  SI NE_base){  SI NE_flags[2];  int exception;  GET_NE_FLAGS (NE_flags, NE_base);  if (target_index >= 0)    CLEAR_NE_FLAG (NE_flags, target_index);  else    {      if (lo_available)	NE_flags[1] = 0;      if (hi_available)	NE_flags[0] = 0;    }  SET_NE_FLAGS (NE_base, NE_flags);}/* Return 1 if the given register is available, 0 otherwise.  TARGET_INDEX==-1   means to check for any register available.  */static voidwhich_registers_available (  SIM_CPU *current_cpu, int *hi_available, int *lo_available, int is_float){  if (is_float)    frv_fr_registers_available (current_cpu, hi_available, lo_available);  else    frv_gr_registers_available (current_cpu, hi_available, lo_available);}voidfrvbf_clear_ne_flags (SIM_CPU *current_cpu, SI target_index, BI is_float){  int hi_available;  int lo_available;  int exception;  SI NE_base;  USI necr;  FRV_REGISTER_CONTROL *control;  /* Check for availability of the target register(s).  */  which_registers_available (current_cpu, & hi_available, & lo_available,			     is_float);  /* Check to make sure that the target register is available.  */  if (! frv_check_register_access (current_cpu, target_index,				   hi_available, lo_available))    return;  /* Determine whether we're working with GR or FR registers.  */  if (is_float)    NE_base = H_SPR_FNER0;  else    NE_base = H_SPR_GNER0;  /* Always clear the appropriate NE flags.  */  clear_ne_flags (current_cpu, target_index, hi_available, lo_available,		  NE_base);  /* Clear the appropriate NESR and NEEAR registers.  */  control = CPU_REGISTER_CONTROL (current_cpu);  if (control->spr[H_SPR_NECR].implemented)    {      necr = GET_NECR ();      if (GET_NECR_VALID (necr) && GET_NECR_ELOS (necr))	clear_nesr_neear (current_cpu, target_index, is_float);    }}voidfrvbf_commit (SIM_CPU *current_cpu, SI target_index, BI is_float){  SI NE_base;  SI NE_flags[2];  BI NE_flag;  int exception;  int hi_available;  int lo_available;  USI necr;  FRV_REGISTER_CONTROL *control;  /* Check for availability of the target register(s).  */  which_registers_available (current_cpu, & hi_available, & lo_available,			     is_float);  /* Check to make sure that the target register is available.  */  if (! frv_check_register_access (current_cpu, target_index,				   hi_available, lo_available))    return;  /* Determine whether we're working with GR or FR registers.  */  if (is_float)    NE_base = H_SPR_FNER0;  else    NE_base = H_SPR_GNER0;  /* Determine whether a ne exception is pending.  */  GET_NE_FLAGS (NE_flags, NE_base);  if (target_index >= 0)    NE_flag = GET_NE_FLAG (NE_flags, target_index);  else    {      NE_flag =	hi_available && NE_flags[0] != 0 || lo_available && NE_flags[1] != 0;    }  /* Always clear the appropriate NE flags.  */  clear_ne_flags (current_cpu, target_index, hi_available, lo_available,		  NE_base);  control = CPU_REGISTER_CONTROL (current_cpu);  if (control->spr[H_SPR_NECR].implemented)    {      necr = GET_NECR ();      if (GET_NECR_VALID (necr) && GET_NECR_ELOS (necr) && NE_flag)	{	  /* Clear the appropriate NESR and NEEAR registers.  */	  clear_nesr_neear (current_cpu, target_index, is_float);	  frv_queue_program_interrupt (current_cpu, FRV_COMMIT_EXCEPTION);	}    }}/* Generate the appropriate fp_exception(s) based on the given status code.  */voidfrvbf_fpu_error (CGEN_FPU* fpu, int status){  struct frv_fp_exception_info fp_info = {    FSR_NO_EXCEPTION, FTT_IEEE_754_EXCEPTION  };  if (status &      (sim_fpu_status_invalid_snan |       sim_fpu_status_invalid_qnan |       sim_fpu_status_invalid_isi |       sim_fpu_status_invalid_idi |       sim_fpu_status_invalid_zdz |       sim_fpu_status_invalid_imz |       sim_fpu_status_invalid_cvi |       sim_fpu_status_invalid_cmp |       sim_fpu_status_invalid_sqrt))    fp_info.fsr_mask |= FSR_INVALID_OPERATION;  if (status & sim_fpu_status_invalid_div0)    fp_info.fsr_mask |= FSR_DIVISION_BY_ZERO;  if (status & sim_fpu_status_inexact)    fp_info.fsr_mask |= FSR_INEXACT;  if (status & sim_fpu_status_overflow)    fp_info.fsr_mask |= FSR_OVERFLOW;  if (status & sim_fpu_status_underflow)    fp_info.fsr_mask |= FSR_UNDERFLOW;  if (status & sim_fpu_status_denorm)    {      fp_info.fsr_mask |= FSR_DENORMAL_INPUT;      fp_info.ftt = FTT_DENORMAL_INPUT;    }  if (fp_info.fsr_mask != FSR_NO_EXCEPTION)    {      SIM_CPU *current_cpu = (SIM_CPU *)fpu->owner;      frv_queue_fp_exception_interrupt (current_cpu, & fp_info);    }}

⌨️ 快捷键说明

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