* configure.ac (HAVE_AS_REL16): Test for R_PPC_REL16 relocs. * config.in: Regenerate. * configure: Regenerate. * 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. (call_nonlocal_sysv, call_value_nonlocal_sysv, sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Add 32768 offset when TARGET_DATA_PLT and -fPIC. * config/rs6000/t-rs6000 (DATA_PLT): New shell variable. * config/rs6000/t-linux64 (TARGET_LIBGCC2_CFLAGS): Add $DATA_PLT. (MULTILIB_EXTRA_OPTS): Likewise. * config/rs6000/t-netbsd (MULTILIB_EXTRA_OPTS): Likewise. * config/rs6000/t-ppcos (MULTILIB_EXTRA_OPTS): Likewise. * config/rs6000/t-ppccomm (CRTSTUFF_T_CFLAGS_S): Likewise. * config/rs6000/t-lynx (CRTSTUFF_T_CFLAGS_S): Likewise. diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/configure.ac gcc-current/gcc/configure.ac --- gcc-virgin/gcc/configure.ac 2005-05-19 19:10:56.000000000 +0930 +++ gcc-current/gcc/configure.ac 2005-05-19 19:13:04.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], -a32, + [$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-19 19:11:10.000000000 +0930 +++ gcc-current/gcc/config/rs6000/sysv4.opt 2005-05-19 19:13:21.000000000 +0930 @@ -139,3 +139,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-18 23:42:08.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.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.c gcc-current/gcc/config/rs6000/rs6000.c --- gcc-virgin/gcc/config/rs6000/rs6000.c 2005-05-19 19:11:10.000000000 +0930 +++ gcc-current/gcc/config/rs6000/rs6000.c 2005-05-19 19:13:18.000000000 +0930 @@ -12572,15 +12621,49 @@ rs6000_emit_load_toc_table (int fromprol rtx dest, insn; dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); - if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1) + if (TARGET_ELF && TARGET_DATA_PLT && DEFAULT_ABI != ABI_AIX && flag_pic) { - rtx temp = (fromprolog - ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM) - : gen_reg_rtx (Pmode)); - insn = emit_insn (gen_load_toc_v4_pic_si (temp)); + char buf[30]; + rtx lab, tmp1, tmp2, got, tempLR; + + ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); + lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); + if (flag_pic == 2) + got = gen_rtx_SYMBOL_REF (Pmode, toc_label_name); + else + got = rs6000_got_sym (); + tmp1 = tmp2 = dest; + if (!fromprolog) + { + tmp1 = gen_reg_rtx (Pmode); + tmp2 = gen_reg_rtx (Pmode); + } + tempLR = (fromprolog + ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM) + : 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 if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1) + { + rtx tempLR = (fromprolog + ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM) + : gen_reg_rtx (Pmode)); + + insn = emit_insn (gen_load_toc_v4_pic_si (tempLR)); if (fromprolog) rs6000_maybe_dead (insn); - insn = emit_move_insn (dest, temp); + insn = emit_move_insn (dest, tempLR); if (fromprolog) rs6000_maybe_dead (insn); } 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-19 19:11:10.000000000 +0930 +++ gcc-current/gcc/config/rs6000/rs6000.md 2005-05-19 21:32:25.000000000 +0930 @@ -7360,26 +7360,6 @@ ;; Now define ways of moving data around. -;; Elf specific ways of loading addresses for non-PIC code. -;; The output of this could be r0, but we make a very strong -;; preference for a base register because it will usually -;; be needed there. -(define_insn "elf_high" - [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r") - (high:SI (match_operand 1 "" "")))] - "TARGET_ELF && ! TARGET_64BIT" - "{liu|lis} %0,%1@ha") - -(define_insn "elf_low" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r") - (match_operand 2 "" "")))] - "TARGET_ELF && ! TARGET_64BIT" - "@ - {cal|la} %0,%2@l(%1) - {ai|addic} %0,%1,%K2") - - ;; Set up a register with a value from the GOT table (define_expand "movsi_got" @@ -9810,7 +9788,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")]) @@ -9833,6 +9812,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")))))] + "TARGET_ELF && TARGET_DATA_PLT && DEFAULT_ABI != ABI_AIX && flag_pic" + "{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"))))] + "TARGET_ELF && TARGET_DATA_PLT && DEFAULT_ABI != ABI_AIX && flag_pic" + "{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 @@ -9867,6 +9862,25 @@ rs6000_emit_load_toc_table (FALSE); DONE; }") + +;; Elf specific ways of loading addresses for non-PIC code. +;; The output of this could be r0, but we make a very strong +;; preference for a base register because it will usually +;; be needed there. +(define_insn "elf_high" + [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r") + (high:SI (match_operand 1 "" "")))] + "TARGET_ELF && ! TARGET_64BIT" + "{liu|lis} %0,%1@ha") + +(define_insn "elf_low" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") + (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r") + (match_operand 2 "" "")))] + "TARGET_ELF && ! TARGET_64BIT" + "@ + {cal|la} %0,%2@l(%1) + {ai|addic} %0,%1,%K2") ;; A function pointer under AIX is a pointer to a data area whose first word ;; contains the actual address of the function, whose second word contains a @@ -9983,6 +9997,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)) @@ -10034,6 +10067,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)) @@ -10307,7 +10362,18 @@ #if TARGET_MACHO return output_call(insn, operands, 0, 2); #else - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0"; + if (DEFAULT_ABI == ABI_V4 && flag_pic) + { + if (TARGET_DATA_PLT && flag_pic == 2) + /* The magic 32768 offset here and in the other sysv call insns + corresponds to the offset of r30 in .got2, as given by LCTOC1. + See sysv4.h:toc_section. */ + return "bl %z0+32768@plt"; + else + return "bl %z0@plt"; + } + else + return "bl %z0"; #endif } [(set_attr "type" "branch,branch") @@ -10352,7 +10418,15 @@ #if TARGET_MACHO return output_call(insn, operands, 1, 3); #else - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1"; + if (DEFAULT_ABI == ABI_V4 && flag_pic) + { + if (TARGET_DATA_PLT && flag_pic == 2) + return "bl %z1+32768@plt"; + else + return "bl %z1@plt"; + } + else + return "bl %z1"; #endif } [(set_attr "type" "branch,branch") @@ -10567,7 +10641,15 @@ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn (\"creqv 6,6,6\", operands); - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\"; + if (DEFAULT_ABI == ABI_V4 && flag_pic) + { + if (TARGET_DATA_PLT && flag_pic == 2) + return \"b %z0+32768@plt\"; + else + return \"b %z0@plt\"; + } + else + return \"b %z0\"; }" [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) @@ -10613,7 +10695,15 @@ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn (\"creqv 6,6,6\", operands); - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\"; + if (DEFAULT_ABI == ABI_V4 && flag_pic) + { + if (TARGET_DATA_PLT && flag_pic == 2) + return \"b %z1+32768@plt\"; + else + return \"b %z1@plt\"; + } + else + return \"b %z1\"; }" [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-rs6000 gcc-current/gcc/config/rs6000/t-rs6000 --- gcc-virgin/gcc/config/rs6000/t-rs6000 2004-05-26 10:55:14.000000000 +0930 +++ gcc-current/gcc/config/rs6000/t-rs6000 2005-05-18 14:29:13.000000000 +0930 @@ -18,3 +18,6 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60 # The rs6000 backend doesn't cause warnings in these files. insn-conditions.o-warn = + +# Whether to use -mdata-plt in other t-files. +DATA_PLT := $(shell sed -n -e 's/\#define HAVE_AS_REL16 1/mdata-plt/p' auto-host.h) diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-linux64 gcc-current/gcc/config/rs6000/t-linux64 --- gcc-virgin/gcc/config/rs6000/t-linux64 2004-04-15 18:55:03.000000000 +0930 +++ gcc-current/gcc/config/rs6000/t-linux64 2005-05-19 20:00:06.000000000 +0930 @@ -4,13 +4,13 @@ LIB2FUNCS_EXTRA = tramp.S $(srcdir)/config/rs6000/ppc64-fp.c \ $(srcdir)/config/rs6000/darwin-ldouble.c -TARGET_LIBGCC2_CFLAGS = -mno-minimal-toc -fPIC -specs=bispecs +TARGET_LIBGCC2_CFLAGS = -mno-minimal-toc -fPIC $(DATA_PLT:m%=-m%) -specs=bispecs SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver MULTILIB_OPTIONS = m64/m32 msoft-float MULTILIB_DIRNAMES = 64 32 nof -MULTILIB_EXTRA_OPTS = fPIC mstrict-align +MULTILIB_EXTRA_OPTS = fPIC $(DATA_PLT) mstrict-align MULTILIB_EXCEPTIONS = m64/msoft-float MULTILIB_EXCLUSIONS = m64/!m32/msoft-float MULTILIB_OSDIRNAMES = ../lib64 ../lib nof diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-lynx gcc-current/gcc/config/rs6000/t-lynx --- gcc-virgin/gcc/config/rs6000/t-lynx 2004-08-05 14:25:37.000000000 +0930 +++ gcc-current/gcc/config/rs6000/t-lynx 2005-05-19 20:00:05.000000000 +0930 @@ -29,9 +29,9 @@ EXTRA_MULTILIB_PARTS = crtbegin.o crtend # If .sdata is enabled __CTOR_{LIST,END}__ go into .sdata instead of # .ctors. CRTSTUFF_T_CFLAGS = -mno-sdata - + # Compile crtbeginS.o and crtendS.o with pic. -CRTSTUFF_T_CFLAGS_S = -fPIC -mno-sdata +CRTSTUFF_T_CFLAGS_S = -fPIC $(DATA_PLT:m%=-m%) -mno-sdata Local Variables: mode: makefile diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-netbsd gcc-current/gcc/config/rs6000/t-netbsd --- gcc-virgin/gcc/config/rs6000/t-netbsd 2002-11-26 10:35:07.000000000 +1030 +++ gcc-current/gcc/config/rs6000/t-netbsd 2005-05-19 20:00:05.000000000 +0930 @@ -26,7 +26,7 @@ MULTILIB_MATCHES_FLOAT = msoft-float=mcp MULTILIB_OPTIONS = msoft-float MULTILIB_DIRNAMES = soft-float -MULTILIB_EXTRA_OPTS = fPIC mstrict-align +MULTILIB_EXTRA_OPTS = fPIC $(DATA_PLT) mstrict-align MULTILIB_EXCEPTIONS = MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-ppccomm gcc-current/gcc/config/rs6000/t-ppccomm --- gcc-virgin/gcc/config/rs6000/t-ppccomm 2002-12-20 22:53:07.000000000 +1030 +++ gcc-current/gcc/config/rs6000/t-ppccomm 2005-05-19 20:00:04.000000000 +0930 @@ -60,4 +60,4 @@ $(T)crtsavres$(objext): crtsavres.S CRTSTUFF_T_CFLAGS = -msdata=none # Make sure crt*.o are built with -fPIC even if configured with # --enable-shared --disable-multilib -CRTSTUFF_T_CFLAGS_S = -fPIC -msdata=none +CRTSTUFF_T_CFLAGS_S = -fPIC $(DATA_PLT:m%=-m%) -msdata=none diff -urp -xCVS -x'*~' -x'.#*' gcc-virgin/gcc/config/rs6000/t-ppcos gcc-current/gcc/config/rs6000/t-ppcos --- gcc-virgin/gcc/config/rs6000/t-ppcos 2001-11-25 00:32:46.000000000 +1030 +++ gcc-current/gcc/config/rs6000/t-ppcos 2005-05-19 20:00:04.000000000 +0930 @@ -2,7 +2,7 @@ MULTILIB_OPTIONS = msoft-float MULTILIB_DIRNAMES = nof -MULTILIB_EXTRA_OPTS = fPIC mstrict-align +MULTILIB_EXTRA_OPTS = fPIC $(DATA_PLT) mstrict-align MULTILIB_EXCEPTIONS = MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT}