From 4f2cb637a76ed0772ea22ee6d8aa73a391ee3e7e Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 8 May 2009 21:26:31 +0000 Subject: Merge from mainline. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/pretty-ipa@147296 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/m68k/m68k.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'gcc/config/m68k/m68k.c') diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index bccb8348a55..e4bb1e2b4a2 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -143,6 +143,7 @@ static tree m68k_handle_fndecl_attribute (tree *node, tree name, static void m68k_compute_frame_layout (void); static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); static bool m68k_ok_for_sibcall_p (tree, tree); +static rtx m68k_legitimize_address (rtx, rtx, enum machine_mode); static bool m68k_rtx_costs (rtx, int, int, int *, bool); #if M68K_HONOR_TARGET_STRICT_ALIGNMENT static bool m68k_return_in_memory (const_tree, const_tree); @@ -195,6 +196,9 @@ int m68k_last_compare_had_fp_operands; #undef TARGET_ASM_FILE_START_APP_OFF #define TARGET_ASM_FILE_START_APP_OFF true +#undef TARGET_LEGITIMIZE_ADDRESS +#define TARGET_LEGITIMIZE_ADDRESS m68k_legitimize_address + #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST m68k_sched_adjust_cost @@ -1422,6 +1426,83 @@ m68k_legitimize_sibcall_address (rtx x) return replace_equiv_address (x, gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM)); } +/* Convert X to a legitimate address and return it if successful. Otherwise + return X. + + For the 68000, we handle X+REG by loading X into a register R and + using R+REG. R will go in an address reg and indexing will be used. + However, if REG is a broken-out memory address or multiplication, + nothing needs to be done because REG can certainly go in an address reg. */ + +rtx +m68k_legitimize_address (rtx x, rtx oldx, enum machine_mode mode) +{ + if (GET_CODE (x) == PLUS) + { + int ch = (x) != (oldx); + int copied = 0; + +#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; } + + if (GET_CODE (XEXP (x, 0)) == MULT) + { + COPY_ONCE (x); + XEXP (x, 0) = force_operand (XEXP (x, 0), 0); + } + if (GET_CODE (XEXP (x, 1)) == MULT) + { + COPY_ONCE (x); + XEXP (x, 1) = force_operand (XEXP (x, 1), 0); + } + if (ch) + { + if (GET_CODE (XEXP (x, 1)) == REG + && GET_CODE (XEXP (x, 0)) == REG) + { + if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT) + { + COPY_ONCE (x); + x = force_operand (x, 0); + } + return x; + } + if (memory_address_p (mode, x)) + return x; + } + if (GET_CODE (XEXP (x, 0)) == REG + || (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND + && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG + && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)) + { + rtx temp = gen_reg_rtx (Pmode); + rtx val = force_operand (XEXP (x, 1), 0); + emit_move_insn (temp, val); + COPY_ONCE (x); + XEXP (x, 1) = temp; + if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT + && GET_CODE (XEXP (x, 0)) == REG) + x = force_operand (x, 0); + } + else if (GET_CODE (XEXP (x, 1)) == REG + || (GET_CODE (XEXP (x, 1)) == SIGN_EXTEND + && GET_CODE (XEXP (XEXP (x, 1), 0)) == REG + && GET_MODE (XEXP (XEXP (x, 1), 0)) == HImode)) + { + rtx temp = gen_reg_rtx (Pmode); + rtx val = force_operand (XEXP (x, 0), 0); + emit_move_insn (temp, val); + COPY_ONCE (x); + XEXP (x, 0) = temp; + if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT + && GET_CODE (XEXP (x, 1)) == REG) + x = force_operand (x, 0); + } + } + + return x; +} + + /* Output a dbCC; jCC sequence. Note we do not handle the floating point version of this sequence (Fdbcc). We also do not handle alternative conditions when CC_NO_OVERFLOW is -- cgit v1.2.3