diff options
author | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-05-29 14:11:07 +0000 |
---|---|---|
committer | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-05-29 14:11:07 +0000 |
commit | 55be0e321ba0662cd1562ec1ca0c3aeb78bb5628 (patch) | |
tree | 732dd171b1791bdb175f887cfa846cd7546dc5a7 /gcc | |
parent | d470ecbdb45fd3daa00e5d7eddbd74c80eaf7dbe (diff) | |
download | gcc-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/ChangeLog | 47 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.c | 168 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.h | 84 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 116 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.opt | 4 | ||||
-rw-r--r-- | gcc/config/bfin/crti.s | 4 | ||||
-rw-r--r-- | gcc/config/bfin/crtn.s | 4 | ||||
-rw-r--r-- | gcc/config/bfin/elf.h | 9 | ||||
-rw-r--r-- | gcc/config/bfin/t-bfin-elf | 11 | ||||
-rw-r--r-- | gcc/config/bfin/uclinux.h | 9 |
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 |