📄 v850.c
字号:
registers that need to be saved. To detect this we note that the helper functions always push at least register r29 (provided that the function is not an interrupt handler). */ if (TARGET_PROLOG_FUNCTION && (i == 2 || ((i >= 20) && (i < 30)))) { if (i == 2) { size += 4; reg_saved |= 1L << i; i = 20; } /* Helper functions save all registers between the starting register and the last register, regardless of whether they are actually used by the function or not. */ for (; i <= 29; i++) { size += 4; reg_saved |= 1L << i; } if (regs_ever_live [LINK_POINTER_REGNUM]) { size += 4; reg_saved |= 1L << LINK_POINTER_REGNUM; } } else { for (; i <= 31; i++) if (regs_ever_live[i] && ((! call_used_regs[i]) || i == LINK_POINTER_REGNUM)) { size += 4; reg_saved |= 1L << i; } } } if (p_reg_saved) *p_reg_saved = reg_saved; return size;}intcompute_frame_size (size, p_reg_saved) int size; long *p_reg_saved;{ return (size + compute_register_save_size (p_reg_saved) + current_function_outgoing_args_size);}voidexpand_prologue (){ unsigned int i; int offset; unsigned int size = get_frame_size (); unsigned int actual_fsize; unsigned int init_stack_alloc = 0; rtx save_regs[32]; rtx save_all; unsigned int num_save; unsigned int default_stack; int code; int interrupt_handler = v850_interrupt_function_p (current_function_decl); long reg_saved = 0; actual_fsize = compute_frame_size (size, ®_saved); /* Save/setup global registers for interrupt functions right now. */ if (interrupt_handler) { if (TARGET_V850E && ! TARGET_DISABLE_CALLT) emit_insn (gen_callt_save_interrupt ()); else emit_insn (gen_save_interrupt ()); actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; } /* Save arg registers to the stack if necessary. */ else if (current_function_args_info.anonymous_args) { if (TARGET_PROLOG_FUNCTION) { if (TARGET_V850E && ! TARGET_DISABLE_CALLT) emit_insn (gen_save_r6_r9_v850e ()); else emit_insn (gen_save_r6_r9 ()); } else { offset = 0; for (i = 6; i < 10; i++) { emit_move_insn (gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, offset)), gen_rtx_REG (SImode, i)); offset += 4; } } } /* Identify all of the saved registers. */ num_save = 0; default_stack = 0; for (i = 1; i < 31; i++) { if (((1L << i) & reg_saved) != 0) save_regs[num_save++] = gen_rtx_REG (Pmode, i); } /* If the return pointer is saved, the helper functions also allocate 16 bytes of stack for arguments to be saved in. */ if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) { save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM); default_stack = 16; } /* See if we have an insn that allocates stack space and saves the particular registers we want to. */ save_all = NULL_RTX; if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack) { int alloc_stack = (4 * num_save) + default_stack; int unalloc_stack = actual_fsize - alloc_stack; int save_func_len = 4; int save_normal_len; if (unalloc_stack) save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4; /* see if we would have used ep to save the stack */ if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255) save_normal_len = (3 * 2) + (2 * num_save); else save_normal_len = 4 * num_save; save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4; /* Don't bother checking if we don't actually save any space. This happens for instance if one register is saved and additional stack space is allocated. */ if (save_func_len < save_normal_len) { save_all = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1))); XVECEXP (save_all, 0, 0) = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -alloc_stack)); if (TARGET_V850) { XVECEXP (save_all, 0, num_save+1) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10)); } offset = - default_stack; for (i = 0; i < num_save; i++) { XVECEXP (save_all, 0, i+1) = gen_rtx_SET (VOIDmode, gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, offset)), save_regs[i]); offset -= 4; } code = recog (save_all, NULL_RTX, NULL); if (code >= 0) { rtx insn = emit_insn (save_all); INSN_CODE (insn) = code; actual_fsize -= alloc_stack; if (TARGET_DEBUG) fprintf (stderr, "\Saved %d bytes via prologue function (%d vs. %d) for function %s\n", save_normal_len - save_func_len, save_normal_len, save_func_len, IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); } else save_all = NULL_RTX; } } /* If no prolog save function is available, store the registers the old fashioned way (one by one). */ if (!save_all) { /* Special case interrupt functions that save all registers for a call. */ if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) { if (TARGET_V850E && ! TARGET_DISABLE_CALLT) emit_insn (gen_callt_save_all_interrupt ()); else emit_insn (gen_save_all_interrupt ()); } else { /* If the stack is too big, allocate it in chunks so we can do the register saves. We use the register save size so we use the ep register. */ if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize)) init_stack_alloc = compute_register_save_size (NULL); else init_stack_alloc = actual_fsize; /* Save registers at the beginning of the stack frame */ offset = init_stack_alloc - 4; if (init_stack_alloc) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-init_stack_alloc))); /* Save the return pointer first. */ if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM) { emit_move_insn (gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, offset)), save_regs[--num_save]); offset -= 4; } for (i = 0; i < num_save; i++) { emit_move_insn (gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, offset)), save_regs[i]); offset -= 4; } } } /* Allocate the rest of the stack that was not allocated above (either it is > 32K or we just called a function to save the registers and needed more stack. */ if (actual_fsize > init_stack_alloc) { int diff = actual_fsize - init_stack_alloc; if (CONST_OK_FOR_K (diff)) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-diff))); else { rtx reg = gen_rtx_REG (Pmode, 12); emit_move_insn (reg, GEN_INT (-diff)); emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); } } /* If we need a frame pointer, set it up now. */ if (frame_pointer_needed) emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);}voidexpand_epilogue (){ unsigned int i; int offset; unsigned int size = get_frame_size (); long reg_saved = 0; unsigned int actual_fsize = compute_frame_size (size, ®_saved); unsigned int init_stack_free = 0; rtx restore_regs[32]; rtx restore_all; unsigned int num_restore; unsigned int default_stack; int code; int interrupt_handler = v850_interrupt_function_p (current_function_decl); /* Eliminate the initial stack stored by interrupt functions. */ if (interrupt_handler) { actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; } /* Cut off any dynamic stack created. */ if (frame_pointer_needed) emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); /* Identify all of the saved registers. */ num_restore = 0; default_stack = 0; for (i = 1; i < 31; i++) { if (((1L << i) & reg_saved) != 0) restore_regs[num_restore++] = gen_rtx_REG (Pmode, i); } /* If the return pointer is saved, the helper functions also allocate 16 bytes of stack for arguments to be saved in. */ if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) { restore_regs[num_restore++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM); default_stack = 16; } /* See if we have an insn that restores the particular registers we want to. */ restore_all = NULL_RTX; if (TARGET_PROLOG_FUNCTION && num_restore > 0 && actual_fsize >= default_stack && !interrupt_handler) { int alloc_stack = (4 * num_restore) + default_stack; int unalloc_stack = actual_fsize - alloc_stack; int restore_func_len = 4; int restore_normal_len; if (unalloc_stack) restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4; /* See if we would have used ep to restore the registers. */ if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255) restore_normal_len = (3 * 2) + (2 * num_restore); else restore_normal_len = 4 * num_restore; restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2; /* Don't bother checking if we don't actually save any space. */ if (restore_func_len < restore_normal_len) { restore_all = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_restore + 2)); XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode); XVECEXP (restore_all, 0, 1) = gen_rtx_SET (VOIDmode, stack_pointer_rtx, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (alloc_stack))); offset = alloc_stack - 4; for (i = 0; i < num_restore; i++) { XVECEXP (restore_all, 0, i+2) = gen_rtx_SET (VOIDmode, restore_regs[i], gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, offset))); offset -= 4; } code = recog (restore_all, NULL_RTX, NULL); if (code >= 0) { rtx insn; actual_fsize -= alloc_stack; if (actual_fsize) { if (CONST_OK_FOR_K (actual_fsize)) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (actual_fsize))); else { rtx reg = gen_rtx_REG (Pmode, 12); emit_move_insn (reg, GEN_INT (actual_fsize)); emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); } } insn = emit_jump_insn (restore_all); INSN_CODE (insn) = code; if (TARGET_DEBUG) fprintf (stderr, "\Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", restore_normal_len - restore_func_len, restore_normal_len, restore_func_len, IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); } else restore_all = NULL_RTX; } } /* If no epilog save function is available, restore the registers the old fashioned way (one by one). */ if (!restore_all) { /* If the stack is large, we need to cut it down in 2 pieces. */ if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize)) init_stack_free = 4 * num_restore; else init_stack_free = actual_fsize; /* Deallocate the rest of the stack if it is > 32K. */ if (actual_fsize > init_stack_free) { int diff; diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free); if (CONST_OK_FOR_K (diff)) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (diff))); else { rtx reg = gen_rtx_REG (Pmode, 12); emit_move_insn (reg, GEN_INT (diff)); emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); } } /* Special case interrupt functions that save all registers for a call. */ if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) { if (TARGET_V850E && ! TARGET_DISABLE_CALLT) emit_insn (gen_callt_restore_all_interrupt ()); else emit_insn (gen_restore_all_interrupt ()); } else { /* Restore registers from the beginning of the stack frame. */ offset = init_stack_free - 4; /* Restore the return pointer first. */ if (num_restore > 0 && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM) { emit_move_insn (restore_regs[--num_restore], gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, offset))); offset -= 4; } for (i = 0; i < num_restore; i++) { emit_move_insn (restore_regs[i], gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, offset))); emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i])); offset -= 4; } /* Cut back the remainder of the stack. */ if (init_stack_free) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (init_stack_free))); } /* And return or use reti for interrupt handlers. */ if (interrupt_handler) { if (TARGET_V850E && ! TARGET_DISABLE_CALLT) emit_insn (gen_callt_return_interrupt ()); else emit_jump_insn (gen_return_interrupt ()); } else if (actual_fsize) emit_jump_insn (gen_return_internal ()); else emit_jump_insn (gen_return ()); } v850_interrupt_cache_p = FALSE; v850_interrupt_p = FALSE;}/* Update the condition code from the insn. */voidnotice_update_cc (body, insn) rtx body; rtx insn;{ switch (get_attr_cc (insn)) { case CC_NONE: /* Insn does not affect CC at all. */ break; case CC_NONE_0HIT: /* Insn does not change CC, but the 0'th operand has been changed. */ if (cc_status.value1 != 0 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -