summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2006-05-29 14:11:07 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2006-05-29 14:11:07 +0000
commit55be0e321ba0662cd1562ec1ca0c3aeb78bb5628 (patch)
tree732dd171b1791bdb175f887cfa846cd7546dc5a7 /gcc
parentd470ecbdb45fd3daa00e5d7eddbd74c80eaf7dbe (diff)
downloadgcc-55be0e321ba0662cd1562ec1ca0c3aeb78bb5628.tar.gz
* config/bfin/bfin.opt (mfdpic): New option.
* config/bfin/t-bfin-elf (EXTRA_PARTS): Add crtbeginS.o and crtendS.o. (EXTRA_MULTILIB_PARTS): Likewise. (CRTSTUFF_T_CFLAGS, TARGET_LIBGCC2_CFLAGS): Use -fpic. (MULTILIB_OPTIONS, MULTILIB_EXCEPTIONS): Build one extra -mfdpic multilib. * config/bfin/elf.h (STARTFILE_SPEC): Don't link in crt0.o if -shared. (CRT_CALL_STATIC_FUNCTION): New. * config/bfin/uclinux.h (STARTFILE_SPEC): Don't link in crt0.o if -shared. (CRT_CALL_STATIC_FUNCTION): New. * config/bfin/bfin.c (legitimize_pic_address): Now static. Handle FD-PIC moves. (n_pregs_to_save): PIC register doesn't need to be saved with FD-PIC. (print_operand): Handle UNSPEC_MOVE_FDPIC and UNSPEC_FUNCDESC_GOT17M4. (initialize_trampoline): Changed to handle FD-PIC code generation. (expand_move): If TARGET_FDPIC, use emit_pic_move as needed. (bfin_expand_call): Generate FD-PIC calls if TARGET_FDPIC. (override_options): Disallow -mid-shared-library -mfdpic combination. Can't do unaligned ops if FD-PIC. Turn off flag_pic if trying to generate non-id-shared-library non-fdpic code, since it's not supported. (bfin_assemble_integer): New function. (TARGET_ASM_INTEGER): Define. * config/bfin/crti.s (__init, __fini): Save P3 on the stack if __BFIN_FDPIC__. * config/bfin/crtn.s: Restore them. * config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS): Define __BFIN_FDPIC__ if TARGET_FDPIC. (DRIVER_SELF_SPECS, SUBTARGET_DRIVER_SELF_SPECS, LINK_GCC_C_SEQUENCE_SPEC, ASM_SPEC, LINK_SPEC): New macros. (FDPIC_FPTR_REGNO, FDPIC_REGNO, OUR_FDPIC_REG): New macros. (TRAMPOLINE_SIZE, TRAMPOLINE_TEMPLATE): Adjust for FD-PIC. (CONDITIONAL_REGISTER_USAGE): If TARGET_FDPIC, FDPIC_REGNO is call-used. (enum reg_class, REG_CLASS_CONTENTS, REG_CLASS_NAMES): Add FDPIC_REGS and FDPIC_FPTR_REGS. (REG_CLASS_FROM_LETTER): Use 'Z' and 'Y' for them. * config/bfin/bfin.md (UNSPEC_MOVE_FDPIC, UNSPEC_FUNCDESC_GOT17M4, UNSPEC_VOLATILE_LOAD_FUNCDESC): New constants. (load_funcdescsi): New pattern. (call_symbol_fdpic, sibcall_symbol_fdpic, call_value_symbol_fdpic, sibcall_value_symbol_fdpic, call_insn_fdpic, sibcall_insn_fdpic, call_value_insn_fdpic, sibcall_value_insn_fdpic): New patterns. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114199 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog47
-rw-r--r--gcc/config/bfin/bfin.c168
-rw-r--r--gcc/config/bfin/bfin.h84
-rw-r--r--gcc/config/bfin/bfin.md116
-rw-r--r--gcc/config/bfin/bfin.opt4
-rw-r--r--gcc/config/bfin/crti.s4
-rw-r--r--gcc/config/bfin/crtn.s4
-rw-r--r--gcc/config/bfin/elf.h9
-rw-r--r--gcc/config/bfin/t-bfin-elf11
-rw-r--r--gcc/config/bfin/uclinux.h9
10 files changed, 405 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b74289ade6a..67964a96aa7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,50 @@
+2005-05-29 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin/bfin.opt (mfdpic): New option.
+ * config/bfin/t-bfin-elf (EXTRA_PARTS): Add crtbeginS.o and crtendS.o.
+ (EXTRA_MULTILIB_PARTS): Likewise.
+ (CRTSTUFF_T_CFLAGS, TARGET_LIBGCC2_CFLAGS): Use -fpic.
+ (MULTILIB_OPTIONS, MULTILIB_EXCEPTIONS): Build one extra -mfdpic
+ multilib.
+ * config/bfin/elf.h (STARTFILE_SPEC): Don't link in crt0.o if -shared.
+ (CRT_CALL_STATIC_FUNCTION): New.
+ * config/bfin/uclinux.h (STARTFILE_SPEC): Don't link in crt0.o if
+ -shared.
+ (CRT_CALL_STATIC_FUNCTION): New.
+ * config/bfin/bfin.c (legitimize_pic_address): Now static. Handle
+ FD-PIC moves.
+ (n_pregs_to_save): PIC register doesn't need to be saved with FD-PIC.
+ (print_operand): Handle UNSPEC_MOVE_FDPIC and UNSPEC_FUNCDESC_GOT17M4.
+ (initialize_trampoline): Changed to handle FD-PIC code generation.
+ (expand_move): If TARGET_FDPIC, use emit_pic_move as needed.
+ (bfin_expand_call): Generate FD-PIC calls if TARGET_FDPIC.
+ (override_options): Disallow -mid-shared-library -mfdpic combination.
+ Can't do unaligned ops if FD-PIC.
+ Turn off flag_pic if trying to generate non-id-shared-library
+ non-fdpic code, since it's not supported.
+ (bfin_assemble_integer): New function.
+ (TARGET_ASM_INTEGER): Define.
+ * config/bfin/crti.s (__init, __fini): Save P3 on the stack if
+ __BFIN_FDPIC__.
+ * config/bfin/crtn.s: Restore them.
+ * config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS): Define __BFIN_FDPIC__
+ if TARGET_FDPIC.
+ (DRIVER_SELF_SPECS, SUBTARGET_DRIVER_SELF_SPECS,
+ LINK_GCC_C_SEQUENCE_SPEC, ASM_SPEC, LINK_SPEC): New macros.
+ (FDPIC_FPTR_REGNO, FDPIC_REGNO, OUR_FDPIC_REG): New macros.
+ (TRAMPOLINE_SIZE, TRAMPOLINE_TEMPLATE): Adjust for FD-PIC.
+ (CONDITIONAL_REGISTER_USAGE): If TARGET_FDPIC, FDPIC_REGNO is
+ call-used.
+ (enum reg_class, REG_CLASS_CONTENTS, REG_CLASS_NAMES): Add
+ FDPIC_REGS and FDPIC_FPTR_REGS.
+ (REG_CLASS_FROM_LETTER): Use 'Z' and 'Y' for them.
+ * config/bfin/bfin.md (UNSPEC_MOVE_FDPIC, UNSPEC_FUNCDESC_GOT17M4,
+ UNSPEC_VOLATILE_LOAD_FUNCDESC): New constants.
+ (load_funcdescsi): New pattern.
+ (call_symbol_fdpic, sibcall_symbol_fdpic, call_value_symbol_fdpic,
+ sibcall_value_symbol_fdpic, call_insn_fdpic, sibcall_insn_fdpic,
+ call_value_insn_fdpic, sibcall_value_insn_fdpic): New patterns.
+
2006-05-29 Kazu Hirata <kazu@codesourcery.com>
* gcse.c, rtlanal.c: Remove obsolete comments associated with
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index c7477113c4a..5234bfde50f 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -129,7 +129,7 @@ static e_funkind funkind (tree funtype)
necessary. PICREG is the register holding the pointer to the PIC offset
table. */
-rtx
+static rtx
legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
{
rtx addr = orig;
@@ -141,26 +141,30 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
reg = new = orig;
else
{
- if (reg == 0)
- {
- gcc_assert (!no_new_pseudos);
- reg = gen_reg_rtx (Pmode);
- }
+ int unspec;
+ rtx tmp;
- if (flag_pic == 2)
+ if (TARGET_ID_SHARED_LIBRARY)
+ unspec = UNSPEC_MOVE_PIC;
+ else if (GET_CODE (addr) == SYMBOL_REF
+ && SYMBOL_REF_FUNCTION_P (addr))
{
- emit_insn (gen_movsi_high_pic (reg, addr));
- emit_insn (gen_movsi_low_pic (reg, reg, addr));
- emit_insn (gen_addsi3 (reg, reg, picreg));
- new = gen_const_mem (Pmode, reg);
+ unspec = UNSPEC_FUNCDESC_GOT17M4;
}
else
{
- rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
- UNSPEC_MOVE_PIC);
- new = gen_const_mem (Pmode,
- gen_rtx_PLUS (Pmode, picreg, tmp));
+ unspec = UNSPEC_MOVE_FDPIC;
}
+
+ if (reg == 0)
+ {
+ gcc_assert (!no_new_pseudos);
+ reg = gen_reg_rtx (Pmode);
+ }
+
+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
+ new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
+
emit_move_insn (reg, new);
}
if (picreg == pic_offset_table_rtx)
@@ -254,7 +258,8 @@ n_pregs_to_save (bool is_inthandler)
for (i = REG_P0; i <= REG_P5; i++)
if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
- || (i == PIC_OFFSET_TABLE_REGNUM
+ || (!TARGET_FDPIC
+ && i == PIC_OFFSET_TABLE_REGNUM
&& (current_function_uses_pic_offset_table
|| (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
return REG_P5 - i + 1;
@@ -1343,6 +1348,16 @@ print_operand (FILE *file, rtx x, char code)
fprintf (file, "@GOT");
break;
+ case UNSPEC_MOVE_FDPIC:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOT17M4");
+ break;
+
+ case UNSPEC_FUNCDESC_GOT17M4:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@FUNCDESC_GOT17M4");
+ break;
+
case UNSPEC_LIBRARY_OFFSET:
fprintf (file, "_current_shared_library_p5_offset_");
break;
@@ -1576,17 +1591,26 @@ initialize_trampoline (tramp, fnaddr, cxt)
rtx t1 = copy_to_reg (fnaddr);
rtx t2 = copy_to_reg (cxt);
rtx addr;
+ int i = 0;
+
+ if (TARGET_FDPIC)
+ {
+ rtx a = memory_address (Pmode, plus_constant (tramp, 8));
+ addr = memory_address (Pmode, tramp);
+ emit_move_insn (gen_rtx_MEM (SImode, addr), a);
+ i = 8;
+ }
- addr = memory_address (Pmode, plus_constant (tramp, 2));
+ addr = memory_address (Pmode, plus_constant (tramp, i + 2));
emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
- addr = memory_address (Pmode, plus_constant (tramp, 6));
+ addr = memory_address (Pmode, plus_constant (tramp, i + 6));
emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
- addr = memory_address (Pmode, plus_constant (tramp, 10));
+ addr = memory_address (Pmode, plus_constant (tramp, i + 10));
emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
- addr = memory_address (Pmode, plus_constant (tramp, 14));
+ addr = memory_address (Pmode, plus_constant (tramp, i + 14));
emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
}
@@ -1597,11 +1621,13 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
{
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+ gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
else
operands[1] = legitimize_pic_address (operands[1], temp,
- pic_offset_table_rtx);
+ TARGET_FDPIC ? OUR_FDPIC_REG
+ : pic_offset_table_rtx);
}
/* Expand a move operation in mode MODE. The operands are in OPERANDS. */
@@ -1609,9 +1635,10 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
void
expand_move (rtx *operands, enum machine_mode mode)
{
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ rtx op = operands[1];
+ if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
+ && SYMBOLIC_CONST (op))
emit_pic_move (operands, mode);
-
/* Don't generate memory->memory or constant->memory moves, go through a
register */
else if ((reload_in_progress | reload_completed) == 0
@@ -1674,23 +1701,46 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
{
rtx use = NULL, call;
rtx callee = XEXP (fnaddr, 0);
- rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sibcall ? 3 : 2));
+ int nelts = 2 + !!sibcall;
+ rtx pat;
+ rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
+ int n;
/* In an untyped call, we can get NULL for operand 2. */
if (cookie == NULL_RTX)
cookie = const0_rtx;
/* Static functions and indirect calls don't need the pic register. */
- if (flag_pic
+ if (!TARGET_FDPIC && flag_pic
&& GET_CODE (callee) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (callee))
use_reg (&use, pic_offset_table_rtx);
- if ((!register_no_elim_operand (callee, Pmode)
- && GET_CODE (callee) != SYMBOL_REF)
- || (GET_CODE (callee) == SYMBOL_REF
- && (flag_pic
- || bfin_longcall_p (callee, INTVAL (cookie)))))
+ if (TARGET_FDPIC)
+ {
+ if (GET_CODE (callee) != SYMBOL_REF
+ || bfin_longcall_p (callee, INTVAL (cookie)))
+ {
+ rtx addr = callee;
+ if (! address_operand (addr, Pmode))
+ addr = force_reg (Pmode, addr);
+
+ fnaddr = gen_reg_rtx (SImode);
+ emit_insn (gen_load_funcdescsi (fnaddr, addr));
+ fnaddr = gen_rtx_MEM (Pmode, fnaddr);
+
+ picreg = gen_reg_rtx (SImode);
+ emit_insn (gen_load_funcdescsi (picreg,
+ plus_constant (addr, 4)));
+ }
+
+ nelts++;
+ }
+ else if ((!register_no_elim_operand (callee, Pmode)
+ && GET_CODE (callee) != SYMBOL_REF)
+ || (GET_CODE (callee) == SYMBOL_REF
+ && (flag_pic
+ || bfin_longcall_p (callee, INTVAL (cookie)))))
{
callee = copy_to_mode_reg (Pmode, callee);
fnaddr = gen_rtx_MEM (Pmode, callee);
@@ -1700,10 +1750,14 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
if (retval)
call = gen_rtx_SET (VOIDmode, retval, call);
- XVECEXP (pat, 0, 0) = call;
- XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie);
+ pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
+ n = 0;
+ XVECEXP (pat, 0, n++) = call;
+ if (TARGET_FDPIC)
+ XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
+ XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
if (sibcall)
- XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode);
+ XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
call = emit_call_insn (pat);
if (use)
CALL_INSN_FUNCTION_USAGE (call) = use;
@@ -1896,10 +1950,23 @@ override_options (void)
if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
error ("-mshared-library-id= specified without -mid-shared-library");
- if (TARGET_ID_SHARED_LIBRARY)
- /* ??? Provide a way to use a bigger GOT. */
+ if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
flag_pic = 1;
+ if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
+ error ("ID shared libraries and FD-PIC mode can't be used together.");
+
+ /* There is no single unaligned SI op for PIC code. Sometimes we
+ need to use ".4byte" and sometimes we need to use ".picptr".
+ See bfin_assemble_integer for details. */
+ if (TARGET_FDPIC)
+ targetm.asm_out.unaligned_op.si = 0;
+
+ /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
+ since we don't support it and it'll just break. */
+ if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
+ flag_pic = 0;
+
flag_schedule_insns = 0;
}
@@ -2895,6 +2962,34 @@ const struct attribute_spec bfin_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL }
};
+/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
+ tell the assembler to generate pointers to function descriptors in
+ some cases. */
+
+static bool
+bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
+{
+ if (TARGET_FDPIC && size == UNITS_PER_WORD)
+ {
+ if (GET_CODE (value) == SYMBOL_REF
+ && SYMBOL_REF_FUNCTION_P (value))
+ {
+ fputs ("\t.picptr\tfuncdesc(", asm_out_file);
+ output_addr_const (asm_out_file, value);
+ fputs (")\n", asm_out_file);
+ return true;
+ }
+ if (!aligned_p)
+ {
+ /* We've set the unaligned SI op to NULL, so we always have to
+ handle the unaligned case here. */
+ assemble_integer_with_op ("\t.4byte\t", value);
+ return true;
+ }
+ }
+ return default_assemble_integer (value, size, aligned_p);
+}
+
/* Output the assembler code for a thunk function. THUNK_DECL is the
declaration for the thunk function itself, FUNCTION is the decl for
the target function. DELTA is an immediate constant offset to be
@@ -3500,6 +3595,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#undef TARGET_ASM_INTERNAL_LABEL
#define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER bfin_assemble_integer
+
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index 777303e3807..0fb9299d494 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -1,5 +1,5 @@
/* Definitions for the Blackfin port.
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Analog Devices.
This file is part of GCC.
@@ -42,12 +42,51 @@ extern int target_flags;
builtin_define ("bfin"); \
builtin_define ("BFIN"); \
builtin_define ("__ADSPBLACKFIN__"); \
+ if (TARGET_FDPIC) \
+ builtin_define ("__BFIN_FDPIC__"); \
if (TARGET_ID_SHARED_LIBRARY) \
builtin_define ("__ID_SHARED_LIB__"); \
} \
while (0)
#endif
+#define DRIVER_SELF_SPECS SUBTARGET_DRIVER_SELF_SPECS "\
+ %{mfdpic:%{!fpic:%{!fpie:%{!fPIC:%{!fPIE:\
+ %{!fno-pic:%{!fno-pie:%{!fno-PIC:%{!fno-PIE:-fpie}}}}}}}}} \
+"
+#ifndef SUBTARGET_DRIVER_SELF_SPECS
+# define SUBTARGET_DRIVER_SELF_SPECS
+#endif
+
+#define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{mfdpic:%{!static: %L} %{static: %G %L %G}} \
+ %{!mfdpic:%G %L %G}"
+
+/* A C string constant that tells the GCC driver program options to pass to
+ the assembler. It can also specify how to translate options you give to GNU
+ CC into options for GCC to pass to the assembler. See the file `sun3.h'
+ for an example of this.
+
+ Do not define this macro if it does not need to do anything.
+
+ Defined in svr4.h. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{G*} %{v} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+ %{mno-fdpic:-mnopic} %{mfdpic}"
+
+#define LINK_SPEC "\
+%{h*} %{v:-V} \
+%{b} \
+%{mfdpic:-melf32bfinfd -z text} \
+%{static:-dn -Bstatic} \
+%{shared:-G -Bdynamic} \
+%{symbolic:-Bsymbolic} \
+%{G*} \
+%{YP,*} \
+%{Qy:} %{!Qn:-Qy} \
+-init __init -fini __fini "
+
/* Generate DSP instructions, like DSP halfword loads */
#define TARGET_DSP (1)
@@ -117,6 +156,10 @@ extern const char *bfin_library_id_string;
to allocate such a register (if necessary). */
#define PIC_OFFSET_TABLE_REGNUM (REG_P5)
+#define FDPIC_FPTR_REGNO REG_P1
+#define FDPIC_REGNO REG_P3
+#define OUR_FDPIC_REG get_hard_reg_initial_val (SImode, FDPIC_REGNO)
+
/* A static chain register for nested functions. We need to use a
call-clobbered register for this. */
#define STATIC_CHAIN_REGNUM REG_P2
@@ -157,13 +200,28 @@ extern const char *bfin_library_id_string;
(TREE_CODE (EXP) == STRING_CST \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-#define TRAMPOLINE_SIZE 18
+#define TRAMPOLINE_SIZE (TARGET_FDPIC ? 30 : 18)
#define TRAMPOLINE_TEMPLATE(FILE) \
- fprintf(FILE, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ \
- fprintf(FILE, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */; \
- fprintf(FILE, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */; \
- fprintf(FILE, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */; \
- fprintf(FILE, "\t.dw\t0x0051\n"); /* jump (p1)*/
+ if (TARGET_FDPIC) \
+ { \
+ fprintf(FILE, "\t.dd\t0x00000000\n"); /* 0 */ \
+ fprintf(FILE, "\t.dd\t0x00000000\n"); /* 0 */ \
+ fprintf(FILE, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ \
+ fprintf(FILE, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ \
+ fprintf(FILE, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ \
+ fprintf(FILE, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ \
+ fprintf(FILE, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */ \
+ fprintf(FILE, "\t.dw\t0x9149\n"); /* p1 = [p1] */ \
+ fprintf(FILE, "\t.dw\t0x0051\n"); /* jump (p1)*/ \
+ } \
+ else \
+ { \
+ fprintf(FILE, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ \
+ fprintf(FILE, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ \
+ fprintf(FILE, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ \
+ fprintf(FILE, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ \
+ fprintf(FILE, "\t.dw\t0x0051\n"); /* jump (p1)*/ \
+ }
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
initialize_trampoline (TRAMP, FNADDR, CXT)
@@ -299,7 +357,9 @@ extern const char *bfin_library_id_string;
#define CONDITIONAL_REGISTER_USAGE \
{ \
conditional_register_usage(); \
- if (flag_pic) \
+ if (TARGET_FDPIC) \
+ call_used_regs[FDPIC_REGNO] = 1; \
+ if (!TARGET_FDPIC && flag_pic) \
{ \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
@@ -343,6 +403,8 @@ enum reg_class
EVEN_DREGS,
ODD_DREGS,
DREGS,
+ FDPIC_REGS,
+ FDPIC_FPTR_REGS,
PREGS_CLOBBERED,
PREGS,
IPREGS,
@@ -374,6 +436,8 @@ enum reg_class
"EVEN_DREGS", \
"ODD_DREGS", \
"DREGS", \
+ "FDPIC_REGS", \
+ "FDPIC_FPTR_REGS", \
"PREGS_CLOBBERED", \
"PREGS", \
"IPREGS", \
@@ -413,6 +477,8 @@ enum reg_class
{ 0x00000055, 0 }, /* EVEN_DREGS */ \
{ 0x000000aa, 0 }, /* ODD_DREGS */ \
{ 0x000000ff, 0 }, /* DREGS */ \
+ { 0x00000800, 0x000 }, /* FDPIC_REGS */ \
+ { 0x00000200, 0x000 }, /* FDPIC_FPTR_REGS */ \
{ 0x00004700, 0x800 }, /* PREGS_CLOBBERED */ \
{ 0x0000ff00, 0x800 }, /* PREGS */ \
{ 0x000fff00, 0x800 }, /* IPREGS */ \
@@ -455,6 +521,8 @@ enum reg_class
#define REG_CLASS_FROM_LETTER(LETTER) \
((LETTER) == 'a' ? PREGS : \
+ (LETTER) == 'Z' ? FDPIC_REGS : \
+ (LETTER) == 'Y' ? FDPIC_FPTR_REGS : \
(LETTER) == 'd' ? DREGS : \
(LETTER) == 'z' ? PREGS_CLOBBERED : \
(LETTER) == 'D' ? EVEN_DREGS : \
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 6992de3ac08..b2b7cffa587 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -122,12 +122,15 @@
(UNSPEC_PUSH_MULTIPLE 5)
;; Multiply or MAC with extra CONST_INT operand specifying the macflag
(UNSPEC_MUL_WITH_FLAG 6)
- (UNSPEC_MAC_WITH_FLAG 7)])
+ (UNSPEC_MAC_WITH_FLAG 7)
+ (UNSPEC_MOVE_FDPIC 8)
+ (UNSPEC_FUNCDESC_GOT17M4 9)])
(define_constants
[(UNSPEC_VOLATILE_EH_RETURN 0)
(UNSPEC_VOLATILE_CSYNC 1)
- (UNSPEC_VOLATILE_SSYNC 2)])
+ (UNSPEC_VOLATILE_SSYNC 2)
+ (UNSPEC_VOLATILE_LOAD_FUNCDESC 3)])
(define_constants
[(MACFLAG_NONE 0)
@@ -1495,6 +1498,19 @@
;; Call instructions..
+;; The explicit MEM inside the UNSPEC prevents the compiler from moving
+;; the load before a branch after a NULL test, or before a store that
+;; initializes a function descriptor.
+
+(define_insn_and_split "load_funcdescsi"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))]
+ UNSPEC_VOLATILE_LOAD_FUNCDESC))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mem:SI (match_dup 1)))])
+
(define_expand "call"
[(parallel [(call (match_operand:SI 0 "" "")
(match_operand 1 "" ""))
@@ -1539,6 +1555,102 @@
DONE;
})
+(define_insn "*call_symbol_fdpic"
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
+ (match_operand 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "register_operand" "Z"))
+ (use (match_operand 3 "" ""))]
+ "! SIBLING_CALL_P (insn)
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !bfin_longcall_p (operands[0], INTVAL (operands[3]))"
+ "call %0;"
+ [(set_attr "type" "call")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_symbol_fdpic"
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
+ (match_operand 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "register_operand" "Z"))
+ (use (match_operand 3 "" ""))
+ (return)]
+ "SIBLING_CALL_P (insn)
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !bfin_longcall_p (operands[0], INTVAL (operands[3]))"
+ "jump.l %0;"
+ [(set_attr "type" "br")
+ (set_attr "length" "4")])
+
+(define_insn "*call_value_symbol_fdpic"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
+ (match_operand 2 "general_operand" "g")))
+ (use (match_operand:SI 3 "register_operand" "Z"))
+ (use (match_operand 4 "" ""))]
+ "! SIBLING_CALL_P (insn)
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !bfin_longcall_p (operands[1], INTVAL (operands[4]))"
+ "call %1;"
+ [(set_attr "type" "call")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_value_symbol_fdpic"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
+ (match_operand 2 "general_operand" "g")))
+ (use (match_operand:SI 3 "register_operand" "Z"))
+ (use (match_operand 4 "" ""))
+ (return)]
+ "SIBLING_CALL_P (insn)
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !bfin_longcall_p (operands[1], INTVAL (operands[4]))"
+ "jump.l %1;"
+ [(set_attr "type" "br")
+ (set_attr "length" "4")])
+
+(define_insn "*call_insn_fdpic"
+ [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y"))
+ (match_operand 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "register_operand" "Z"))
+ (use (match_operand 3 "" ""))]
+ "! SIBLING_CALL_P (insn)"
+ "call (%0);"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")])
+
+(define_insn "*sibcall_insn_fdpic"
+ [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y"))
+ (match_operand 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "register_operand" "Z"))
+ (use (match_operand 3 "" ""))
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ "jump (%0);"
+ [(set_attr "type" "br")
+ (set_attr "length" "2")])
+
+(define_insn "*call_value_insn_fdpic"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y"))
+ (match_operand 2 "general_operand" "g")))
+ (use (match_operand:SI 3 "register_operand" "Z"))
+ (use (match_operand 4 "" ""))]
+ "! SIBLING_CALL_P (insn)"
+ "call (%1);"
+ [(set_attr "type" "call")
+ (set_attr "length" "2")])
+
+(define_insn "*sibcall_value_insn_fdpic"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y"))
+ (match_operand 2 "general_operand" "g")))
+ (use (match_operand:SI 3 "register_operand" "Z"))
+ (use (match_operand 4 "" ""))
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ "jump (%1);"
+ [(set_attr "type" "br")
+ (set_attr "length" "2")])
+
(define_insn "*call_symbol"
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
(match_operand 1 "general_operand" "g"))
diff --git a/gcc/config/bfin/bfin.opt b/gcc/config/bfin/bfin.opt
index 43f56c4d624..5fe54c9cfb7 100644
--- a/gcc/config/bfin/bfin.opt
+++ b/gcc/config/bfin/bfin.opt
@@ -47,3 +47,7 @@ ID of shared library to build
mlong-calls
Target Report Mask(LONG_CALLS)
Avoid generating pc-relative calls; use indirection
+
+mfdpic
+Target Report Mask(FDPIC)
+Enable Function Descriptor PIC mode
diff --git a/gcc/config/bfin/crti.s b/gcc/config/bfin/crti.s
index 5a13df19bbd..c9753599986 100644
--- a/gcc/config/bfin/crti.s
+++ b/gcc/config/bfin/crti.s
@@ -40,6 +40,8 @@ Boston, MA 02110-1301, USA. */
__init:
#if defined __ID_SHARED_LIB__
[--SP] = P5;
+#elif defined __BFIN_FDPIC__
+ [--SP] = P3;
#endif
LINK 12;
#if defined __ID_SHARED_LIB__
@@ -51,6 +53,8 @@ __init:
__fini:
#if defined __ID_SHARED_LIB__
[--SP] = P5;
+#elif defined __BFIN_FDPIC__
+ [--SP] = P3;
#endif
LINK 12;
#if defined __ID_SHARED_LIB__
diff --git a/gcc/config/bfin/crtn.s b/gcc/config/bfin/crtn.s
index 69a17c0184e..06af2bea9e7 100644
--- a/gcc/config/bfin/crtn.s
+++ b/gcc/config/bfin/crtn.s
@@ -38,6 +38,8 @@ Boston, MA 02110-1301, USA. */
unlink;
#if defined __ID_SHARED_LIB__
P5 = [SP++];
+#elif defined __BFIN_FDPIC__
+ P3 = [SP++];
#endif
rts;
@@ -45,5 +47,7 @@ Boston, MA 02110-1301, USA. */
unlink;
#if defined __ID_SHARED_LIB__
P5 = [SP++];
+#elif defined __BFIN_FDPIC__
+ P3 = [SP++];
#endif
rts;
diff --git a/gcc/config/bfin/elf.h b/gcc/config/bfin/elf.h
index 621b786c94d..39d06881dfb 100644
--- a/gcc/config/bfin/elf.h
+++ b/gcc/config/bfin/elf.h
@@ -7,7 +7,7 @@
sprintf (LABEL, "*%s%s$%d", LOCAL_LABEL_PREFIX, PREFIX, (int) NUM)
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crt0%O%s crti%O%s crtbegin%O%s crtlibid%O%s"
+#define STARTFILE_SPEC "%{!shared: crt0%O%s} crti%O%s crtbegin%O%s crtlibid%O%s"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
@@ -15,4 +15,11 @@
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
+#ifdef __BFIN_FDPIC__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+asm (SECTION_OP); \
+asm ("P3 = [SP + 20];\n\tcall " USER_LABEL_PREFIX #FUNC ";"); \
+asm (TEXT_SECTION_ASM_OP);
+#endif
+
#define NO_IMPLICIT_EXTERN_C
diff --git a/gcc/config/bfin/t-bfin-elf b/gcc/config/bfin/t-bfin-elf
index 64e71b0d3cf..8b30cf62497 100644
--- a/gcc/config/bfin/t-bfin-elf
+++ b/gcc/config/bfin/t-bfin-elf
@@ -3,7 +3,7 @@
LIB1ASMSRC = bfin/lib1funcs.asm
LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3
-EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+EXTRA_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o
FPBIT = fp-bit.c
DPBIT = dp-bit.c
@@ -19,10 +19,13 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# it is fixed in binutils (if it is necessary).
GCC_CFLAGS += -N
-MULTILIB_OPTIONS=mid-shared-library
+CRTSTUFF_T_CFLAGS = -fpic
+TARGET_LIBGCC2_CFLAGS = -fpic
+
+MULTILIB_OPTIONS=mid-shared-library mfdpic
MULTILIB_DEFAULTS=
MULTILIB_DIRNAMES=
-MULTILIB_EXCEPTIONS=
+MULTILIB_EXCEPTIONS=mid-shared-library/mfdpic
# Assemble startup files.
$(T)crti.o: $(srcdir)/config/bfin/crti.s $(GCC_PASSES)
@@ -38,4 +41,4 @@ $(T)crtlibid.o: $(srcdir)/config/bfin/crtlibid.s $(GCC_PASSES)
-c -o $(T)crtlibid.o -x assembler-with-cpp \
$(srcdir)/config/bfin/crtlibid.s
-EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crti.o crtn.o crtlibid.o
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o
diff --git a/gcc/config/bfin/uclinux.h b/gcc/config/bfin/uclinux.h
index 7476df8255a..57e062dd68e 100644
--- a/gcc/config/bfin/uclinux.h
+++ b/gcc/config/bfin/uclinux.h
@@ -4,7 +4,7 @@
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "crt1%O%s crti%O%s crtbegin%O%s crtlibid%O%s"
+ "%{!shared: crt1%O%s} crti%O%s crtbegin%O%s crtlibid%O%s"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
@@ -13,4 +13,11 @@
#undef LIB_SPEC
#define LIB_SPEC "%{pthread:-lpthread} -lc"
+#ifdef __BFIN_FDPIC__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+asm (SECTION_OP); \
+asm ("P3 = [SP + 20];\n\tcall " USER_LABEL_PREFIX #FUNC ";"); \
+asm (TEXT_SECTION_ASM_OP);
+#endif
+
#define NO_IMPLICIT_EXTERN_C