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