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

📄 frv.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);      int first = reg_ptr->first;      int last = reg_ptr->last;      int size_1word = 0;      int size_2words = 0;      int regno;      /* Calculate which registers need to be saved & save area size.  */      switch (range)	{	default:	  for (regno = first; regno <= last; regno++)	    {	      if ((regs_ever_live[regno] && !call_used_regs[regno])		  || (current_function_calls_eh_return		      && (regno >= FIRST_EH_REGNUM && regno <= LAST_EH_REGNUM))		  || (!TARGET_FDPIC && flag_pic		      && cfun->uses_pic_offset_table && regno == PIC_REGNO))		{		  info_ptr->save_p[regno] = REG_SAVE_1WORD;		  size_1word += UNITS_PER_WORD;		}	    }	  break;	  /* Calculate whether we need to create a frame after everything else             has been processed.  */	case STACK_REGS_FP:	  break;	case STACK_REGS_LR:	  if (regs_ever_live[LR_REGNO]              || profile_flag	      /* This is set for __builtin_return_address, etc.  */	      || cfun->machine->frame_needed              || (TARGET_LINKED_FP && frame_pointer_needed)              || (!TARGET_FDPIC && flag_pic		  && cfun->uses_pic_offset_table))	    {	      info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;	      size_1word += UNITS_PER_WORD;	    }	  break;	case STACK_REGS_STDARG:	  if (varargs_p)	    {	      /* If this is a stdarg function with a non varardic		 argument split between registers and the stack,		 adjust the saved registers downward.  */	      last -= (ADDR_ALIGN (cfun->pretend_args_size, UNITS_PER_WORD)		       / UNITS_PER_WORD);	      for (regno = first; regno <= last; regno++)		{		  info_ptr->save_p[regno] = REG_SAVE_1WORD;		  size_1word += UNITS_PER_WORD;		}	      info_ptr->stdarg_size = size_1word;	    }	  break;	case STACK_REGS_STRUCT:	  if (cfun->returns_struct)	    {	      info_ptr->save_p[FRV_STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;	      size_1word += UNITS_PER_WORD;	    }	  break;	}      if (size_1word)	{	  /* If this is a field, it only takes one word.  */	  if (reg_ptr->field_p)	    size_1word = UNITS_PER_WORD;	  /* Determine which register pairs can be saved together.  */	  else if (reg_ptr->dword_p && TARGET_DWORD)	    {	      for (regno = first; regno < last; regno += 2)		{		  if (info_ptr->save_p[regno] && info_ptr->save_p[regno+1])		    {		      size_2words += 2 * UNITS_PER_WORD;		      size_1word -= 2 * UNITS_PER_WORD;		      info_ptr->save_p[regno] = REG_SAVE_2WORDS;		      info_ptr->save_p[regno+1] = REG_SAVE_NO_SAVE;		    }		}	    }	  reg_ptr->size_1word = size_1word;	  reg_ptr->size_2words = size_2words;	  if (! reg_ptr->special_p)	    {	      info_ptr->regs_size_1word += size_1word;	      info_ptr->regs_size_2words += size_2words;	    }	}    }  /* Set up the sizes of each each field in the frame body, making the sizes     of each be divisible by the size of a dword if dword operations might     be used, or the size of a word otherwise.  */  alignment = (TARGET_DWORD? 2 * UNITS_PER_WORD : UNITS_PER_WORD);  info_ptr->parameter_size = ADDR_ALIGN (cfun->outgoing_args_size, alignment);  info_ptr->regs_size = ADDR_ALIGN (info_ptr->regs_size_2words				    + info_ptr->regs_size_1word,				    alignment);  info_ptr->vars_size = ADDR_ALIGN (get_frame_size (), alignment);  info_ptr->pretend_size = cfun->pretend_args_size;  /* Work out the size of the frame, excluding the header.  Both the frame     body and register parameter area will be dword-aligned.  */  info_ptr->total_size    = (ADDR_ALIGN (info_ptr->parameter_size		   + info_ptr->regs_size		   + info_ptr->vars_size,		   2 * UNITS_PER_WORD)       + ADDR_ALIGN (info_ptr->pretend_size		     + info_ptr->stdarg_size,		     2 * UNITS_PER_WORD));  /* See if we need to create a frame at all, if so add header area.  */  if (info_ptr->total_size  > 0      || frame_pointer_needed      || info_ptr->regs[STACK_REGS_LR].size_1word > 0      || info_ptr->regs[STACK_REGS_STRUCT].size_1word > 0)    {      offset = info_ptr->parameter_size;      info_ptr->header_size = 4 * UNITS_PER_WORD;      info_ptr->total_size += 4 * UNITS_PER_WORD;      /* Calculate the offsets to save normal register pairs.  */      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_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[FRV_STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;	  info_ptr->reg_offset[FRV_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 (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);}/* Used during final to control the packing of insns.  The value is   1 if the current instruction should be packed with the next one,   0 if it shouldn't or -1 if packing is disabled altogether.  */static int frv_insn_packing_flag;/* True if the current function contains a far jump.  */static intfrv_function_contains_far_jump (void){  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 *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 ();  /* Allow the garbage collector to free the nops created by frv_reorg.  */  memset (frv_nops, 0, sizeof (frv_nops));}/* Return the next available temporary register in a given class.  */static rtxfrv_alloc_temp_reg (     frv_tmp_reg_t *info,	/* which registers are available */     enum reg_class class,	/* register class desired */

⌨️ 快捷键说明

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