This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[2/2] Add VxWorks PIC support to i386


(Sorry, I hope you don't mind me keeping you on cc:, but it so happens
that i386 was the first port in line.)

This patch adds VxWorks PIC for x86 targets.  As a comment in the patch
says, the main difference is that:

;; 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.

The patch therefore adds a gotoff_operand predicate to go alongside
local_symbolic_operand, and updates various users accordingly.
Also:

  - It adds a VxWorks-specific set-up sequence to output_set_got.

  - It uses PC-relative rather than GP-relative switch tables for RTP PIC.

  - ix86_expand_move currently uses legitimize_address to legitimize
    symbolic addresses if flag_pic.  The problem is that this code can
    be called for constant pool addresses during reload, and unlike the
    @GOTOFF sequence, the @GOT sequence needs temporary registers.
    The patch therefore calls legitimize_pic_address instead of
    legitimize_address and passes op0 as the temporary register
    if !no_new_pseudos.  (Earlier code has already checked that op1
    is a non-TLS symbolic constant.)

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also tested
on i586-wrs-vxworks.  OK to install?

Richard


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): Use legitimize_pic_address instead
	of legitimize_address.  Use op0 as a temporary register if
	no_new_pseudos.
	* config/i386/i386.md (tablejump): Use PC-relative rather than
	GP-relative offsets for VxWorks PIC.
	* config/i386/predicates.md (gotoff_operand): New predicate.

Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 122473)
+++ gcc/config/i386/i386.c	(working copy)
@@ -5326,6 +5326,23 @@ output_set_got (rtx dest, rtx label ATTR
   rtx xops[3];
 
   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);
 
   if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
@@ -6693,7 +6710,11 @@ legitimate_pic_address_disp_p (rtx disp)
     case UNSPEC_GOT:
       if (saw_plus)
 	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:
       /* 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
@@ -6701,7 +6722,7 @@ legitimate_pic_address_disp_p (rtx disp)
       if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
 	   || GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
 	  && !TARGET_64BIT)
-        return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
+        return gotoff_operand (XVECEXP (disp, 0, 0), Pmode);
       return false;
     case UNSPEC_GOTTPOFF:
     case UNSPEC_GOTNTPOFF:
@@ -7022,7 +7043,7 @@ legitimize_pic_address (rtx orig, rtx re
     new = addr;
   else if (TARGET_64BIT
 	   && ix86_cmodel != CM_SMALL_PIC
-	   && local_symbolic_operand (addr, Pmode))
+	   && gotoff_operand (addr, Pmode))
     {
       rtx tmpreg;
       /* This symbol may be referenced via a displacement from the PIC
@@ -7054,7 +7075,7 @@ legitimize_pic_address (rtx orig, rtx re
 	}
       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
 	 base address (@GOTOFF).  */
@@ -7079,7 +7100,10 @@ legitimize_pic_address (rtx orig, rtx re
 	  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)
 	{
@@ -7147,7 +7171,7 @@ legitimize_pic_address (rtx orig, rtx re
 
 	  /* Check first to see if this is a constant offset from a @GOTOFF
 	     symbol reference.  */
-	  if (local_symbolic_operand (op0, Pmode)
+	  if (gotoff_operand (op0, Pmode)
 	      && CONST_INT_P (op1))
 	    {
 	      if (!TARGET_64BIT)
@@ -9297,7 +9321,8 @@ ix86_output_addr_vec_elt (FILE *file, in
 void
 ix86_output_addr_diff_elt (FILE *file, int value, int rel)
 {
-  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",
 	     ASM_LONG, LPREFIX, value, LPREFIX, rel);
   else if (HAVE_AS_GOTOFF_IN_DATA)
@@ -9420,7 +9445,12 @@ ix86_expand_move (enum machine_mode mode
 	  if (MEM_P (op0))
 	    op1 = force_reg (Pmode, op1);
 	  else
-	    op1 = legitimize_address (op1, op1, Pmode);
+	    {
+	      rtx reg = no_new_pseudos ? op0 : NULL_RTX;
+	      op1 = legitimize_pic_address (op1, reg);
+	      if (op0 == op1)
+		return;
+	    }
 	}
     }
   else
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 122473)
+++ gcc/config/i386/i386.md	(working copy)
@@ -14350,7 +14350,9 @@ (define_expand "tablejump"
       rtx op0, op1;
       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;
 	  op0 = operands[0];
Index: gcc/config/i386/predicates.md
===================================================================
--- gcc/config/i386/predicates.md	(revision 122473)
+++ gcc/config/i386/predicates.md	(working copy)
@@ -456,6 +456,18 @@ (define_predicate "local_symbolic_operan
   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.
 (define_predicate "tls_symbolic_operand"
   (and (match_code "symbol_ref")


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]