diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1997-10-24 19:18:29 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1997-10-24 19:18:29 +0000 |
commit | c4cd8f6a5c401b32b4f401de909791536b5b68a5 (patch) | |
tree | 6e425b652d9ccf93be2d52a87725410a1a5664c7 /gcc/config/mn10300/mn10300.c | |
parent | 9ea36bcb8668f71419bccc5db2534c29840a4aea (diff) | |
download | gcc-c4cd8f6a5c401b32b4f401de909791536b5b68a5.tar.gz |
* mn10300.c (symbolic_operand, legitimize_address): New functions.
* mn10300.h (LEGITIMIZE_ADDRESS): Call legitimize_address.
(GO_IF_LEGITIMATE_ADDRESS): Don't allow base + symbolic.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16158 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/mn10300/mn10300.c')
-rw-r--r-- | gcc/config/mn10300/mn10300.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index e5559212b07..8bb5371ad73 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -989,3 +989,72 @@ impossible_plus_operand (op, mode) return 0; } + +/* Return 1 if X contains a symbolic expression. We know these + expressions will have one of a few well defined forms, so + we need only check those forms. */ +int +symbolic_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } +} + +/* Try machine dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + Normally it is always safe for this macro to do nothing. It exists to + recognize opportunities to optimize the output. + + But on a few ports with segmented architectures and indexed addressing + (mn10300, hppa) it is used to rewrite certain problematical addresses. */ +rtx +legitimize_address (x, oldx, mode) + rtx x; + rtx oldx; + enum machine_mode mode; +{ + /* Uh-oh. We might have an address for x[n-100000]. This needs + special handling to avoid creating an indexed memory address + with x-100000 as the base. */ + if (GET_CODE (x) == PLUS + && symbolic_operand (XEXP (x, 1), VOIDmode)) + { + /* Ugly. We modify things here so that the address offset specified + by the index expression is computed first, then added to x to form + the entire address. */ + + rtx regx1, regx2, regy1, regy2, y; + + /* Strip off any CONST. */ + y = XEXP (x, 1); + if (GET_CODE (y) == CONST) + y = XEXP (y, 0); + + regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0)); + regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0)); + regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0)); + regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2)); + return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1)); + } +} |