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

📄 frv.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	      int first = reg_ptr->first;	      int last = reg_ptr->last;	      int regno;	      for (regno = first; regno <= last; regno++)		if (info_ptr->save_p[regno] == REG_SAVE_2WORDS		    && regno != FRAME_POINTER_REGNUM		    && (regno < FIRST_ARG_REGNUM			|| regno > LAST_ARG_REGNUM))		  {		    info_ptr->reg_offset[regno] = offset;		    offset += 2 * UNITS_PER_WORD;		  }	    }	}      /* Calculate the offsets to save normal single registers */      for (range = 0; range < STACK_REGS_MAX; range++)	{	  frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);	  if (! reg_ptr->special_p)	    {	      int first = reg_ptr->first;	      int last = reg_ptr->last;	      int regno;	      for (regno = first; regno <= last; regno++)		if (info_ptr->save_p[regno] == REG_SAVE_1WORD		    && regno != FRAME_POINTER_REGNUM		    && (regno < FIRST_ARG_REGNUM			|| regno > LAST_ARG_REGNUM))		  {		    info_ptr->reg_offset[regno] = offset;		    offset += UNITS_PER_WORD;		  }	    }	}      /* Calculate the offset to save the local variables at.  */      offset = ADDR_ALIGN (offset, alignment);      if (info_ptr->vars_size)	{	  info_ptr->vars_offset = offset;	  offset += info_ptr->vars_size;	}      /* Align header to a dword-boundary.  */      offset = ADDR_ALIGN (offset, 2 * UNITS_PER_WORD);      /* Calculate the offsets in the fixed frame.  */      info_ptr->save_p[FRAME_POINTER_REGNUM] = REG_SAVE_1WORD;      info_ptr->reg_offset[FRAME_POINTER_REGNUM] = offset;      info_ptr->regs[STACK_REGS_FP].size_1word = UNITS_PER_WORD;      info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;      info_ptr->reg_offset[LR_REGNO] = offset + 2*UNITS_PER_WORD;      info_ptr->regs[STACK_REGS_LR].size_1word = UNITS_PER_WORD;      if (cfun->returns_struct)	{	  info_ptr->save_p[STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;	  info_ptr->reg_offset[STRUCT_VALUE_REGNUM] = offset + UNITS_PER_WORD;	  info_ptr->regs[STACK_REGS_STRUCT].size_1word = UNITS_PER_WORD;	}      /* Calculate the offsets to store the arguments passed in registers         for stdarg functions.  The register pairs are first and the single         register if any is last.  The register save area starts on a         dword-boundary.  */      if (info_ptr->stdarg_size)	{	  int first = info_ptr->regs[STACK_REGS_STDARG].first;	  int last  = info_ptr->regs[STACK_REGS_STDARG].last;	  int regno;	  /* Skip the header.  */	  offset += 4 * UNITS_PER_WORD;	  for (regno = first; regno <= last; regno++)	    {	      if (info_ptr->save_p[regno] == REG_SAVE_2WORDS)		{		  info_ptr->reg_offset[regno] = offset;		  offset += 2 * UNITS_PER_WORD;		}	      else if (info_ptr->save_p[regno] == REG_SAVE_1WORD)		{		  info_ptr->reg_offset[regno] = offset;		  offset += UNITS_PER_WORD;		}	    }	}    }  if (reload_completed)    frv_stack_cache = info_ptr;  return info_ptr;}/* Print the information about the frv stack offsets, etc. when debugging. */voidfrv_debug_stack (info)     frv_stack_t *info;{  int range;  if (!info)    info = frv_stack_info ();  fprintf (stderr, "\nStack information for function %s:\n",	   ((current_function_decl && DECL_NAME (current_function_decl))	    ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))	    : "<unknown>"));  fprintf (stderr, "\ttotal_size\t= %6d\n", info->total_size);  fprintf (stderr, "\tvars_size\t= %6d\n", info->vars_size);  fprintf (stderr, "\tparam_size\t= %6d\n", info->parameter_size);  fprintf (stderr, "\tregs_size\t= %6d, 1w = %3d, 2w = %3d\n",	   info->regs_size, info->regs_size_1word, info->regs_size_2words);  fprintf (stderr, "\theader_size\t= %6d\n", info->header_size);  fprintf (stderr, "\tpretend_size\t= %6d\n", info->pretend_size);  fprintf (stderr, "\tvars_offset\t= %6d\n", info->vars_offset);  fprintf (stderr, "\tregs_offset\t= %6d\n", info->regs_offset);  for (range = 0; range < STACK_REGS_MAX; range++)    {      frv_stack_regs_t *regs = &(info->regs[range]);      if ((regs->size_1word + regs->size_2words) > 0)	{	  int first = regs->first;	  int last  = regs->last;	  int regno;	  fprintf (stderr, "\t%s\tsize\t= %6d, 1w = %3d, 2w = %3d, save =",		   regs->name, regs->size_1word + regs->size_2words,		   regs->size_1word, regs->size_2words);	  for (regno = first; regno <= last; regno++)	    {	      if (info->save_p[regno] == REG_SAVE_1WORD)		fprintf (stderr, " %s (%d)", reg_names[regno],			 info->reg_offset[regno]);	      else if (info->save_p[regno] == REG_SAVE_2WORDS)		fprintf (stderr, " %s-%s (%d)", reg_names[regno],			 reg_names[regno+1], info->reg_offset[regno]);	    }	  fputc ('\n', stderr);	}    }  fflush (stderr);}/* The following variable value is TRUE if the next output insn should   finish cpu cycle.  In order words the insn will have packing bit   (which means absence of asm code suffix `.p' on assembler. */static int frv_insn_packing_flag;/* True if the current function contains a far jump.  */static intfrv_function_contains_far_jump (){  rtx insn = get_insns ();  while (insn != NULL	 && !(GET_CODE (insn) == JUMP_INSN	      /* Ignore tablejump patterns.  */	      && GET_CODE (PATTERN (insn)) != ADDR_VEC	      && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC	      && get_attr_far_jump (insn) == FAR_JUMP_YES))    insn = NEXT_INSN (insn);  return (insn != NULL);}/* For the FRV, this function makes sure that a function with far jumps   will return correctly.  It also does the VLIW packing.  */static voidfrv_function_prologue (file, size)     FILE *file;     HOST_WIDE_INT size ATTRIBUTE_UNUSED;{  /* If no frame was created, check whether the function uses a call     instruction to implement a far jump.  If so, save the link in gr3 and     replace all returns to LR with returns to GR3.  GR3 is used because it     is call-clobbered, because is not available to the register allocator,     and because all functions that take a hidden argument pointer will have     a stack frame.  */  if (frv_stack_info ()->total_size == 0 && frv_function_contains_far_jump ())    {      rtx insn;      /* Just to check that the above comment is true.  */      if (regs_ever_live[GPR_FIRST + 3])	abort ();      /* Generate the instruction that saves the link register.  */      fprintf (file, "\tmovsg lr,gr3\n");      /* Replace the LR with GR3 in *return_internal patterns.  The insn	 will now return using jmpl @(gr3,0) rather than bralr.  We cannot	 simply emit a different assembly directive because bralr and jmpl	 execute in different units.  */      for (insn = get_insns(); insn != NULL; insn = NEXT_INSN (insn))	if (GET_CODE (insn) == JUMP_INSN)	  {	    rtx pattern = PATTERN (insn);	    if (GET_CODE (pattern) == PARALLEL		&& XVECLEN (pattern, 0) >= 2		&& GET_CODE (XVECEXP (pattern, 0, 0)) == RETURN		&& GET_CODE (XVECEXP (pattern, 0, 1)) == USE)	      {		rtx address = XEXP (XVECEXP (pattern, 0, 1), 0);		if (GET_CODE (address) == REG && REGNO (address) == LR_REGNO)		  REGNO (address) = GPR_FIRST + 3;	      }	  }    }  frv_pack_insns ();  frv_insn_packing_flag = TRUE;}/* Return the next available temporary register in a given class.  */static rtxfrv_alloc_temp_reg (info, class, mode, mark_as_used, no_abort)     frv_tmp_reg_t *info;	/* which registers are available */     enum reg_class class;	/* register class desired */     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 (offset)     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 (mode, base, offset)     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 (reg, offset)     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 (pattern, dwarf_pattern)     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 (accessor, reg, stack_offset)     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)    {

⌨️ 快捷键说明

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