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

📄 frv.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
 * +---------------+-----------------------+-----------------------+ * |GR0            |Zero register          |        -              | * |GR1            |Stack pointer(SP)      |        -              | * |GR2            |Frame pointer(FP)      |        -              | * |GR3            |Hidden parameter       |        caller save    | * |GR4-GR7        |        -              |        caller save    | * |GR8-GR13       |Argument register      |        caller save    | * |GR14-GR15      |        -              |        caller save    | * |GR16-GR31      |        -              |        callee save    | * |GR32-GR47      |        -              |        caller save    | * |GR48-GR63      |        -              |        callee save    | * |FR0-FR15       |        -              |        caller save    | * |FR16-FR31      |        -              |        callee save    | * |FR32-FR47      |        -              |        caller save    | * |FR48-FR63      |        -              |        callee save    | * +---------------+-----------------------+-----------------------+ * * Stack frame setup: * Low *     SP-> |-----------------------------------| *	    |         Argument area		| *	    |-----------------------------------| *	    |	 Register save area		| *	    |-----------------------------------| *	    |	Local variable save area	| *     FP-> |-----------------------------------| *	    |	    Old FP			| *	    |-----------------------------------| *	    |    Hidden parameter save area     | *	    |-----------------------------------| *	    | Return address(LR) storage area   | *	    |-----------------------------------| *	    |     Padding for alignment         | *	    |-----------------------------------| *	    |     Register argument area	| * OLD SP-> |-----------------------------------| *          |       Parameter area		| *          |-----------------------------------| * High * * Argument area/Parameter area: * * When a function is called, this area is used for argument transfer.  When * the argument is set up by the caller function, this area is referred to as * the argument area.  When the argument is referenced by the callee function, * this area is referred to as the parameter area.  The area is allocated when * all arguments cannot be placed on the argument register at the time of * argument transfer. * * Register save area: * * This is a register save area that must be guaranteed for the caller * function.  This area is not secured when the register save operation is not * needed. * * Local variable save area: * * This is the area for local variables and temporary variables. * * Old FP: * * This area stores the FP value of the caller function. * * Hidden parameter save area: * * This area stores the start address of the return value storage * area for a struct/union return function. * When a struct/union is used as the return value, the caller * function stores the return value storage area start address in * register GR3 and passes it to the caller function. * The callee function interprets the address stored in the GR3 * as the return value storage area start address. * When register GR3 needs to be saved into memory, the callee * function saves it in the hidden parameter save area.  This * area is not secured when the save operation is not needed. * * Return address(LR) storage area: * * This area saves the LR.  The LR stores the address of a return to the caller * function for the purpose of function calling. * * Argument register area: * * This area saves the argument register.  This area is not secured when the * save operation is not needed. * * Argument: * * Arguments, the count of which equals the count of argument registers (6 * words), are positioned in registers GR8 to GR13 and delivered to the callee * function.  When a struct/union return function is called, the return value * area address is stored in register GR3.  Arguments not placed in the * argument registers will be stored in the stack argument area for transfer * purposes.  When an 8-byte type argument is to be delivered using registers, * it is divided into two and placed in two registers for transfer.  When * argument registers must be saved to memory, the callee function secures an * argument register save area in the stack.  In this case, a continuous * argument register save area must be established in the parameter area.  The * argument register save area must be allocated as needed to cover the size of * the argument register to be saved.  If the function has a variable count of * arguments, it saves all argument registers in the argument register save * area. * * Argument Extension Format: * * When an argument is to be stored in the stack, its type is converted to an * extended type in accordance with the individual argument type.  The argument * is freed by the caller function after the return from the callee function is * made. * * +-----------------------+---------------+------------------------+ * |    Argument Type      |Extended Type  |Stack Storage Size(byte)| * +-----------------------+---------------+------------------------+ * |char                   |int            |        4		    | * |signed char            |int            |        4		    | * |unsigned char          |int            |        4		    | * |[signed] short int     |int            |        4		    | * |unsigned short int     |int            |        4		    | * |[signed] int           |No extension   |        4		    | * |unsigned int           |No extension   |        4		    | * |[signed] long int      |No extension   |        4		    | * |unsigned long int      |No extension   |        4		    | * |[signed] long long int |No extension   |        8		    | * |unsigned long long int |No extension   |        8		    | * |float                  |double         |        8		    | * |double                 |No extension   |        8		    | * |long double            |No extension   |        8		    | * |pointer                |No extension   |        4		    | * |struct/union           |-              |        4 (*1)	    | * +-----------------------+---------------+------------------------+ * * When a struct/union is to be delivered as an argument, the caller copies it * to the local variable area and delivers the address of that area. * * Return Value: * * +-------------------------------+----------------------+ * |Return Value Type              |Return Value Interface| * +-------------------------------+----------------------+ * |void                           |None                  | * |[signed|unsigned] char         |GR8                   | * |[signed|unsigned] short int    |GR8                   | * |[signed|unsigned] int          |GR8                   | * |[signed|unsigned] long int     |GR8                   | * |pointer                        |GR8                   | * |[signed|unsigned] long long int|GR8 & GR9             | * |float                          |GR8                   | * |double                         |GR8 & GR9             | * |long double                    |GR8 & GR9             | * |struct/union                   |(*1)                  | * +-------------------------------+----------------------+ * * When a struct/union is used as the return value, the caller function stores * the start address of the return value storage area into GR3 and then passes * it to the callee function.  The callee function interprets GR3 as the start * address of the return value storage area.  When this address needs to be * saved in memory, the callee function secures the hidden parameter save area * and saves the address in that area. */frv_stack_t *frv_stack_info (){  static frv_stack_t info, zero_info;  frv_stack_t *info_ptr	= &info;  tree fndecl		= current_function_decl;  int varargs_p		= 0;  tree cur_arg;  tree next_arg;  int range;  int alignment;  int offset;  /* If we've already calculated the values and reload is complete, just return now */  if (frv_stack_cache)    return frv_stack_cache;  /* Zero all fields */  info = zero_info;  /* Set up the register range information */  info_ptr->regs[STACK_REGS_GPR].name         = "gpr";  info_ptr->regs[STACK_REGS_GPR].first        = LAST_ARG_REGNUM + 1;  info_ptr->regs[STACK_REGS_GPR].last         = GPR_LAST;  info_ptr->regs[STACK_REGS_GPR].dword_p      = TRUE;  info_ptr->regs[STACK_REGS_FPR].name         = "fpr";  info_ptr->regs[STACK_REGS_FPR].first        = FPR_FIRST;  info_ptr->regs[STACK_REGS_FPR].last         = FPR_LAST;  info_ptr->regs[STACK_REGS_FPR].dword_p      = TRUE;  info_ptr->regs[STACK_REGS_LR].name          = "lr";  info_ptr->regs[STACK_REGS_LR].first         = LR_REGNO;  info_ptr->regs[STACK_REGS_LR].last          = LR_REGNO;  info_ptr->regs[STACK_REGS_LR].special_p     = 1;  info_ptr->regs[STACK_REGS_CC].name          = "cc";  info_ptr->regs[STACK_REGS_CC].first         = CC_FIRST;  info_ptr->regs[STACK_REGS_CC].last          = CC_LAST;  info_ptr->regs[STACK_REGS_CC].field_p       = TRUE;  info_ptr->regs[STACK_REGS_LCR].name         = "lcr";  info_ptr->regs[STACK_REGS_LCR].first        = LCR_REGNO;  info_ptr->regs[STACK_REGS_LCR].last         = LCR_REGNO;  info_ptr->regs[STACK_REGS_STDARG].name      = "stdarg";  info_ptr->regs[STACK_REGS_STDARG].first     = FIRST_ARG_REGNUM;  info_ptr->regs[STACK_REGS_STDARG].last      = LAST_ARG_REGNUM;  info_ptr->regs[STACK_REGS_STDARG].dword_p   = 1;  info_ptr->regs[STACK_REGS_STDARG].special_p = 1;  info_ptr->regs[STACK_REGS_STRUCT].name      = "struct";  info_ptr->regs[STACK_REGS_STRUCT].first     = STRUCT_VALUE_REGNUM;  info_ptr->regs[STACK_REGS_STRUCT].last      = STRUCT_VALUE_REGNUM;  info_ptr->regs[STACK_REGS_STRUCT].special_p = 1;  info_ptr->regs[STACK_REGS_FP].name          = "fp";  info_ptr->regs[STACK_REGS_FP].first         = FRAME_POINTER_REGNUM;  info_ptr->regs[STACK_REGS_FP].last          = FRAME_POINTER_REGNUM;  info_ptr->regs[STACK_REGS_FP].special_p     = 1;  /* Determine if this is a stdarg function.  If so, allocate space to store     the 6 arguments.  */  if (cfun->stdarg)    varargs_p = 1;  else    {      /* Find the last argument, and see if it is __builtin_va_alist.  */      for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg)	{	  next_arg = TREE_CHAIN (cur_arg);	  if (next_arg == (tree)0)	    {	      if (DECL_NAME (cur_arg)		  && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist"))		varargs_p = 1;	      break;	    }	}    }  /* Iterate over all of the register ranges */  for (range = 0; range < STACK_REGS_MAX; range++)    {      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))		  || (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              || frame_pointer_needed              || (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 an 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[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      || 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)	    {

⌨️ 快捷键说明

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