📄 c4x.c
字号:
gen_rtx_REG (QImode, R1_REGNO), GEN_INT(size & 0xffff))); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, R1_REGNO))); RTX_FRAME_RELATED_P (insn) = 1; } else if (size != 0) { /* Local vars take up less than 32767 words, so we can directly add the number. */ insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, SP_REGNO), GEN_INT (size))); RTX_FRAME_RELATED_P (insn) = 1; } for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { if (regs_ever_live[regno] && ! call_used_regs[regno]) { if (IS_FLOAT_CALL_SAVED_REGNO (regno)) { if (TARGET_PRESERVE_FLOAT) { insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } else if ((! dont_push_ar3) || (regno != AR3_REGNO)) { insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } } }}voidc4x_expand_epilogue(){ int regno; int jump = 0; int dont_pop_ar3; rtx insn; int size = get_frame_size (); /* For __assembler__ function build no epilogue. */ if (c4x_assembler_function_p ()) { insn = emit_jump_insn (gen_return_from_epilogue ()); RTX_FRAME_RELATED_P (insn) = 1; return; } /* For __interrupt__ function build specific epilogue. */ if (c4x_interrupt_function_p ()) { for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) { if (! c4x_isr_reg_used_p (regno)) continue; if (regno == DP_REGNO) { insn = emit_insn (gen_pop_dp ()); RTX_FRAME_RELATED_P (insn) = 1; } else { /* We have to use unspec because the compiler will delete insns that are not call-saved. */ if (IS_EXT_REGNO (regno)) { insn = emit_insn (gen_popqf_unspec (gen_rtx_REG (QFmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } if (size) { insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, SP_REGNO), GEN_INT(size))); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, AR3_REGNO))); RTX_FRAME_RELATED_P (insn) = 1; } insn = emit_insn (gen_pop_st ()); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_jump_insn (gen_return_from_interrupt_epilogue ()); RTX_FRAME_RELATED_P (insn) = 1; } else { if (frame_pointer_needed) { if ((size != 0) || (current_function_args_size != 0) || (optimize < 2)) { insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R2_REGNO), gen_rtx_MEM (QImode, gen_rtx_PLUS (QImode, gen_rtx_REG (QImode, AR3_REGNO), GEN_INT(-1))))); RTX_FRAME_RELATED_P (insn) = 1; /* We already have the return value and the fp, so we need to add those to the stack. */ size += 2; jump = 1; dont_pop_ar3 = 1; } else { /* Since ar3 is not used for anything, we don't need to pop it. */ dont_pop_ar3 = 1; } } else { dont_pop_ar3 = 0; /* If we use ar3, we need to pop it. */ if (size || current_function_args_size) { /* If we are ommitting the frame pointer, we still have to make space for it so the offsets are correct unless we don't use anything on the stack at all. */ size += 1; } } /* Now restore the saved registers, putting in the delayed branch where required. */ for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) { if (regs_ever_live[regno] && ! call_used_regs[regno]) { if (regno == AR3_REGNO && dont_pop_ar3) continue; if (IS_FLOAT_CALL_SAVED_REGNO (regno)) { insn = emit_insn (gen_popqf_unspec (gen_rtx_REG (QFmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; if (TARGET_PRESERVE_FLOAT) { insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } else { insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } } if (frame_pointer_needed) { if ((size != 0) || (current_function_args_size != 0) || (optimize < 2)) { /* Restore the old FP. */ insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO), gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO)))); RTX_FRAME_RELATED_P (insn) = 1; } } if (size > 32767) { /* Local vars are too big, it will take multiple operations to decrement SP. */ if (TARGET_C3X) { insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), GEN_INT(size >> 16))); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO), gen_rtx_REG (QImode, R3_REGNO), GEN_INT(-16))); RTX_FRAME_RELATED_P (insn) = 1; } else { insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), GEN_INT(size & ~0xffff))); RTX_FRAME_RELATED_P (insn) = 1; } insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO), gen_rtx_REG (QImode, R3_REGNO), GEN_INT(size & 0xffff))); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, R3_REGNO))); RTX_FRAME_RELATED_P (insn) = 1; } else if (size != 0) { /* Local vars take up less than 32768 words, so we can directly subtract the number. */ insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), gen_rtx_REG (QImode, SP_REGNO), GEN_INT(size))); RTX_FRAME_RELATED_P (insn) = 1; } if (jump) { insn = emit_jump_insn (gen_return_indirect_internal (gen_rtx_REG (QImode, R2_REGNO))); RTX_FRAME_RELATED_P (insn) = 1; } else { insn = emit_jump_insn (gen_return_from_epilogue ()); RTX_FRAME_RELATED_P (insn) = 1; } }}intc4x_null_epilogue_p (){ int regno; if (reload_completed && ! c4x_assembler_function_p () && ! c4x_interrupt_function_p () && ! current_function_calls_alloca && ! current_function_args_size && ! (optimize < 2) && ! get_frame_size ()) { for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) if (regs_ever_live[regno] && ! call_used_regs[regno] && (regno != AR3_REGNO)) return 0; return 1; } return 0;}intc4x_emit_move_sequence (operands, mode) rtx *operands; enum machine_mode mode; { rtx op0 = operands[0]; rtx op1 = operands[1]; if (! reload_in_progress && ! REG_P (op0) && ! REG_P (op1) && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode))) op1 = force_reg (mode, op1); if (GET_CODE (op1) == LO_SUM && GET_MODE (op1) == Pmode && dp_reg_operand (XEXP (op1, 0), mode)) { /* expand_increment will sometimes create a LO_SUM immediate address. */ op1 = XEXP (op1, 1); } else if (symbolic_address_operand (op1, mode)) { if (TARGET_LOAD_ADDRESS) { /* Alias analysis seems to do a better job if we force constant addresses to memory after reload. */ emit_insn (gen_load_immed_address (op0, op1)); return 1; } else { /* Stick symbol or label address into the constant pool. */ op1 = force_const_mem (Pmode, op1); } } else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) { /* We could be a lot smarter about loading some of these constants... */ op1 = force_const_mem (mode, op1); } /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF))) and emit associated (HIGH (SYMREF)) if large memory model. c4x_legitimize_address could be used to do this, perhaps by calling validize_address. */ if (TARGET_EXPOSE_LDP && ! (reload_in_progress || reload_completed) && GET_CODE (op1) == MEM && symbolic_address_operand (XEXP (op1, 0), Pmode)) { rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); if (! TARGET_SMALL) emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0))); op1 = change_address (op1, mode, gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0))); } if (TARGET_EXPOSE_LDP && ! (reload_in_progress || reload_completed) && GET_CODE (op0) == MEM && symbolic_address_operand (XEXP (op0, 0), Pmode)) { rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); if (! TARGET_SMALL) emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0))); op0 = change_address (op0, mode, gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0))); } if (GET_CODE (op0) == SUBREG && mixed_subreg_operand (op0, mode)) { /* We should only generate these mixed mode patterns during RTL generation. If we need do it later on then we'll have to emit patterns that won't clobber CC. */ if (reload_in_progress || reload_completed) abort (); if (GET_MODE (SUBREG_REG (op0)) == QImode) op0 = SUBREG_REG (op0); else if (GET_MODE (SUBREG_REG (op0)) == HImode) { op0 = copy_rtx (op0); PUT_MODE (op0, QImode); } else abort (); if (mode == QFmode) emit_insn (gen_storeqf_int_clobber (op0, op1)); else abort (); return 1; } if (GET_CODE (op1) == SUBREG && mixed_subreg_operand (op1, mode)) { /* We should only generate these mixed mode patterns during RTL generation. If we need do it later on then we'll have to emit patterns that won't clobber CC. */ if (reload_in_progress || reload_completed) abort (); if (GET_MODE (SUBREG_REG (op1)) == QImode) op1 = SUBREG_REG (op1); else if (GET_MODE (SUBREG_REG (op1)) == HImode) { op1 = copy_rtx (op1); PUT_MODE (op1, QImode); } else abort (); if (mode == QFmode) emit_insn (gen_loadqf_int_clobber (op0, op1)); else abort (); return 1; } if (mode == QImode && reg_operand (op0, mode) && const_int_operand (op1, mode) && ! IS_INT16_CONST (INTVAL (op1)) && ! IS_HIGH_CONST (INTVAL (op1))) { emit_insn (gen_loadqi_big_constant (op0, op1)); return 1; } if (mode == HImode && reg_operand (op0, mode) && const_int_operand (op1, mode)) { emit_insn (gen_loadhi_big_constant (op0, op1)); return 1; } /* Adjust operands in case we have modified them. */ operands[0] = op0; operands[1] = op1; /* Emit normal pattern. */ return 0;}voidc4x_emit_libcall (libcall, code, dmode, smode, noperands, operands) rtx libcall; enum rtx_code code; enum machine_mode dmode; enum machine_mode smode; int noperands; rtx *operands;{ rtx ret; rtx insns; rtx equiv; start_sequence (); switch (noperands) { case 2: ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1, operands[1], smode); equiv = gen_rtx (code, dmode, operands[1]); break; case 3: ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2, operands[1], smode, operands[2], smode); equiv = gen_rtx (code, dmode, operands[1], operands[2]); break; default: abort (); } insns = get_insns (); end_sequence (); emit_libcall_block (insns, operands[0], ret, equiv);}voidc4x_emit_libcall3 (libcall, code, mode, operands) rtx libcall; enum rtx_code code; enum machine_mode mode; rtx *operands;{ c4x_emit_libcall (libcall, code, mode, mode, 3, operands);}voidc4x_emit_libcall_mulhi (libcall, code, mode, operands) rtx libcall; enum rtx_code code; enum machine_mode mode; rtx *operands;{ rtx ret; rtx insns; rtx equiv; start_sequence (); ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2, operands[1], mode, operands[2], mode); equiv = gen_rtx_TRUNCATE (mode,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -