summaryrefslogtreecommitdiff
path: root/gcc/config/mn10300/mn10300.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-10-24 19:18:29 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-10-24 19:18:29 +0000
commitc4cd8f6a5c401b32b4f401de909791536b5b68a5 (patch)
tree6e425b652d9ccf93be2d52a87725410a1a5664c7 /gcc/config/mn10300/mn10300.c
parent9ea36bcb8668f71419bccc5db2534c29840a4aea (diff)
downloadgcc-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.c69
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));
+ }
+}