📄 frv.c
字号:
* +---------------+-----------------------+-----------------------+ * |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 + -