+ int have_sym = 0;
+ int have_toc = 0;
+ return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
+}
+
+/* SPE offset addressing is limited to 5-bits worth of double words. */
+#define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
+
+bool
+legitimate_constant_pool_address_p (x)
+ rtx x;
+{
+ return (TARGET_TOC
+ && GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER)
+ && constant_pool_expr_p (XEXP (x, 1)));
+}
+
+static bool
+legitimate_small_data_p (mode, x)
+ enum machine_mode mode;
+ rtx x;
+{
+ return (DEFAULT_ABI == ABI_V4
+ && !flag_pic && !TARGET_TOC
+ && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)
+ && small_data_operand (x, mode));
+}
+
+static bool
+legitimate_offset_address_p (mode, x, strict)
+ enum machine_mode mode;
+ rtx x;
+ int strict;
+{
+ unsigned HOST_WIDE_INT offset, extra;
+
+ if (GET_CODE (x) != PLUS)
+ return false;
+ if (GET_CODE (XEXP (x, 0)) != REG)
+ return false;
+ if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
+ return false;
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+ return false;
+
+ offset = INTVAL (XEXP (x, 1));
+ extra = 0;
+ switch (mode)
+ {
+ case V16QImode:
+ case V8HImode:
+ case V4SFmode:
+ case V4SImode:
+ /* AltiVec vector modes. Only reg+reg addressing is valid here,
+ which leaves the only valid constant offset of zero, which by
+ canonicalization rules is also invalid. */
+ return false;
+
+ case V4HImode:
+ case V2SImode:
+ case V1DImode:
+ case V2SFmode:
+ /* SPE vector modes. */
+ return SPE_CONST_OFFSET_OK (offset);
+
+ case DFmode:
+ case DImode:
+ if (TARGET_32BIT)
+ extra = 4;
+ else if (offset & 3)
+ return false;
+ break;
+
+ case TFmode:
+ case TImode:
+ if (TARGET_32BIT)
+ extra = 12;
+ else if (offset & 3)
+ return false;
+ else
+ extra = 8;
+ break;
+
+ default:
+ break;
+ }
+
+ return (offset + extra >= offset) && (offset + extra + 0x8000 < 0x10000);
+}
+
+static bool
+legitimate_indexed_address_p (x, strict)
+ rtx x;
+ int strict;
+{
+ rtx op0, op1;
+
+ if (GET_CODE (x) != PLUS)
+ return false;
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+
+ if (!REG_P (op0) || !REG_P (op1))
+ return false;
+
+ return ((INT_REG_OK_FOR_BASE_P (op0, strict)
+ && INT_REG_OK_FOR_INDEX_P (op1, strict))
+ || (INT_REG_OK_FOR_BASE_P (op1, strict)
+ && INT_REG_OK_FOR_INDEX_P (op0, strict)));
+}
+
+static inline bool
+legitimate_indirect_address_p (x, strict)
+ rtx x;
+ int strict;
+{
+ return GET_CODE (x) == REG && INT_REG_OK_FOR_BASE_P (x, strict);
+}
+
+static bool
+legitimate_lo_sum_address_p (mode, x, strict)
+ enum machine_mode mode;
+ rtx x;
+ int strict;
+{
+ if (GET_CODE (x) != LO_SUM)
+ return false;
+ if (GET_CODE (XEXP (x, 0)) != REG)
+ return false;
+ if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
+ return false;
+ x = XEXP (x, 1);
+
+ if (TARGET_ELF)
+ {
+ if (DEFAULT_ABI != ABI_AIX && flag_pic)
+ return false;
+ if (TARGET_TOC)
+ return false;
+ if (GET_MODE_NUNITS (mode) != 1)
+ return false;
+ if (GET_MODE_BITSIZE (mode) > 32
+ && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode))
+ return false;
+
+ return CONSTANT_P (x);
+ }
+
+ return false;