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

📄 frv.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
     enum machine_mode mode,	/* mode to allocate register with */     int mark_as_used,		/* register not available after allocation */     int no_abort)		/* return NULL instead of aborting */{  int regno = info->next_reg[ (int)class ];  int orig_regno = regno;  HARD_REG_SET *reg_in_class = &reg_class_contents[ (int)class ];  int i, nr;  for (;;)    {      if (TEST_HARD_REG_BIT (*reg_in_class, regno)	  && TEST_HARD_REG_BIT (info->regs, regno))	  break;      if (++regno >= FIRST_PSEUDO_REGISTER)	regno = 0;      if (regno == orig_regno)	{	  if (no_abort)	    return NULL_RTX;	  else	    abort ();	}    }  nr = HARD_REGNO_NREGS (regno, mode);  info->next_reg[ (int)class ] = regno + nr;  if (mark_as_used)    for (i = 0; i < nr; i++)      CLEAR_HARD_REG_BIT (info->regs, regno+i);  return gen_rtx_REG (mode, regno);}/* Return an rtx with the value OFFSET, which will either be a register or a   signed 12-bit integer.  It can be used as the second operand in an "add"   instruction, or as the index in a load or store.   The function returns a constant rtx if OFFSET is small enough, otherwise   it loads the constant into register OFFSET_REGNO and returns that.  */static rtxfrv_frame_offset_rtx (int offset){  rtx offset_rtx = GEN_INT (offset);  if (IN_RANGE_P (offset, -2048, 2047))    return offset_rtx;  else    {      rtx reg_rtx = gen_rtx_REG (SImode, OFFSET_REGNO);      if (IN_RANGE_P (offset, -32768, 32767))	emit_insn (gen_movsi (reg_rtx, offset_rtx));      else	{	  emit_insn (gen_movsi_high (reg_rtx, offset_rtx));	  emit_insn (gen_movsi_lo_sum (reg_rtx, offset_rtx));	}      return reg_rtx;    }}/* Generate (mem:MODE (plus:Pmode BASE (frv_frame_offset OFFSET)))).  The   prologue and epilogue uses such expressions to access the stack.  */static rtxfrv_frame_mem (enum machine_mode mode, rtx base, int offset){  return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode,					  base,					  frv_frame_offset_rtx (offset)));}/* Generate a frame-related expression:	(set REG (mem (plus (sp) (const_int OFFSET)))).   Such expressions are used in FRAME_RELATED_EXPR notes for more complex   instructions.  Marking the expressions as frame-related is superfluous if   the note contains just a single set.  But if the note contains a PARALLEL   or SEQUENCE that has several sets, each set must be individually marked   as frame-related.  */static rtxfrv_dwarf_store (rtx reg, int offset){  rtx set = gen_rtx_SET (VOIDmode,			 gen_rtx_MEM (GET_MODE (reg),				      plus_constant (stack_pointer_rtx,						     offset)),			 reg);  RTX_FRAME_RELATED_P (set) = 1;  return set;}/* Emit a frame-related instruction whose pattern is PATTERN.  The   instruction is the last in a sequence that cumulatively performs the   operation described by DWARF_PATTERN.  The instruction is marked as   frame-related and has a REG_FRAME_RELATED_EXPR note containing   DWARF_PATTERN.  */static voidfrv_frame_insn (rtx pattern, rtx dwarf_pattern){  rtx insn = emit_insn (pattern);  RTX_FRAME_RELATED_P (insn) = 1;  REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,				      dwarf_pattern,				      REG_NOTES (insn));}/* Emit instructions that transfer REG to or from the memory location (sp +   STACK_OFFSET).  The register is stored in memory if ACCESSOR->OP is   FRV_STORE and loaded if it is FRV_LOAD.  Only the prologue uses this   function to store registers and only the epilogue uses it to load them.   The caller sets up ACCESSOR so that BASE is equal to (sp + BASE_OFFSET).   The generated instruction will use BASE as its base register.  BASE may   simply be the stack pointer, but if several accesses are being made to a   region far away from the stack pointer, it may be more efficient to set   up a temporary instead.   Store instructions will be frame-related and will be annotated with the   overall effect of the store.  Load instructions will be followed by a   (use) to prevent later optimizations from zapping them.   The function takes care of the moves to and from SPRs, using TEMP_REGNO   as a temporary in such cases.  */static voidfrv_frame_access (frv_frame_accessor_t *accessor, rtx reg, int stack_offset){  enum machine_mode mode = GET_MODE (reg);  rtx mem = frv_frame_mem (mode,			   accessor->base,			   stack_offset - accessor->base_offset);  if (accessor->op == FRV_LOAD)    {      if (SPR_P (REGNO (reg)))	{	  rtx temp = gen_rtx_REG (mode, TEMP_REGNO);	  emit_insn (gen_rtx_SET (VOIDmode, temp, mem));	  emit_insn (gen_rtx_SET (VOIDmode, reg, temp));	}      else	emit_insn (gen_rtx_SET (VOIDmode, reg, mem));      emit_insn (gen_rtx_USE (VOIDmode, reg));    }  else    {      if (SPR_P (REGNO (reg)))	{	  rtx temp = gen_rtx_REG (mode, TEMP_REGNO);	  emit_insn (gen_rtx_SET (VOIDmode, temp, reg));	  frv_frame_insn (gen_rtx_SET (Pmode, mem, temp),			  frv_dwarf_store (reg, stack_offset));	}      else if (GET_MODE (reg) == DImode)	{	  /* For DImode saves, the dwarf2 version needs to be a SEQUENCE	     with a separate save for each register.  */	  rtx reg1 = gen_rtx_REG (SImode, REGNO (reg));	  rtx reg2 = gen_rtx_REG (SImode, REGNO (reg) + 1);	  rtx set1 = frv_dwarf_store (reg1, stack_offset);	  rtx set2 = frv_dwarf_store (reg2, stack_offset + 4);	  frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),			  gen_rtx_PARALLEL (VOIDmode,					    gen_rtvec (2, set1, set2)));	}      else	frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),			frv_dwarf_store (reg, stack_offset));    }}/* A function that uses frv_frame_access to transfer a group of registers to   or from the stack.  ACCESSOR is passed directly to frv_frame_access, INFO   is the stack information generated by frv_stack_info, and REG_SET is the   number of the register set to transfer.  */static voidfrv_frame_access_multi (frv_frame_accessor_t *accessor,                        frv_stack_t *info,                        int reg_set){  frv_stack_regs_t *regs_info;  int regno;  regs_info = &info->regs[reg_set];  for (regno = regs_info->first; regno <= regs_info->last; regno++)    if (info->save_p[regno])      frv_frame_access (accessor,			info->save_p[regno] == REG_SAVE_2WORDS			? gen_rtx_REG (DImode, regno)			: gen_rtx_REG (SImode, regno),			info->reg_offset[regno]);}/* Save or restore callee-saved registers that are kept outside the frame   header.  The function saves the registers if OP is FRV_STORE and restores   them if OP is FRV_LOAD.  INFO is the stack information generated by   frv_stack_info.  */static voidfrv_frame_access_standard_regs (enum frv_stack_op op, frv_stack_t *info){  frv_frame_accessor_t accessor;  accessor.op = op;  accessor.base = stack_pointer_rtx;  accessor.base_offset = 0;  frv_frame_access_multi (&accessor, info, STACK_REGS_GPR);  frv_frame_access_multi (&accessor, info, STACK_REGS_FPR);  frv_frame_access_multi (&accessor, info, STACK_REGS_LCR);}/* Called after register allocation to add any instructions needed for the   prologue.  Using a prologue insn is favored compared to putting all of the   instructions in the TARGET_ASM_FUNCTION_PROLOGUE target hook, since   it allows the scheduler to intermix instructions with the saves of   the caller saved registers.  In some cases, it might be necessary   to emit a barrier instruction as the last insn to prevent such   scheduling.   Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1   so that the debug info generation code can handle them properly.  */voidfrv_expand_prologue (void){  frv_stack_t *info = frv_stack_info ();  rtx sp = stack_pointer_rtx;  rtx fp = frame_pointer_rtx;  frv_frame_accessor_t accessor;  if (TARGET_DEBUG_STACK)    frv_debug_stack (info);  if (info->total_size == 0)    return;  /* We're interested in three areas of the frame here:         A: the register save area	 B: the old FP	 C: the header after B     If the frame pointer isn't used, we'll have to set up A, B and C     using the stack pointer.  If the frame pointer is used, we'll access     them as follows:         A: set up using sp	 B: set up using sp or a temporary (see below)	 C: set up using fp     We set up B using the stack pointer if the frame is small enough.     Otherwise, it's more efficient to copy the old stack pointer into a     temporary and use that.     Note that it's important to make sure the prologue and epilogue use the     same registers to access A and C, since doing otherwise will confuse     the aliasing code.  */  /* Set up ACCESSOR for accessing region B above.  If the frame pointer     isn't used, the same method will serve for C.  */  accessor.op = FRV_STORE;  if (frame_pointer_needed && info->total_size > 2048)    {      rtx insn;      accessor.base = gen_rtx_REG (Pmode, OLD_SP_REGNO);      accessor.base_offset = info->total_size;      insn = emit_insn (gen_movsi (accessor.base, sp));    }  else    {      accessor.base = stack_pointer_rtx;      accessor.base_offset = 0;    }  /* Allocate the stack space.  */  {    rtx asm_offset = frv_frame_offset_rtx (-info->total_size);    rtx dwarf_offset = GEN_INT (-info->total_size);    frv_frame_insn (gen_stack_adjust (sp, sp, asm_offset),		    gen_rtx_SET (Pmode,				 sp,				 gen_rtx_PLUS (Pmode, sp, dwarf_offset)));  }  /* If the frame pointer is needed, store the old one at (sp + FP_OFFSET)     and point the new one to that location.  */  if (frame_pointer_needed)    {      int fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];      /* ASM_SRC and DWARF_SRC both point to the frame header.  ASM_SRC is	 based on ACCESSOR.BASE but DWARF_SRC is always based on the stack	 pointer.  */      rtx asm_src = plus_constant (accessor.base,				   fp_offset - accessor.base_offset);      rtx dwarf_src = plus_constant (sp, fp_offset);      /* Store the old frame pointer at (sp + FP_OFFSET).  */      frv_frame_access (&accessor, fp, fp_offset);      /* Set up the new frame pointer.  */      frv_frame_insn (gen_rtx_SET (VOIDmode, fp, asm_src),		      gen_rtx_SET (VOIDmode, fp, dwarf_src));      /* Access region C from the frame pointer.  */      accessor.base = fp;      accessor.base_offset = fp_offset;    }  /* Set up region C.  */  frv_frame_access_multi (&accessor, info, STACK_REGS_STRUCT);  frv_frame_access_multi (&accessor, info, STACK_REGS_LR);  frv_frame_access_multi (&accessor, info, STACK_REGS_STDARG);  /* Set up region A.  */  frv_frame_access_standard_regs (FRV_STORE, info);  /* If this is a varargs/stdarg function, issue a blockage to prevent the     scheduler from moving loads before the stores saving the registers.  */  if (info->stdarg_size > 0)    emit_insn (gen_blockage ());  /* Set up pic register/small data register for this function.  */  if (!TARGET_FDPIC && flag_pic && cfun->uses_pic_offset_table)    emit_insn (gen_pic_prologue (gen_rtx_REG (Pmode, PIC_REGNO),				 gen_rtx_REG (Pmode, LR_REGNO),				 gen_rtx_REG (SImode, OFFSET_REGNO)));}/* Under frv, all of the work is done via frv_expand_epilogue, but   this function provides a convenient place to do cleanup.  */static voidfrv_function_epilogue (FILE *file ATTRIBUTE_UNUSED,                       HOST_WIDE_INT size ATTRIBUTE_UNUSED){  frv_stack_cache = (frv_stack_t *)0;  /* Zap last used registers for conditional execution.  */  memset (&frv_ifcvt.tmp_reg, 0, sizeof (frv_ifcvt.tmp_reg));  /* Release the bitmap of created insns.  */  BITMAP_FREE (frv_ifcvt.scratch_insns_bitmap);}/* Called after register allocation to add any instructions needed for the   epilogue.  Using an epilogue insn is favored compared to putting all of the   instructions in the TARGET_ASM_FUNCTION_PROLOGUE target hook, since   it allows the scheduler to intermix instructions with the saves of   the caller saved registers.  In some cases, it might be necessary   to emit a barrier instruction as the last insn to prevent such   scheduling.  */voidfrv_expand_epilogue (bool emit_return){  frv_stack_t *info = frv_stack_info ();  rtx fp = frame_pointer_rtx;  rtx sp = stack_pointer_rtx;  rtx return_addr;  int fp_offset;  fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];  /* Restore the stack pointer to its original value if alloca or the like     is used.  */  if (! current_function_sp_is_unchanging)    emit_insn (gen_addsi3 (sp, fp, frv_frame_offset_rtx (-fp_offset)));  /* Restore the callee-saved registers that were used in this function.  */  frv_frame_access_standard_regs (FRV_LOAD, info);  /* Set RETURN_ADDR to the address we should return to.  Set it to NULL if     no return instruction should be emitted.  */  if (info->sav

⌨️ 快捷键说明

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