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]

powerpc new PLT and GOT


This is where I'm at with gcc support for the new powerpc-linux PLT/GOT
layout (see http://sources.redhat.com/ml/binutils/2005-05/msg00391.html).
I'm not asking for commit approval yet;  That ought to wait until I've
thrown together glibc support as well so this can all be tested properly,
but what I have here seems to do the right thing.  So I'm looking for
comments like "That's the Wrong Way.  You ought to ..."

Some things I know need attention:
a) Should the new -fpic PLT/GOT code support be enabled by default?  The
   linker  will continue to generate the old GOT/PLT layout until a new
   glibc is available, a consequence of a "bl got-4" used in the current
   crti.o.  This is fortunate, and means we don't need to do a configure
   test on glibc to figure whether the new PLT/GOT code is safe to use.
   However, the new GOT pointer load sequence is larger, (but might be
   quicker) and new PLT calls always need the GOT pointer, so code
   increases a little in size.
b) -fPIC should use the new GOT pointer load sequence too, as it is
   faster and smaller than the current -fPIC sequence.
c) The rtl generated by load_toc_v4_PIC_3c matches elf_low.  We get the
   right assembly though.

	* configure.ac (HAVE_AS_REL16): Test for R_PPC_REL16 relocs.
	* config/rs6000/sysv4.opt (mdata-plt, bss-plt): Add options.
	* config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Error if
	-mdata-plt given without assembler support.
	* config/rs6000/rs6000.h (TARGET_DATA_PLT): Undef if not HAVE_AS_REL16.
	* config/rs6000/rs6000.c (rs6000_emit_load_toc_table): Handle
	TARGET_DATA_PLT got register load sequence.
	* config/rs6000/rs6000.md (load_toc_v4_PIC_1) Enable for
	TARGET_DATA_PLT.
	(load_toc_v4_PIC_3b, load_toc_v4_PIC_3c): New insns.
	(call, call_value): Mark pic_offset_table_rtx used for TARGET_DATA_PLT.
	* config.in: Regenerate.
	* configure: Regenerate.

diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/configure.ac gcc-current/gcc/configure.ac
--- gcc-virgin/gcc/configure.ac	2005-05-09 20:03:03.000000000 +0930
+++ gcc-current/gcc/configure.ac	2005-05-12 18:31:15.000000000 +0930
@@ -2828,6 +2828,24 @@ foo:	nop
       [AC_DEFINE(HAVE_AS_POPCNTB, 1,
 	  [Define if your assembler supports popcntb field.])])
 
+    case $target in
+      *-*-aix*) conftest_s='	.csect .text[[PR]]
+LCF..0:
+	addis 11,30,_GLOBAL_OFFSET_TABLE_-LCF..0@ha';;
+      *-*-darwin*)
+	conftest_s='	.text
+LCF0:
+	addis r11,r30,_GLOBAL_OFFSET_TABLE_-LCF0@ha';;
+      *) conftest_s='	.text
+.LCF0:
+	addis 11,30,_GLOBAL_OFFSET_TABLE_-.LCF0@ha';;
+    esac
+
+    gcc_GAS_CHECK_FEATURE([rel16 relocs],
+      gcc_cv_as_powerpc_rel16, [2,17,0],,
+      [$conftest_s],,
+      [AC_DEFINE(HAVE_AS_REL16, 1,
+	  [Define if your assembler supports R_PPC_REL16 relocs.])])
     ;;
 
   mips*-*-*)
diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/sysv4.opt gcc-current/gcc/config/rs6000/sysv4.opt
--- gcc-virgin/gcc/config/rs6000/sysv4.opt	2005-05-07 17:51:46.000000000 +0930
+++ gcc-current/gcc/config/rs6000/sysv4.opt	2005-05-12 20:27:22.000000000 +0930
@@ -140,3 +140,11 @@ Generate 32-bit code
 mnewlib
 Target RejectNegative
 no description yet
+
+mdata-plt
+Target Report RejectNegative Mask(DATA_PLT)
+Generate code to use a non-exec PLT and GOT
+
+mbss-plt
+Target Report RejectNegative InverseMask(DATA_PLT)
+Generate code for old exec BSS PLT
diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/sysv4.h gcc-current/gcc/config/rs6000/sysv4.h
--- gcc-virgin/gcc/config/rs6000/sysv4.h	2005-05-06 23:34:43.000000000 +0930
+++ gcc-current/gcc/config/rs6000/sysv4.h	2005-05-12 19:41:09.000000000 +0930
@@ -205,6 +205,11 @@ do {									\
       error ("-mcall-aixdesc must be big endian");			\
     }									\
 									\
+  if (TARGET_DATA_PLT != ((target_flags & MASK_DATA_PLT) != 0))		\
+    {									\
+      error ("-mdata-plt not supported by your assembler");		\
+    }									\
+									\
   /* Treat -fPIC the same as -mrelocatable.  */				\
   if (flag_pic > 1 && DEFAULT_ABI != ABI_AIX)				\
     target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; \
diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/rs6000.c gcc-current/gcc/config/rs6000/rs6000.c
--- gcc-virgin/gcc/config/rs6000/rs6000.c	2005-05-09 20:03:12.000000000 +0930
+++ gcc-current/gcc/config/rs6000/rs6000.c	2005-05-12 18:45:53.000000000 +0930
@@ -12547,15 +12596,46 @@ rs6000_emit_load_toc_table (int fromprol
 
   if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
     {
-      rtx temp = (fromprolog
-		  ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
-		  : gen_reg_rtx (Pmode));
-      insn = emit_insn (gen_load_toc_v4_pic_si (temp));
-      if (fromprolog)
-	rs6000_maybe_dead (insn);
-      insn = emit_move_insn (dest, temp);
-      if (fromprolog)
-	rs6000_maybe_dead (insn);
+      rtx tempLR = (fromprolog
+		    ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
+		    : gen_reg_rtx (Pmode));
+
+      if (TARGET_DATA_PLT)
+	{
+	  char buf[30];
+	  rtx lab, tmp1, tmp2, got;
+
+	  ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+	  lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+	  got = rs6000_got_sym ();
+	  tmp1 = tmp2 = dest;
+	  if (!fromprolog)
+	    {
+	      tmp1 = gen_reg_rtx (Pmode);
+	      tmp2 = gen_reg_rtx (Pmode);
+	    }
+	  insn = emit_insn (gen_load_toc_v4_PIC_1 (tempLR, lab));
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	  insn = emit_move_insn (tmp1, tempLR);
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	  insn = emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	  insn = emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	}
+      else
+	{
+	  insn = emit_insn (gen_load_toc_v4_pic_si (tempLR));
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	  insn = emit_move_insn (dest, tempLR);
+	  if (fromprolog)
+	    rs6000_maybe_dead (insn);
+	}
     }
   else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
     {
diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/rs6000.h gcc-current/gcc/config/rs6000/rs6000.h
--- gcc-virgin/gcc/config/rs6000/rs6000.h	2005-05-09 20:03:12.000000000 +0930
+++ gcc-current/gcc/config/rs6000/rs6000.h	2005-05-12 18:45:55.000000000 +0930
@@ -144,6 +144,11 @@
 #define TARGET_POPCNTB 0
 #endif
 
+#ifndef HAVE_AS_REL16
+#undef  TARGET_DATA_PLT
+#define TARGET_DATA_PLT 0
+#endif
+
 #define TARGET_32BIT		(! TARGET_64BIT)
 
 /* Emit a dtp-relative reference to a TLS variable.  */
diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/rs6000.md gcc-current/gcc/config/rs6000/rs6000.md
--- gcc-virgin/gcc/config/rs6000/rs6000.md	2005-05-12 12:45:31.000000000 +0930
+++ gcc-current/gcc/config/rs6000/rs6000.md	2005-05-12 18:39:45.000000000 +0930
@@ -9812,7 +9810,8 @@
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(match_operand:SI 1 "immediate_operand" "s"))
    (use (unspec [(match_dup 1)] UNSPEC_TOC))]
-  "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+  "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+   && (flag_pic == 2 || (flag_pic && TARGET_DATA_PLT))"
   "bcl 20,31,%1\\n%1:"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
@@ -9835,6 +9834,22 @@
   "{l|lwz} %0,%2-%3(%1)"
   [(set_attr "type" "load")])
 
+(define_insn "load_toc_v4_PIC_3b"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+	(plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+		 (high:SI
+		   (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+			     (match_operand:SI 3 "symbol_ref_operand" "s")))))]
+  "DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_DATA_PLT"
+  "{cau|addis} %0,%1,%2-%3@ha")
+
+(define_insn "load_toc_v4_PIC_3c"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+		   (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+			     (match_operand:SI 3 "symbol_ref_operand" "s"))))]
+  "DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_DATA_PLT"
+  "{cal|addi} %0,%1,%2-%3@l")
 
 ;; If the TOC is shared over a translation unit, as happens with all
 ;; the kinds of PIC that we support, we need to restore the TOC
@@ -9985,6 +10000,25 @@
 
   operands[0] = XEXP (operands[0], 0);
 
+  if (DEFAULT_ABI == ABI_V4 && TARGET_DATA_PLT
+      && flag_pic
+      && GET_CODE (operands[0]) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (operands[0]))
+    {
+      rtx call;
+      rtvec tmp;
+
+      tmp = gen_rtvec (3,
+		       gen_rtx_CALL (VOIDmode,
+				     gen_rtx_MEM (SImode, operands[0]),
+				     operands[1]),
+		       gen_rtx_USE (VOIDmode, operands[2]),
+		       gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+      call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+      use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+      DONE;
+    }
+
   if (GET_CODE (operands[0]) != SYMBOL_REF
       || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
       || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
@@ -10036,6 +10070,28 @@
 
   operands[1] = XEXP (operands[1], 0);
 
+  if (DEFAULT_ABI == ABI_V4 && TARGET_DATA_PLT
+      && flag_pic
+      && GET_CODE (operands[1]) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (operands[1]))
+    {
+      rtx call;
+      rtvec tmp;
+
+      tmp = gen_rtvec (3,
+		       gen_rtx_SET (VOIDmode,
+				    operands[0],
+				    gen_rtx_CALL (VOIDmode,
+						  gen_rtx_MEM (SImode,
+							       operands[1]),
+						  operands[2])),
+		       gen_rtx_USE (VOIDmode, operands[3]),
+		       gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+      call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+      use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+      DONE;
+    }
+
   if (GET_CODE (operands[1]) != SYMBOL_REF
       || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
       || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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