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
{
return address_is_prefixed (XEXP (op, 0), mode, NON_PREFIXED_DEFAULT);
})
+
+;; 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;
+})
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
+ /* If we are building PIC code, then any symbol must be wrapped in an
+ UNSPEC_MACHOPIC_OFFSET so that it will get the picbase subtracted. */
+ bool machopic_offs_p = false;
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_MACHOPIC_OFFSET)
- x = XVECEXP (x, 0, 0);
+ {
+ x = XVECEXP (x, 0, 0);
+ machopic_offs_p = true;
+ }
rtx sym = NULL_RTX;
unsigned HOST_WIDE_INT offset = 0;
if (sym)
{
tree decl = SYMBOL_REF_DECL (sym);
+ /* As noted above, PIC code cannot use a bare SYMBOL_REF. */
+ if (TARGET_MACHO && flag_pic && !machopic_offs_p)
+ return false;
#if TARGET_MACHO
if (MACHO_SYMBOL_INDIRECTION_P (sym))
/* The decl in an indirection symbol is the original one, which might
return false;
x = XEXP (x, 1);
- if (TARGET_ELF || TARGET_MACHO)
+ if (TARGET_ELF)
{
bool large_toc_ok;
return CONSTANT_P (x) || large_toc_ok;
}
+ else if (TARGET_MACHO)
+ {
+ if (GET_MODE_NUNITS (mode) != 1)
+ return false;
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+ && !(/* see above */
+ TARGET_HARD_FLOAT && (mode == DFmode || mode == DDmode)))
+ return false;
+#if TARGET_MACHO
+ if (MACHO_DYNAMIC_NO_PIC_P || !flag_pic)
+ return CONSTANT_P (x);
+#endif
+ /* Macho-O PIC code from here. */
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ /* SYMBOL_REFs need to be wrapped in an UNSPEC_MACHOPIC_OFFSET. */
+ if (SYMBOL_REF_P (x))
+ return false;
+ /* So this is OK if the wrapped object is const. */
+ if (GET_CODE (x) == UNSPEC
+ && XINT (x, 1) == UNSPEC_MACHOPIC_OFFSET)
+ return CONSTANT_P (XVECEXP (x, 0, 0));
+ return CONSTANT_P (x);
+ }
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)