304 lines
9.1 KiB
Diff
304 lines
9.1 KiB
Diff
Index: gcc/config/arm/arm-protos.h
|
|
===================================================================
|
|
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm-protos.h,v
|
|
retrieving revision 1.60.4.20
|
|
diff -u -r1.60.4.20 arm-protos.h
|
|
--- gcc/config/arm/arm-protos.h 29 Mar 2005 03:00:11 -0000 1.60.4.20
|
|
+++ gcc/config/arm/arm-protos.h 23 Apr 2005 04:41:06 -0000
|
|
@@ -64,6 +64,7 @@
|
|
extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
|
|
extern int tls_symbolic_operand (rtx, enum machine_mode);
|
|
extern bool arm_tls_operand_p (rtx x);
|
|
+extern bool arm_pc_pic_operand_p (rtx x);
|
|
|
|
/* Predicates. */
|
|
extern int s_register_operand (rtx, enum machine_mode);
|
|
Index: gcc/config/arm/arm.c
|
|
===================================================================
|
|
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.c,v
|
|
retrieving revision 1.303.2.79
|
|
diff -u -r1.303.2.79 arm.c
|
|
--- gcc/config/arm/arm.c 12 Apr 2005 06:17:07 -0000 1.303.2.79
|
|
+++ gcc/config/arm/arm.c 23 Apr 2005 04:41:09 -0000
|
|
@@ -1003,7 +1003,7 @@
|
|
|
|
/* If stack checking is disabled, we can use r10 as the PIC register,
|
|
which keeps r9 available. */
|
|
- if (flag_pic)
|
|
+ if (0 && flag_pic)
|
|
arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
|
|
|
|
if (TARGET_APCS_FLOAT)
|
|
@@ -3120,6 +3120,10 @@
|
|
rtx
|
|
legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
|
{
|
|
+ if (GET_CODE (orig) == UNSPEC
|
|
+ && XINT (orig, 1) == UNSPEC_GOTSLOTPC)
|
|
+ abort ();
|
|
+
|
|
if (GET_CODE (orig) == SYMBOL_REF
|
|
|| GET_CODE (orig) == LABEL_REF)
|
|
{
|
|
@@ -3149,27 +3153,80 @@
|
|
else
|
|
address = reg;
|
|
|
|
- if (TARGET_ARM)
|
|
- emit_insn (gen_pic_load_addr_arm (address, orig));
|
|
- else
|
|
- emit_insn (gen_pic_load_addr_thumb (address, orig));
|
|
+ if (arm_pic_register != INVALID_REGNUM)
|
|
+ {
|
|
+ /* Using GP-based PIC addressing. */
|
|
+ if (TARGET_ARM)
|
|
+ emit_insn (gen_pic_load_addr_arm (address, orig));
|
|
+ else
|
|
+ emit_insn (gen_pic_load_addr_thumb (address, orig));
|
|
+
|
|
+ if ((GET_CODE (orig) == LABEL_REF
|
|
+ || (GET_CODE (orig) == SYMBOL_REF &&
|
|
+ SYMBOL_REF_LOCAL_P (orig)))
|
|
+ && NEED_GOT_RELOC)
|
|
+ pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
|
|
+ else
|
|
+ {
|
|
+ pic_ref = gen_rtx_MEM (Pmode,
|
|
+ gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
|
|
+ address));
|
|
+ RTX_UNCHANGING_P (pic_ref) = 1;
|
|
+ }
|
|
|
|
- if ((GET_CODE (orig) == LABEL_REF
|
|
- || (GET_CODE (orig) == SYMBOL_REF &&
|
|
- SYMBOL_REF_LOCAL_P (orig)))
|
|
- && NEED_GOT_RELOC)
|
|
- pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
|
|
+ current_function_uses_pic_offset_table = 1;
|
|
+ }
|
|
else
|
|
{
|
|
- pic_ref = gen_rtx_MEM (Pmode,
|
|
- gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
|
|
- address));
|
|
- RTX_UNCHANGING_P (pic_ref) = 1;
|
|
+ /* Using PC-based PIC addressing. */
|
|
+ rtx label, tmp;
|
|
+ int offset;
|
|
+
|
|
+ label = gen_label_rtx ();
|
|
+ offset = TARGET_ARM ? 8 : 4;
|
|
+
|
|
+ if (GET_CODE (orig) == LABEL_REF
|
|
+ || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig)))
|
|
+ {
|
|
+ /* This symbol is defined locally. We don't need a GOT entry. */
|
|
+ tmp = gen_rtx_MINUS (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), UNSPEC_PIC_SYM), gen_rtx_PLUS (Pmode,
|
|
+ gen_rtx_LABEL_REF (Pmode, label),
|
|
+ GEN_INT (offset)));
|
|
+
|
|
+ load_tls_operand (tmp, address);
|
|
+
|
|
+ if (TARGET_ARM)
|
|
+ emit_insn (gen_pic_add_dot_plus_eight (address, label));
|
|
+ else
|
|
+ emit_insn (gen_pic_add_dot_plus_four (address, label));
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ rtx x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), UNSPEC_GOTSLOTPC);
|
|
+ rtx dummy_label;
|
|
+
|
|
+ dummy_label = gen_label_rtx ();
|
|
+ LABEL_PRESERVE_P (dummy_label) = 1;
|
|
+ LABEL_NUSES (dummy_label) = 1;
|
|
+
|
|
+ tmp = gen_rtx_MINUS (Pmode, x, gen_rtx_PLUS (Pmode,
|
|
+ gen_rtx_LABEL_REF (Pmode, label),
|
|
+ GEN_INT (offset)));
|
|
+
|
|
+ load_tls_operand (tmp, address);
|
|
+
|
|
+ if (TARGET_ARM)
|
|
+ emit_insn (gen_tls_load_dot_plus_eight (address, address, label, dummy_label));
|
|
+ else
|
|
+ emit_insn (gen_tls_load_dot_plus_four (address, address, label, dummy_label));
|
|
+ }
|
|
+
|
|
+ pic_ref = address;
|
|
}
|
|
|
|
insn = emit_move_insn (reg, pic_ref);
|
|
#endif
|
|
- current_function_uses_pic_offset_table = 1;
|
|
+
|
|
/* Put a REG_EQUAL note on this insn, so that it can be optimized
|
|
by loop. */
|
|
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
|
|
@@ -3179,11 +3236,17 @@
|
|
else if (GET_CODE (orig) == CONST)
|
|
{
|
|
rtx base, offset;
|
|
+ bool minus = FALSE;
|
|
|
|
if (GET_CODE (XEXP (orig, 0)) == PLUS
|
|
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
|
|
return orig;
|
|
|
|
+ if (GET_CODE (XEXP (orig, 0)) == MINUS
|
|
+ && GET_CODE (XEXP (XEXP (orig, 0), 0)) == UNSPEC
|
|
+ && XINT (XEXP (XEXP (orig, 0), 0), 1) == UNSPEC_GOTSLOTPC)
|
|
+ return orig;
|
|
+
|
|
if (GET_CODE (XEXP (orig, 0)) == UNSPEC)
|
|
return orig;
|
|
|
|
@@ -3201,6 +3264,13 @@
|
|
offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
|
|
base == reg ? 0 : reg);
|
|
}
|
|
+ else if (GET_CODE (XEXP (orig, 0)) == MINUS)
|
|
+ {
|
|
+ minus = TRUE;
|
|
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
|
|
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
|
|
+ base == reg ? 0 : reg);
|
|
+ }
|
|
else
|
|
abort ();
|
|
|
|
@@ -3228,7 +3298,7 @@
|
|
return reg;
|
|
}
|
|
|
|
- return gen_rtx_PLUS (Pmode, base, offset);
|
|
+ return minus ? gen_rtx_MINUS (Pmode, base, offset) : gen_rtx_PLUS (Pmode, base, offset);
|
|
}
|
|
|
|
return orig;
|
|
@@ -3267,7 +3337,7 @@
|
|
rtx l1, pic_tmp, pic_tmp2, pic_rtx;
|
|
rtx global_offset_table;
|
|
|
|
- if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
|
|
+ if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE || arm_pic_register == INVALID_REGNUM)
|
|
return;
|
|
|
|
if (!flag_pic)
|
|
@@ -3341,8 +3411,11 @@
|
|
static int
|
|
pcrel_constant_p (rtx x)
|
|
{
|
|
+ if (GET_CODE (x) == CONST)
|
|
+ return pcrel_constant_p (XEXP (x, 0));
|
|
+
|
|
if (GET_CODE (x) == MINUS)
|
|
- return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1));
|
|
+ return (((GET_CODE (XEXP (x, 0)) == UNSPEC && XINT (XEXP (x, 0), 1) == UNSPEC_PIC_SYM)) || symbol_mentioned_p (XEXP (x, 0))) && label_mentioned_p (XEXP (x, 1));
|
|
|
|
if (GET_CODE (x) == UNSPEC
|
|
&& XINT (x, 1) == UNSPEC_TLS
|
|
@@ -3946,12 +4019,32 @@
|
|
return SYMBOL_REF_TLS_MODEL (op);
|
|
}
|
|
|
|
+bool
|
|
+arm_pc_pic_operand_p (rtx op)
|
|
+{
|
|
+ if (GET_CODE (op) == CONST
|
|
+ && GET_CODE (XEXP (op, 0)) == MINUS
|
|
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
|
|
+ && XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTSLOTPC)
|
|
+ return 1;
|
|
+
|
|
+ if (GET_CODE (op) == CONST
|
|
+ && GET_CODE (XEXP (op, 0)) == MINUS
|
|
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
|
|
+ && XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_PIC_SYM)
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Valid input to a move instruction. */
|
|
int
|
|
move_input_operand (rtx op, enum machine_mode mode)
|
|
{
|
|
if (tls_symbolic_operand (op, mode))
|
|
return 0;
|
|
+ if (pcrel_constant_p (op))
|
|
+ return 1;
|
|
return general_operand (op, mode);
|
|
}
|
|
|
|
@@ -15634,11 +15727,34 @@
|
|
return TRUE;
|
|
}
|
|
|
|
+static bool
|
|
+arm_emit_got_decoration (FILE *fp, rtx x)
|
|
+{
|
|
+ rtx val;
|
|
+
|
|
+ val = XVECEXP (x, 0, 0);
|
|
+
|
|
+ fputs ("_gotslotpc_(", fp);
|
|
+
|
|
+ output_addr_const (fp, val);
|
|
+
|
|
+ fputc (')', fp);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
bool
|
|
arm_output_addr_const_extra (FILE *fp, rtx x)
|
|
{
|
|
if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
|
|
return arm_emit_tls_decoration (fp, x);
|
|
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_GOTSLOTPC)
|
|
+ return arm_emit_got_decoration (fp, x);
|
|
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PIC_SYM)
|
|
+ {
|
|
+ output_addr_const (fp, XVECEXP (x, 0, 0));
|
|
+ return TRUE;
|
|
+ }
|
|
else if (GET_CODE (x) == CONST_VECTOR)
|
|
return arm_emit_vector_const (fp, x);
|
|
|
|
Index: gcc/config/arm/arm.md
|
|
===================================================================
|
|
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.md,v
|
|
retrieving revision 1.145.2.31
|
|
diff -u -r1.145.2.31 arm.md
|
|
--- gcc/config/arm/arm.md 28 Mar 2005 19:04:37 -0000 1.145.2.31
|
|
+++ gcc/config/arm/arm.md 23 Apr 2005 04:41:11 -0000
|
|
@@ -88,6 +88,7 @@
|
|
(UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
|
|
(UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
|
|
(UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
|
|
+ (UNSPEC_GOTSLOTPC 21)
|
|
]
|
|
)
|
|
|
|
@@ -4179,7 +4180,8 @@
|
|
&& (CONSTANT_P (operands[1])
|
|
|| symbol_mentioned_p (operands[1])
|
|
|| label_mentioned_p (operands[1]))
|
|
- && ! tls_mentioned_p (operands[1]))
|
|
+ && ! tls_mentioned_p (operands[1])
|
|
+ && ! arm_pc_pic_operand_p (operands[1]))
|
|
operands[1] = legitimize_pic_address (operands[1], SImode,
|
|
(no_new_pseudos ? operands[0] : 0));
|
|
}
|
|
@@ -4412,7 +4414,8 @@
|
|
(mem:SI (unspec:SI [(plus:SI (match_dup 0)
|
|
(const (plus:SI (pc) (const_int 8))))]
|
|
UNSPEC_PIC_BASE)))
|
|
- (use (label_ref (match_operand 1 "" "")))])]
|
|
+ (use (label_ref (match_operand 1 "" "")))
|
|
+ (use (label_ref (match_operand 1 "" "")))])]
|
|
""
|
|
)
|
|
|