Commit 170bdaba by Richard Sandiford Committed by Richard Sandiford

i386.c (output_set_got): Add a GOT initialization sequence for VxWorks PIC.

gcc/
	* config/i386/i386.c (output_set_got): Add a GOT initialization
	sequence for VxWorks PIC.
	(legitimate_pic_address_disp_p): Allow UNSPEC_GOT wrappers
	around labels as well as symbols.  Use gotoff_operand instead
	of local_symbolic_operand.
	(legitimize_pic_address): Use gotoff_operand instead of
	local_symbolic_operand.  Use @GOT accesses for labels as
	well as symbols.
	(ix86_output_addr_diff_elt): Use PC-relative rather than
	GP-relative offsets for VxWorks PIC.
	(ix86_expand_move): Pass NULL_RTX to legitimize_pic_address unless
	no_new_pseudos.  Check whether the returned register is op0.
	* config/i386/i386.md (tablejump): Use PC-relative rather than
	GP-relative offsets for VxWorks PIC.
	* config/i386/predicates.md (gotoff_operand): New predicate.

From-SVN: r122654
parent 26b5109f
2007-03-07 Richard Sandiford <richard@codesourcery.com>
* config/i386/i386.c (output_set_got): Add a GOT initialization
sequence for VxWorks PIC.
(legitimate_pic_address_disp_p): Allow UNSPEC_GOT wrappers
around labels as well as symbols. Use gotoff_operand instead
of local_symbolic_operand.
(legitimize_pic_address): Use gotoff_operand instead of
local_symbolic_operand. Use @GOT accesses for labels as
well as symbols.
(ix86_output_addr_diff_elt): Use PC-relative rather than
GP-relative offsets for VxWorks PIC.
(ix86_expand_move): Pass NULL_RTX to legitimize_pic_address unless
no_new_pseudos. Check whether the returned register is op0.
* config/i386/i386.md (tablejump): Use PC-relative rather than
GP-relative offsets for VxWorks PIC.
* config/i386/predicates.md (gotoff_operand): New predicate.
2007-03-06 Richard Sandiford <richard@codesourcery.com> 2007-03-06 Richard Sandiford <richard@codesourcery.com>
* config/vxworks.h (VXWORKS_GOTT_BASE, VXWORKS_GOTT_INDEX): Undefine * config/vxworks.h (VXWORKS_GOTT_BASE, VXWORKS_GOTT_INDEX): Undefine
......
...@@ -5371,6 +5371,23 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED) ...@@ -5371,6 +5371,23 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
rtx xops[3]; rtx xops[3];
xops[0] = dest; xops[0] = dest;
if (TARGET_VXWORKS_RTP && flag_pic)
{
/* Load (*VXWORKS_GOTT_BASE) into the PIC register. */
xops[2] = gen_rtx_MEM (Pmode,
gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE));
output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
/* Load (*VXWORKS_GOTT_BASE)[VXWORKS_GOTT_INDEX] into the PIC register.
Use %P and a local symbol in order to print VXWORKS_GOTT_INDEX as
an unadorned address. */
xops[2] = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
SYMBOL_REF_FLAGS (xops[2]) |= SYMBOL_FLAG_LOCAL;
output_asm_insn ("mov{l}\t{%P2(%0), %0|%0, DWORD PTR %P2[%0]}", xops);
return "";
}
xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME); xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic) if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
...@@ -6762,7 +6779,11 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -6762,7 +6779,11 @@ legitimate_pic_address_disp_p (rtx disp)
case UNSPEC_GOT: case UNSPEC_GOT:
if (saw_plus) if (saw_plus)
return false; return false;
return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF; /* We need to check for both symbols and labels because VxWorks loads
text labels with @GOT rather than @GOTOFF. See gotoff_operand for
details. */
return (GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
|| GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF);
case UNSPEC_GOTOFF: case UNSPEC_GOTOFF:
/* Refuse GOTOFF in 64bit mode since it is always 64bit when used. /* Refuse GOTOFF in 64bit mode since it is always 64bit when used.
While ABI specify also 32bit relocation but we don't produce it in While ABI specify also 32bit relocation but we don't produce it in
...@@ -6770,7 +6791,7 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -6770,7 +6791,7 @@ legitimate_pic_address_disp_p (rtx disp)
if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
|| GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF) || GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
&& !TARGET_64BIT) && !TARGET_64BIT)
return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode); return gotoff_operand (XVECEXP (disp, 0, 0), Pmode);
return false; return false;
case UNSPEC_GOTTPOFF: case UNSPEC_GOTTPOFF:
case UNSPEC_GOTNTPOFF: case UNSPEC_GOTNTPOFF:
...@@ -7091,7 +7112,7 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -7091,7 +7112,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = addr; new = addr;
else if (TARGET_64BIT else if (TARGET_64BIT
&& ix86_cmodel != CM_SMALL_PIC && ix86_cmodel != CM_SMALL_PIC
&& local_symbolic_operand (addr, Pmode)) && gotoff_operand (addr, Pmode))
{ {
rtx tmpreg; rtx tmpreg;
/* This symbol may be referenced via a displacement from the PIC /* This symbol may be referenced via a displacement from the PIC
...@@ -7123,7 +7144,7 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -7123,7 +7144,7 @@ legitimize_pic_address (rtx orig, rtx reg)
} }
else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg); else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
} }
else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode)) else if (!TARGET_64BIT && gotoff_operand (addr, Pmode))
{ {
/* This symbol may be referenced via a displacement from the PIC /* This symbol may be referenced via a displacement from the PIC
base address (@GOTOFF). */ base address (@GOTOFF). */
...@@ -7148,7 +7169,10 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -7148,7 +7169,10 @@ legitimize_pic_address (rtx orig, rtx reg)
new = reg; new = reg;
} }
} }
else if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0) else if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0)
/* We can't use @GOTOFF for text labels on VxWorks;
see gotoff_operand. */
|| (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF))
{ {
if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC) if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC)
{ {
...@@ -7218,7 +7242,7 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -7218,7 +7242,7 @@ legitimize_pic_address (rtx orig, rtx reg)
/* Check first to see if this is a constant offset from a @GOTOFF /* Check first to see if this is a constant offset from a @GOTOFF
symbol reference. */ symbol reference. */
if (local_symbolic_operand (op0, Pmode) if (gotoff_operand (op0, Pmode)
&& CONST_INT_P (op1)) && CONST_INT_P (op1))
{ {
if (!TARGET_64BIT) if (!TARGET_64BIT)
...@@ -9379,7 +9403,8 @@ ix86_output_addr_diff_elt (FILE *file, int value, int rel) ...@@ -9379,7 +9403,8 @@ ix86_output_addr_diff_elt (FILE *file, int value, int rel)
#else #else
gcc_assert (!TARGET_64BIT); gcc_assert (!TARGET_64BIT);
#endif #endif
if (TARGET_64BIT) /* We can't use @GOTOFF for text labels on VxWorks; see gotoff_operand. */
if (TARGET_64BIT || TARGET_VXWORKS_RTP)
fprintf (file, "%s%s%d-%s%d\n", fprintf (file, "%s%s%d-%s%d\n",
directive, LPREFIX, value, LPREFIX, rel); directive, LPREFIX, value, LPREFIX, rel);
else if (HAVE_AS_GOTOFF_IN_DATA) else if (HAVE_AS_GOTOFF_IN_DATA)
...@@ -9502,7 +9527,12 @@ ix86_expand_move (enum machine_mode mode, rtx operands[]) ...@@ -9502,7 +9527,12 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
if (MEM_P (op0)) if (MEM_P (op0))
op1 = force_reg (Pmode, op1); op1 = force_reg (Pmode, op1);
else if (!TARGET_64BIT || !x86_64_movabs_operand (op1, Pmode)) else if (!TARGET_64BIT || !x86_64_movabs_operand (op1, Pmode))
op1 = legitimize_pic_address (op1, op0); {
rtx reg = no_new_pseudos ? op0 : NULL_RTX;
op1 = legitimize_pic_address (op1, reg);
if (op0 == op1)
return;
}
} }
} }
else else
......
...@@ -14353,7 +14353,9 @@ ...@@ -14353,7 +14353,9 @@
rtx op0, op1; rtx op0, op1;
enum rtx_code code; enum rtx_code code;
if (TARGET_64BIT) /* We can't use @GOTOFF for text labels on VxWorks;
see gotoff_operand. */
if (TARGET_64BIT || TARGET_VXWORKS_RTP)
{ {
code = PLUS; code = PLUS;
op0 = operands[0]; op0 = operands[0];
......
...@@ -456,6 +456,18 @@ ...@@ -456,6 +456,18 @@
return 0; return 0;
}) })
;; Test for a legitimate @GOTOFF operand.
;;
;; VxWorks does not impose a fixed gap between segments; the run-time
;; gap can be different from the object-file gap. We therefore can't
;; use @GOTOFF unless we are absolutely sure that the symbol is in the
;; same segment as the GOT. Unfortunately, the flexibility of linker
;; scripts means that we can't be sure of that in general, so assume
;; that @GOTOFF is never valid on VxWorks.
(define_predicate "gotoff_operand"
(and (match_test "!TARGET_VXWORKS_RTP")
(match_operand 0 "local_symbolic_operand")))
;; Test for various thread-local symbols. ;; Test for various thread-local symbols.
(define_predicate "tls_symbolic_operand" (define_predicate "tls_symbolic_operand"
(and (match_code "symbol_ref") (and (match_code "symbol_ref")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment