Commit 6614f9f5 by Bernd Schmidt Committed by Bernd Schmidt

bfin.opt (mfdpic): New option.

	* 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.

From-SVN: r114199
parent 152279c4
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> 2006-05-29 Kazu Hirata <kazu@codesourcery.com>
* gcse.c, rtlanal.c: Remove obsolete comments associated with * gcse.c, rtlanal.c: Remove obsolete comments associated with
......
...@@ -129,7 +129,7 @@ static e_funkind funkind (tree funtype) ...@@ -129,7 +129,7 @@ static e_funkind funkind (tree funtype)
necessary. PICREG is the register holding the pointer to the PIC offset necessary. PICREG is the register holding the pointer to the PIC offset
table. */ table. */
rtx static rtx
legitimize_pic_address (rtx orig, rtx reg, rtx picreg) legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
{ {
rtx addr = orig; rtx addr = orig;
...@@ -141,26 +141,30 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg) ...@@ -141,26 +141,30 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
reg = new = orig; reg = new = orig;
else else
{ {
if (reg == 0) int unspec;
{ rtx tmp;
gcc_assert (!no_new_pseudos);
reg = gen_reg_rtx (Pmode);
}
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)); unspec = UNSPEC_FUNCDESC_GOT17M4;
emit_insn (gen_movsi_low_pic (reg, reg, addr));
emit_insn (gen_addsi3 (reg, reg, picreg));
new = gen_const_mem (Pmode, reg);
} }
else else
{ {
rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec = UNSPEC_MOVE_FDPIC;
UNSPEC_MOVE_PIC);
new = gen_const_mem (Pmode,
gen_rtx_PLUS (Pmode, picreg, tmp));
} }
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); emit_move_insn (reg, new);
} }
if (picreg == pic_offset_table_rtx) if (picreg == pic_offset_table_rtx)
...@@ -254,7 +258,8 @@ n_pregs_to_save (bool is_inthandler) ...@@ -254,7 +258,8 @@ n_pregs_to_save (bool is_inthandler)
for (i = REG_P0; i <= REG_P5; i++) for (i = REG_P0; i <= REG_P5; i++)
if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[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 && (current_function_uses_pic_offset_table
|| (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf)))) || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
return REG_P5 - i + 1; return REG_P5 - i + 1;
...@@ -1343,6 +1348,16 @@ print_operand (FILE *file, rtx x, char code) ...@@ -1343,6 +1348,16 @@ print_operand (FILE *file, rtx x, char code)
fprintf (file, "@GOT"); fprintf (file, "@GOT");
break; 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: case UNSPEC_LIBRARY_OFFSET:
fprintf (file, "_current_shared_library_p5_offset_"); fprintf (file, "_current_shared_library_p5_offset_");
break; break;
...@@ -1576,17 +1591,26 @@ initialize_trampoline (tramp, fnaddr, cxt) ...@@ -1576,17 +1591,26 @@ initialize_trampoline (tramp, fnaddr, cxt)
rtx t1 = copy_to_reg (fnaddr); rtx t1 = copy_to_reg (fnaddr);
rtx t2 = copy_to_reg (cxt); rtx t2 = copy_to_reg (cxt);
rtx addr; 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_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16))); 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)); 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_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16))); 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)); 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) ...@@ -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); 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])) if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
operands[1] = force_reg (SImode, operands[1]); operands[1] = force_reg (SImode, operands[1]);
else else
operands[1] = legitimize_pic_address (operands[1], temp, 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. */ /* 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) ...@@ -1609,9 +1635,10 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
void void
expand_move (rtx *operands, enum machine_mode mode) 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); emit_pic_move (operands, mode);
/* Don't generate memory->memory or constant->memory moves, go through a /* Don't generate memory->memory or constant->memory moves, go through a
register */ register */
else if ((reload_in_progress | reload_completed) == 0 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) ...@@ -1674,23 +1701,46 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
{ {
rtx use = NULL, call; rtx use = NULL, call;
rtx callee = XEXP (fnaddr, 0); 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. */ /* In an untyped call, we can get NULL for operand 2. */
if (cookie == NULL_RTX) if (cookie == NULL_RTX)
cookie = const0_rtx; cookie = const0_rtx;
/* Static functions and indirect calls don't need the pic register. */ /* Static functions and indirect calls don't need the pic register. */
if (flag_pic if (!TARGET_FDPIC && flag_pic
&& GET_CODE (callee) == SYMBOL_REF && GET_CODE (callee) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (callee)) && !SYMBOL_REF_LOCAL_P (callee))
use_reg (&use, pic_offset_table_rtx); use_reg (&use, pic_offset_table_rtx);
if ((!register_no_elim_operand (callee, Pmode) if (TARGET_FDPIC)
&& GET_CODE (callee) != SYMBOL_REF) {
|| (GET_CODE (callee) == SYMBOL_REF if (GET_CODE (callee) != SYMBOL_REF
&& (flag_pic || bfin_longcall_p (callee, INTVAL (cookie)))
|| 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); callee = copy_to_mode_reg (Pmode, callee);
fnaddr = gen_rtx_MEM (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) ...@@ -1700,10 +1750,14 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
if (retval) if (retval)
call = gen_rtx_SET (VOIDmode, retval, call); call = gen_rtx_SET (VOIDmode, retval, call);
XVECEXP (pat, 0, 0) = call; pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie); 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) if (sibcall)
XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode); XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
call = emit_call_insn (pat); call = emit_call_insn (pat);
if (use) if (use)
CALL_INSN_FUNCTION_USAGE (call) = use; CALL_INSN_FUNCTION_USAGE (call) = use;
...@@ -1896,10 +1950,23 @@ override_options (void) ...@@ -1896,10 +1950,23 @@ override_options (void)
if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY) if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
error ("-mshared-library-id= specified without -mid-shared-library"); error ("-mshared-library-id= specified without -mid-shared-library");
if (TARGET_ID_SHARED_LIBRARY) if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
/* ??? Provide a way to use a bigger GOT. */
flag_pic = 1; 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; flag_schedule_insns = 0;
} }
...@@ -2895,6 +2962,34 @@ const struct attribute_spec bfin_attribute_table[] = ...@@ -2895,6 +2962,34 @@ const struct attribute_spec bfin_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL } { 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 /* Output the assembler code for a thunk function. THUNK_DECL is the
declaration for the thunk function itself, FUNCTION is the decl for declaration for the thunk function itself, FUNCTION is the decl for
the target function. DELTA is an immediate constant offset to be the target function. DELTA is an immediate constant offset to be
...@@ -3500,6 +3595,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, ...@@ -3500,6 +3595,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#undef TARGET_ASM_INTERNAL_LABEL #undef TARGET_ASM_INTERNAL_LABEL
#define TARGET_ASM_INTERNAL_LABEL bfin_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 #undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
......
/* Definitions for the Blackfin port. /* Definitions for the Blackfin port.
Copyright (C) 2005, 2006 Free Software Foundation, Inc. Copyright (C) 2005 Free Software Foundation, Inc.
Contributed by Analog Devices. Contributed by Analog Devices.
This file is part of GCC. This file is part of GCC.
...@@ -42,12 +42,51 @@ extern int target_flags; ...@@ -42,12 +42,51 @@ extern int target_flags;
builtin_define ("bfin"); \ builtin_define ("bfin"); \
builtin_define ("BFIN"); \ builtin_define ("BFIN"); \
builtin_define ("__ADSPBLACKFIN__"); \ builtin_define ("__ADSPBLACKFIN__"); \
if (TARGET_FDPIC) \
builtin_define ("__BFIN_FDPIC__"); \
if (TARGET_ID_SHARED_LIBRARY) \ if (TARGET_ID_SHARED_LIBRARY) \
builtin_define ("__ID_SHARED_LIB__"); \ builtin_define ("__ID_SHARED_LIB__"); \
} \ } \
while (0) while (0)
#endif #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 */ /* Generate DSP instructions, like DSP halfword loads */
#define TARGET_DSP (1) #define TARGET_DSP (1)
...@@ -117,6 +156,10 @@ extern const char *bfin_library_id_string; ...@@ -117,6 +156,10 @@ extern const char *bfin_library_id_string;
to allocate such a register (if necessary). */ to allocate such a register (if necessary). */
#define PIC_OFFSET_TABLE_REGNUM (REG_P5) #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 /* A static chain register for nested functions. We need to use a
call-clobbered register for this. */ call-clobbered register for this. */
#define STATIC_CHAIN_REGNUM REG_P2 #define STATIC_CHAIN_REGNUM REG_P2
...@@ -157,13 +200,28 @@ extern const char *bfin_library_id_string; ...@@ -157,13 +200,28 @@ extern const char *bfin_library_id_string;
(TREE_CODE (EXP) == STRING_CST \ (TREE_CODE (EXP) == STRING_CST \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
#define TRAMPOLINE_SIZE 18 #define TRAMPOLINE_SIZE (TARGET_FDPIC ? 30 : 18)
#define TRAMPOLINE_TEMPLATE(FILE) \ #define TRAMPOLINE_TEMPLATE(FILE) \
fprintf(FILE, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ \ if (TARGET_FDPIC) \
fprintf(FILE, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */; \ { \
fprintf(FILE, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */; \ fprintf(FILE, "\t.dd\t0x00000000\n"); /* 0 */ \
fprintf(FILE, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */; \ fprintf(FILE, "\t.dd\t0x00000000\n"); /* 0 */ \
fprintf(FILE, "\t.dw\t0x0051\n"); /* jump (p1)*/ 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) \ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
initialize_trampoline (TRAMP, FNADDR, CXT) initialize_trampoline (TRAMP, FNADDR, CXT)
...@@ -299,7 +357,9 @@ extern const char *bfin_library_id_string; ...@@ -299,7 +357,9 @@ extern const char *bfin_library_id_string;
#define CONDITIONAL_REGISTER_USAGE \ #define CONDITIONAL_REGISTER_USAGE \
{ \ { \
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; \ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
...@@ -343,6 +403,8 @@ enum reg_class ...@@ -343,6 +403,8 @@ enum reg_class
EVEN_DREGS, EVEN_DREGS,
ODD_DREGS, ODD_DREGS,
DREGS, DREGS,
FDPIC_REGS,
FDPIC_FPTR_REGS,
PREGS_CLOBBERED, PREGS_CLOBBERED,
PREGS, PREGS,
IPREGS, IPREGS,
...@@ -374,6 +436,8 @@ enum reg_class ...@@ -374,6 +436,8 @@ enum reg_class
"EVEN_DREGS", \ "EVEN_DREGS", \
"ODD_DREGS", \ "ODD_DREGS", \
"DREGS", \ "DREGS", \
"FDPIC_REGS", \
"FDPIC_FPTR_REGS", \
"PREGS_CLOBBERED", \ "PREGS_CLOBBERED", \
"PREGS", \ "PREGS", \
"IPREGS", \ "IPREGS", \
...@@ -413,6 +477,8 @@ enum reg_class ...@@ -413,6 +477,8 @@ enum reg_class
{ 0x00000055, 0 }, /* EVEN_DREGS */ \ { 0x00000055, 0 }, /* EVEN_DREGS */ \
{ 0x000000aa, 0 }, /* ODD_DREGS */ \ { 0x000000aa, 0 }, /* ODD_DREGS */ \
{ 0x000000ff, 0 }, /* DREGS */ \ { 0x000000ff, 0 }, /* DREGS */ \
{ 0x00000800, 0x000 }, /* FDPIC_REGS */ \
{ 0x00000200, 0x000 }, /* FDPIC_FPTR_REGS */ \
{ 0x00004700, 0x800 }, /* PREGS_CLOBBERED */ \ { 0x00004700, 0x800 }, /* PREGS_CLOBBERED */ \
{ 0x0000ff00, 0x800 }, /* PREGS */ \ { 0x0000ff00, 0x800 }, /* PREGS */ \
{ 0x000fff00, 0x800 }, /* IPREGS */ \ { 0x000fff00, 0x800 }, /* IPREGS */ \
...@@ -455,6 +521,8 @@ enum reg_class ...@@ -455,6 +521,8 @@ enum reg_class
#define REG_CLASS_FROM_LETTER(LETTER) \ #define REG_CLASS_FROM_LETTER(LETTER) \
((LETTER) == 'a' ? PREGS : \ ((LETTER) == 'a' ? PREGS : \
(LETTER) == 'Z' ? FDPIC_REGS : \
(LETTER) == 'Y' ? FDPIC_FPTR_REGS : \
(LETTER) == 'd' ? DREGS : \ (LETTER) == 'd' ? DREGS : \
(LETTER) == 'z' ? PREGS_CLOBBERED : \ (LETTER) == 'z' ? PREGS_CLOBBERED : \
(LETTER) == 'D' ? EVEN_DREGS : \ (LETTER) == 'D' ? EVEN_DREGS : \
......
...@@ -122,12 +122,15 @@ ...@@ -122,12 +122,15 @@
(UNSPEC_PUSH_MULTIPLE 5) (UNSPEC_PUSH_MULTIPLE 5)
;; Multiply or MAC with extra CONST_INT operand specifying the macflag ;; Multiply or MAC with extra CONST_INT operand specifying the macflag
(UNSPEC_MUL_WITH_FLAG 6) (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 (define_constants
[(UNSPEC_VOLATILE_EH_RETURN 0) [(UNSPEC_VOLATILE_EH_RETURN 0)
(UNSPEC_VOLATILE_CSYNC 1) (UNSPEC_VOLATILE_CSYNC 1)
(UNSPEC_VOLATILE_SSYNC 2)]) (UNSPEC_VOLATILE_SSYNC 2)
(UNSPEC_VOLATILE_LOAD_FUNCDESC 3)])
(define_constants (define_constants
[(MACFLAG_NONE 0) [(MACFLAG_NONE 0)
...@@ -1495,6 +1498,19 @@ ...@@ -1495,6 +1498,19 @@
;; Call instructions.. ;; 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" (define_expand "call"
[(parallel [(call (match_operand:SI 0 "" "") [(parallel [(call (match_operand:SI 0 "" "")
(match_operand 1 "" "")) (match_operand 1 "" ""))
...@@ -1539,6 +1555,102 @@ ...@@ -1539,6 +1555,102 @@
DONE; 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" (define_insn "*call_symbol"
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
(match_operand 1 "general_operand" "g")) (match_operand 1 "general_operand" "g"))
......
...@@ -47,3 +47,7 @@ ID of shared library to build ...@@ -47,3 +47,7 @@ ID of shared library to build
mlong-calls mlong-calls
Target Report Mask(LONG_CALLS) Target Report Mask(LONG_CALLS)
Avoid generating pc-relative calls; use indirection Avoid generating pc-relative calls; use indirection
mfdpic
Target Report Mask(FDPIC)
Enable Function Descriptor PIC mode
...@@ -40,6 +40,8 @@ Boston, MA 02110-1301, USA. */ ...@@ -40,6 +40,8 @@ Boston, MA 02110-1301, USA. */
__init: __init:
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
[--SP] = P5; [--SP] = P5;
#elif defined __BFIN_FDPIC__
[--SP] = P3;
#endif #endif
LINK 12; LINK 12;
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
...@@ -51,6 +53,8 @@ __init: ...@@ -51,6 +53,8 @@ __init:
__fini: __fini:
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
[--SP] = P5; [--SP] = P5;
#elif defined __BFIN_FDPIC__
[--SP] = P3;
#endif #endif
LINK 12; LINK 12;
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
......
...@@ -38,6 +38,8 @@ Boston, MA 02110-1301, USA. */ ...@@ -38,6 +38,8 @@ Boston, MA 02110-1301, USA. */
unlink; unlink;
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
P5 = [SP++]; P5 = [SP++];
#elif defined __BFIN_FDPIC__
P3 = [SP++];
#endif #endif
rts; rts;
...@@ -45,5 +47,7 @@ Boston, MA 02110-1301, USA. */ ...@@ -45,5 +47,7 @@ Boston, MA 02110-1301, USA. */
unlink; unlink;
#if defined __ID_SHARED_LIB__ #if defined __ID_SHARED_LIB__
P5 = [SP++]; P5 = [SP++];
#elif defined __BFIN_FDPIC__
P3 = [SP++];
#endif #endif
rts; rts;
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
sprintf (LABEL, "*%s%s$%d", LOCAL_LABEL_PREFIX, PREFIX, (int) NUM) sprintf (LABEL, "*%s%s$%d", LOCAL_LABEL_PREFIX, PREFIX, (int) NUM)
#undef STARTFILE_SPEC #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 #undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend%O%s crtn%O%s" #define ENDFILE_SPEC "crtend%O%s crtn%O%s"
...@@ -15,4 +15,11 @@ ...@@ -15,4 +15,11 @@
#undef USER_LABEL_PREFIX #undef USER_LABEL_PREFIX
#define 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 #define NO_IMPLICIT_EXTERN_C
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
LIB1ASMSRC = bfin/lib1funcs.asm LIB1ASMSRC = bfin/lib1funcs.asm
LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 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 FPBIT = fp-bit.c
DPBIT = dp-bit.c DPBIT = dp-bit.c
...@@ -19,10 +19,13 @@ fp-bit.c: $(srcdir)/config/fp-bit.c ...@@ -19,10 +19,13 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# it is fixed in binutils (if it is necessary). # it is fixed in binutils (if it is necessary).
GCC_CFLAGS += -N 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_DEFAULTS=
MULTILIB_DIRNAMES= MULTILIB_DIRNAMES=
MULTILIB_EXCEPTIONS= MULTILIB_EXCEPTIONS=mid-shared-library/mfdpic
# Assemble startup files. # Assemble startup files.
$(T)crti.o: $(srcdir)/config/bfin/crti.s $(GCC_PASSES) $(T)crti.o: $(srcdir)/config/bfin/crti.s $(GCC_PASSES)
...@@ -38,4 +41,4 @@ $(T)crtlibid.o: $(srcdir)/config/bfin/crtlibid.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 \ -c -o $(T)crtlibid.o -x assembler-with-cpp \
$(srcdir)/config/bfin/crtlibid.s $(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
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#undef STARTFILE_SPEC #undef STARTFILE_SPEC
#define 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 #undef ENDFILE_SPEC
#define ENDFILE_SPEC \ #define ENDFILE_SPEC \
...@@ -13,4 +13,11 @@ ...@@ -13,4 +13,11 @@
#undef LIB_SPEC #undef LIB_SPEC
#define LIB_SPEC "%{pthread:-lpthread} -lc" #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 #define NO_IMPLICIT_EXTERN_C
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment