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));
+ }
+}
base = XEXP (X, 1), index = XEXP (X, 0); \
if (base != 0 && index != 0) \
{ \
- if (CONSTANT_ADDRESS_P (index)) \
+ if (GET_CODE (index) == CONST_INT) \
goto ADDR; \
if (REG_P (index) \
&& REG_OK_FOR_INDEX_P (index) \
It is always safe for this macro to do nothing. It exists to recognize
opportunities to optimize the output. */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+extern struct rtx_def *legitimize_address ();
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
+{ rtx orig_x = (X); \
+ (X) = legitimize_address (X, OLDX, MODE); \
+ if ((X) != orig_x && memory_address_p (MODE, X)) \
+ goto WIN; }
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for. */
extern enum reg_class secondary_reload_class ();
extern int initial_offset ();
extern char *output_tst ();
+int symbolic_operand ();