This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Committed: Initial FD-PIC support for the Blackfin


This implements a new FD-PIC ABI, very similar to what aoliva did for the FR-V, on the Blackfin. This allows us to use ELF binaries and shared libraries, as well as dlopen/dlsym, on a nommu target.

Some parts of this (primarily related to some shared library issues) are still in flux, but this is about equivalent to the code we'll be shipping in the next Analog toolchain release. Binutils has had the necessary changes for a while.


Bernd


Index: ChangeLog
===================================================================
--- ChangeLog	(revision 114195)
+++ ChangeLog	(working copy)
@@ -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
Index: config/bfin/bfin.opt
===================================================================
--- config/bfin/bfin.opt	(revision 114195)
+++ config/bfin/bfin.opt	(working copy)
@@ -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
Index: config/bfin/t-bfin-elf
===================================================================
--- config/bfin/t-bfin-elf	(revision 114195)
+++ config/bfin/t-bfin-elf	(working copy)
@@ -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/cr
 	-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
Index: config/bfin/elf.h
===================================================================
--- config/bfin/elf.h	(revision 114195)
+++ config/bfin/elf.h	(working copy)
@@ -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
Index: config/bfin/bfin.c
===================================================================
--- config/bfin/bfin.c	(revision 114195)
+++ config/bfin/bfin.c	(working copy)
@@ -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 re
 	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 c
 	      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, cx
   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 machi
 {
   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 machi
 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 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
   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_attribu
   { 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 targe
 #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
 
Index: config/bfin/crti.s
===================================================================
--- config/bfin/crti.s	(revision 114195)
+++ config/bfin/crti.s	(working copy)
@@ -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__
Index: config/bfin/bfin.h
===================================================================
--- config/bfin/bfin.h	(revision 114195)
+++ config/bfin/bfin.h	(working copy)
@@ -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_strin
      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
@@ -161,13 +204,28 @@ extern const char *bfin_library_id_strin
   (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)
@@ -303,7 +361,9 @@ extern const char *bfin_library_id_strin
 #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;	\
@@ -347,6 +407,8 @@ enum reg_class
   EVEN_DREGS,
   ODD_DREGS,
   DREGS,
+  FDPIC_REGS,
+  FDPIC_FPTR_REGS,
   PREGS_CLOBBERED,
   PREGS,
   IPREGS,
@@ -378,6 +440,8 @@ enum reg_class
    "EVEN_DREGS",	\
    "ODD_DREGS",		\
    "DREGS",		\
+   "FDPIC_REGS",	\
+   "FDPIC_FPTR_REGS",	\
    "PREGS_CLOBBERED",	\
    "PREGS",		\
    "IPREGS",		\
@@ -417,6 +481,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 */	\
@@ -459,6 +525,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 : 	\
Index: config/bfin/crtn.s
===================================================================
--- config/bfin/crtn.s	(revision 114195)
+++ config/bfin/crtn.s	(working copy)
@@ -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;
Index: config/bfin/bfin.md
===================================================================
--- config/bfin/bfin.md	(revision 114195)
+++ config/bfin/bfin.md	(working copy)
@@ -122,12 +122,15 @@ (define_constants
    (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 @@ (define_insn "*tablejump_internal"
 
 ;;  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 @@ (define_expand "sibcall_value"
   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"))
Index: config/bfin/uclinux.h
===================================================================
--- config/bfin/uclinux.h	(revision 114195)
+++ config/bfin/uclinux.h	(working copy)
@@ -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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]