stw %0,lo16(%2)(%1)"
[(set_attr "type" "store")])
-;; 64-bit MachO load/store support
-
;; Mach-O PIC.
(define_insn "@macho_high_<mode>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
(high:P (match_operand 1 "" "")))]
- "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN)"
+ "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && !flag_pic"
"lis %0,ha16(%1)")
(define_insn "@macho_low_<mode>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
(match_operand 2 "" "")))]
- "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN)"
+ "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && !flag_pic"
+ "la %0,lo16(%2)(%1)")
+
+(define_insn "@machopic_high_<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
+ (high:P (match_operand 1 "macho_pic_address" "")))]
+ "TARGET_MACHO && flag_pic"
+ "lis %0,ha16(%1)")
+
+(define_insn "@machopic_low_<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
+ (match_operand 2 "macho_pic_address" "")))]
+ "TARGET_MACHO && flag_pic"
"la %0,lo16(%2)(%1)")
(define_split
(if_then_else (match_test "TARGET_VSX")
(match_operand 0 "reg_or_cint_operand")
(match_operand 0 "const_int_operand")))
+
+;; Return true if the operand is a valid Mach-O pic address.
+;;
+(define_predicate "macho_pic_address"
+ (match_code "const,unspec")
+{
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+
+ if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_MACHOPIC_OFFSET)
+ return CONSTANT_P (XVECEXP (op, 0, 0));
+ else
+ return false;
+})
else
return force_reg (Pmode, x);
}
- if (SYMBOL_REF_P (x))
+ if (SYMBOL_REF_P (x) && !TARGET_MACHO)
{
enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
if (model != 0)
*ad.inner = gen_rtx_LO_SUM (Pmode, new_reg, addr);
if (!valid_address_p (op, &ad, cn))
{
- *ad.inner = addr; /* Punt. */
- code = -1;
+ /* Try to put lo_sum into register. */
+ insn = emit_insn (gen_rtx_SET
+ (new_reg,
+ gen_rtx_LO_SUM (Pmode, new_reg, addr)));
+ code = recog_memoized (insn);
+ if (code >= 0)
+ {
+ *ad.inner = new_reg;
+ if (!valid_address_p (op, &ad, cn))
+ {
+ *ad.inner = addr;
+ code = -1;
+ }
+ }
+
}
}
if (code < 0)