📄 v850.c
字号:
{ 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, gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (-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_PTR); 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) { 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_PTR); 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) { 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))); 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) emit_jump_insn (gen_restore_interrupt ()); else if (actual_fsize) emit_jump_insn (gen_return_internal ()); else emit_jump_insn (gen_return ()); } current_function_anonymous_args = 0; 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_operand[0], cc_status.value1)) cc_status.value1 = 0; break; case CC_SET_ZN: /* Insn sets the Z,N flags of CC to recog_operand[0]. V,C is in an unusable state. */ CC_STATUS_INIT; cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY; cc_status.value1 = recog_operand[0]; break; case CC_SET_ZNV: /* Insn sets the Z,N,V flags of CC to recog_operand[0]. C is in an unusable state. */ CC_STATUS_INIT; cc_status.flags |= CC_NO_CARRY; cc_status.value1 = recog_operand[0]; break; case CC_COMPARE: /* The insn is a compare instruction. */ CC_STATUS_INIT; cc_status.value1 = SET_SRC (body); break; case CC_CLOBBER: /* Insn doesn't leave CC in a usable state. */ CC_STATUS_INIT; break; }}/* Retrieve the data area that has been chosen for the given decl. */v850_data_areav850_get_data_area (decl) tree decl;{ if (lookup_attribute ("sda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE) return DATA_AREA_SDA; if (lookup_attribute ("tda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE) return DATA_AREA_TDA; if (lookup_attribute ("zda", DECL_MACHINE_ATTRIBUTES (decl)) != NULL_TREE) return DATA_AREA_ZDA; return DATA_AREA_NORMAL;}/* Store the indicated data area in the decl's attributes. */static voidv850_set_data_area (decl, data_area) tree decl; v850_data_area data_area;{ tree name; switch (data_area) { case DATA_AREA_SDA: name = get_identifier ("sda"); break; case DATA_AREA_TDA: name = get_identifier ("tda"); break; case DATA_AREA_ZDA: name = get_identifier ("zda"); break; default: return; } DECL_MACHINE_ATTRIBUTES (decl) = tree_cons (name, NULL, DECL_MACHINE_ATTRIBUTES (decl));}/* Return nonzero if ATTR is a valid attribute for DECL. ARGS are the arguments supplied with ATTR. */intv850_valid_machine_decl_attribute (decl, attr, args) tree decl; tree attr; tree args;{ v850_data_area data_area; v850_data_area area; if (args != NULL_TREE) return 0; if (is_attribute_p ("interrupt_handler", attr) || is_attribute_p ("interrupt", attr)) return TREE_CODE (decl) == FUNCTION_DECL; /* Implement data area attribute. */ if (is_attribute_p ("sda", attr)) data_area = DATA_AREA_SDA; else if (is_attribute_p ("tda", attr)) data_area = DATA_AREA_TDA; else if (is_attribute_p ("zda", attr)) data_area = DATA_AREA_ZDA; else return 0; switch (TREE_CODE (decl)) { case VAR_DECL: if (current_function_decl != NULL_TREE) error_with_decl (decl, "\a data area attribute cannot be specified for local variables"); /* Drop through. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -