diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 128 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 57 |
4 files changed, 145 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea773b7..e5aa14d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2001-12-19 Dale Johannesen <dalej@apple.com> + + * config/rs6000/rs6000.h: LEGITIMIZE_RELOAD_ADDRESS: + redefine in terms of rs6000_legitimize_reload_address(). + * config/rs6000/rs6000-protos.h: Add this function. + * config/rs6000/rs6000.c: Add this function. Includes + handling for Darwin FP constants. + Wed Dec 19 11:01:21 2001 Jeffrey A Law (law@redhat.com) * config/pa/t-hpux-shlib: New file. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 5a86ab0..c40689e 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -114,6 +114,8 @@ extern struct rtx_def *create_TOC_reference PARAMS ((rtx)); extern void rs6000_emit_eh_toc_restore PARAMS ((rtx)); extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode)); extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode)); +extern rtx rs6000_legitimize_reload_address PARAMS ((rtx, enum machine_mode, + int, int, int, int *)); extern int rs6000_legitimate_address PARAMS ((enum machine_mode, rtx, int)); extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3dca0fa..4a661fc 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */ #include "target.h" #include "target-def.h" #include "langhooks.h" +#include "reload.h" #ifndef TARGET_NO_PROTOTYPE #define TARGET_NO_PROTOTYPE 0 @@ -1757,6 +1758,133 @@ rs6000_legitimize_address (x, oldx, mode) return NULL_RTX; } +/* The convention appears to be to define this wherever it is used. + With legitimize_reload_address now defined here, REG_MODE_OK_FOR_BASE_P + is now used here. */ +#ifndef REG_MODE_OK_FOR_BASE_P +#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO) +#endif + +/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to + replace the input X, or the original X if no replacement is called for. + The output parameter *WIN is 1 if the calling macro should goto WIN, + 0 if it should not. + + For RS/6000, we wish to handle large displacements off a base + register by splitting the addend across an addiu/addis and the mem insn. + This cuts number of extra insns needed from 3 to 1. + + On Darwin, we use this to generate code for floating point constants. + A movsf_low is generated so we wind up with 2 instructions rather than 3. + The Darwin code is inside #if TARGET_MACHO because only then is + machopic_function_base_name() defined. */ +rtx +rs6000_legitimize_reload_address (x, mode, opnum, type, ind_levels, win) + rtx x; + enum machine_mode mode; + int opnum; + int type; + int ind_levels ATTRIBUTE_UNUSED; + int *win; +{ + /* We must recognize output that we have already generated ourselves. */ + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT + && GET_CODE (XEXP (x, 1)) == CONST_INT) + { + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + *win = 1; + return x; + } +#if TARGET_MACHO + if (DEFAULT_ABI == ABI_DARWIN && flag_pic + && GET_CODE (x) == LO_SUM + && GET_CODE (XEXP (x, 0)) == PLUS + && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx + && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH + && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST + && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1) + && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS + && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF) + { + /* Result of previous invocation of this function on Darwin + floating point constant. */ + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, + opnum, (enum reload_type)type); + *win = 1; + return x; + } +#endif + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == REG + && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER + && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) + && GET_CODE (XEXP (x, 1)) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); + HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; + HOST_WIDE_INT high + = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000; + + /* Check for 32-bit overflow. */ + if (high + low != val) + { + *win = 0; + return x; + } + + /* Reload the high part into a base reg; leave the low part + in the mem directly. */ + + x = gen_rtx_PLUS (GET_MODE (x), + gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), + GEN_INT (high)), + GEN_INT (low)); + + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + *win = 1; + return x; + } +#if TARGET_MACHO + if (GET_CODE (x) == SYMBOL_REF + && DEFAULT_ABI == ABI_DARWIN + && flag_pic) + { + /* Darwin load of floating point constant. */ + rtx offset = gen_rtx (CONST, Pmode, + gen_rtx (MINUS, Pmode, x, + gen_rtx (SYMBOL_REF, Pmode, + machopic_function_base_name ()))); + x = gen_rtx (LO_SUM, GET_MODE (x), + gen_rtx (PLUS, Pmode, pic_offset_table_rtx, + gen_rtx (HIGH, Pmode, offset)), offset); + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, + opnum, (enum reload_type)type); + *win = 1; + return x; + } +#endif + if (TARGET_TOC + && CONSTANT_POOL_EXPR_P (x) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode)) + { + (x) = create_TOC_reference (x); + *win = 1; + return x; + } + *win = 0; + return x; +} + /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 47cf4d3..40769a0 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2058,59 +2058,16 @@ typedef struct rs6000_args operand. If we find one, push the reload and jump to WIN. This macro is used in only one place: `find_reloads_address' in reload.c. - For RS/6000, we wish to handle large displacements off a base - register by splitting the addend across an addiu/addis and the mem insn. - This cuts number of extra insns needed from 3 to 1. */ + Implemented on rs6000 by rs6000_legitimize_reload_address. + Note that (X) is evaluated twice; this is safe in current usage. */ #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ do { \ - /* We must recognize output that we have already generated ourselves. */ \ - if (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \ - BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - goto WIN; \ - } \ - if (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == REG \ - && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \ - && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \ - HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; \ - HOST_WIDE_INT high \ - = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000; \ - \ - /* Check for 32-bit overflow. */ \ - if (high + low != val) \ - break; \ - \ - /* Reload the high part into a base reg; leave the low part \ - in the mem directly. */ \ - \ - X = gen_rtx_PLUS (GET_MODE (X), \ - gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \ - GEN_INT (high)), \ - GEN_INT (low)); \ - \ - push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \ - BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - goto WIN; \ - } \ - else if (TARGET_TOC \ - && CONSTANT_POOL_EXPR_P (X) \ - && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X), MODE)) \ - { \ - (X) = create_TOC_reference (X); \ - goto WIN; \ - } \ + int win; \ + (X) = rs6000_legitimize_reload_address ((X), (MODE), (OPNUM), \ + (int)(TYPE), (IND_LEVELS), &win); \ + if ( win ) \ + goto WIN; \ } while (0) /* Go to LABEL if ADDR (a legitimate address expression) |