@@ -112,6 +112,10 @@ (define_memory_constraint "R"
(and (match_operand:DI 0 "memory_operand")
(not (match_operand:DI 0 "illegal_addsub_di_memory_operand" ""))))
+(define_constraint "A"
+ "@internal An integer constant suitable for address load operations."
+ (match_test ("CONSTANT_P (op) && pic_symbolic_operand (op, mode)")))
+
(define_constraint "T"
"@internal satisfies CONSTANT_P and, if pic is enabled, is not a SYMBOL_REF, LABEL_REF, or CONST."
(and (match_test ("CONSTANT_P (op)"))
@@ -23,33 +23,17 @@
(define_predicate "symbolic_operand"
(match_code "const,symbol_ref,label_ref"))
-(define_predicate "local_symbolic_operand"
- (match_code "const,symbol_ref,label_ref")
-{
- if (GET_CODE (op) == LABEL_REF)
- return 1;
- if (GET_CODE (op) == SYMBOL_REF)
- return !flag_pic || SYMBOL_REF_LOCAL_P (op);
- if (GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF)
- return 1;
- return !flag_pic || SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0));
-})
-
-(define_predicate "external_symbolic_operand"
- (and (match_code "symbol_ref")
- (not (match_operand 0 "local_symbolic_operand" ""))))
-
-(define_predicate "external_const_operand"
- (and (match_code "const")
- (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0))")))
+(define_predicate "pic_symbolic_operand"
+ (and (match_code "const,symbol_ref,label_ref")
+ (match_test "!flag_pic
+ || vax_acceptable_pic_operand_p (op, false, true)")))
(define_predicate "nonsymbolic_operand"
(and (ior (match_test "!flag_pic")
(not (match_operand 0 "symbolic_operand")))
(match_operand 0 "general_operand" "")))
-(define_predicate "external_memory_operand"
+(define_predicate "non_pic_external_memory_operand"
(match_code "mem")
{
rtx addr = XEXP (op, 0);
@@ -61,8 +45,8 @@ (define_predicate "external_memory_operand"
addr = XEXP (addr, 0);
if (GET_CODE (addr) == PLUS)
addr = XEXP (addr, 1);
- return external_symbolic_operand (addr, SImode)
- || external_const_operand (addr, SImode);
+ return (symbolic_operand (addr, SImode)
+ && !vax_acceptable_pic_operand_p (addr, true, true));
})
(define_predicate "indirect_memory_operand"
@@ -87,7 +71,7 @@ (define_predicate "indexed_memory_operand"
(define_predicate "illegal_blk_memory_operand"
(and (match_code "mem")
(ior (and (match_test "flag_pic")
- (match_operand 0 "external_memory_operand" ""))
+ (match_operand 0 "non_pic_external_memory_operand" ""))
(ior (match_operand 0 "indexed_memory_operand" "")
(ior (match_operand 0 "indirect_memory_operand" "")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))))))
@@ -95,7 +79,7 @@ (define_predicate "illegal_blk_memory_operand"
(define_predicate "illegal_addsub_di_memory_operand"
(and (match_code "mem")
(ior (and (match_test "flag_pic")
- (match_operand 0 "external_memory_operand" ""))
+ (match_operand 0 "non_pic_external_memory_operand" ""))
(ior (match_operand 0 "indexed_memory_operand" "")
(ior (match_operand 0 "indirect_memory_operand" "")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))))))
@@ -21,6 +21,7 @@ extern bool legitimate_constant_address_p (rtx);
extern void vax_expand_prologue (void);
#ifdef RTX_CODE
+extern bool vax_acceptable_pic_operand_p (rtx, bool, bool);
extern const char *cond_name (rtx);
extern bool adjacent_operands_p (rtx, rtx, machine_mode);
extern const char *rev_cond_name (rtx);
@@ -1033,6 +1033,39 @@ vax_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
}
+/* With ELF we do not support GOT entries for external `symbol+offset'
+ references, so do not accept external symbol references if an offset
+ is to be added. Do not accept external symbol references at all if
+ LOCAL_P is set. This is for cases where making a reference indirect
+ would make it invalid. Do not accept any kind of symbols if SYMBOL_P
+ is clear. This is for situations where the a reference is used as an
+ immediate value for operations other than address loads (MOVA/PUSHA),
+ as those operations do not support PC-relative immediates. */
+
+bool
+vax_acceptable_pic_operand_p (rtx x ATTRIBUTE_UNUSED,
+ bool local_p ATTRIBUTE_UNUSED,
+ bool symbol_p ATTRIBUTE_UNUSED)
+{
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+ {
+ x = XEXP (XEXP (x, 0), 0);
+ local_p = true;
+ }
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ return symbol_p && !(local_p && !SYMBOL_REF_LOCAL_P (x));
+ case LABEL_REF:
+ return symbol_p && !(local_p && LABEL_REF_NONLOCAL_P (x));
+ default:
+ break;
+ }
+#endif
+ return true;
+}
+
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance.
.mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
@@ -1370,8 +1403,10 @@ vax_output_int_add (rtx_insn *insn, rtx *operands, machine_mode mode)
{
gcc_assert (rtx_equal_p (operands[0], operands[1]));
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
- gcc_assert (!flag_pic || !external_memory_operand (low[2], SImode));
- gcc_assert (!flag_pic || !external_memory_operand (low[0], SImode));
+ gcc_assert (!flag_pic
+ || !non_pic_external_memory_operand (low[2], SImode));
+ gcc_assert (!flag_pic
+ || !non_pic_external_memory_operand (low[0], SImode));
#endif
/* No reason to add a 0 to the low part and thus no carry, so just
@@ -442,6 +442,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
of a shift count. */
/* #define SHIFT_COUNT_TRUNCATED */
+/* We need to reject symbol references in PIC code except for address
+ loads, handled elsewhere. */
+#define LEGITIMATE_PIC_OPERAND_P(x) \
+ vax_acceptable_pic_operand_p ((x), false, false)
+
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
@@ -338,34 +338,6 @@ (define_insn "add<mode>3"
add<VAXfp:fsfx>2 %1,%0
add<VAXfp:fsfx>3 %1,%2,%0")
-(define_insn "pushlclsymreg"
- [(set (match_operand:SI 0 "push_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "local_symbolic_operand" "i")))]
- "flag_pic"
- "pushab %a2[%1]")
-
-(define_insn "pushextsymreg"
- [(set (match_operand:SI 0 "push_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "external_symbolic_operand" "i")))]
- "flag_pic"
- "pushab %a2[%1]")
-
-(define_insn "movlclsymreg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "local_symbolic_operand" "i")))]
- "flag_pic"
- "movab %a2[%1],%0")
-
-(define_insn "movextsymreg"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "external_symbolic_operand" "i")))]
- "flag_pic"
- "movab %a2[%1],%0")
-
(define_insn "add<mode>3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
@@ -1525,29 +1497,31 @@ (define_insn "casesi1"
""
"casel %0,$0,%1")
-(define_insn "pushextsym"
+(define_insn "*pushsym"
[(set (match_operand:SI 0 "push_operand" "=g")
- (match_operand:SI 1 "external_symbolic_operand" "i"))]
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))]
""
"pushab %a1")
-(define_insn "movextsym"
+(define_insn "*movsym"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (match_operand:SI 1 "external_symbolic_operand" "i"))]
+ (match_operand:SI 1 "pic_symbolic_operand" "A"))]
""
"movab %a1,%0")
-(define_insn "pushlclsym"
+(define_insn "*pushsymreg"
[(set (match_operand:SI 0 "push_operand" "=g")
- (match_operand:SI 1 "local_symbolic_operand" "i"))]
- ""
- "pushab %a1")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))]
+ "flag_pic"
+ "pushab %a2[%1]")
-(define_insn "movlclsym"
+(define_insn "*movsymreg"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
- (match_operand:SI 1 "local_symbolic_operand" "i"))]
- ""
- "movab %a1,%0")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "pic_symbolic_operand" "A")))]
+ "flag_pic"
+ "movab %a2[%1],%0")
;;- load or push effective address
;; These come after the move and add/sub patterns