This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
powerpc new PLT and GOT
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 13 May 2005 01:35:24 +0930
- Subject: 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