OSDN Git Service

* config/bfin/bfin.opt (mfdpic): New option.
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 May 2006 14:11:07 +0000 (14:11 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 May 2006 14:11:07 +0000 (14:11 +0000)
* 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

gcc/ChangeLog
gcc/config/bfin/bfin.c
gcc/config/bfin/bfin.h
gcc/config/bfin/bfin.md
gcc/config/bfin/bfin.opt
gcc/config/bfin/crti.s
gcc/config/bfin/crtn.s
gcc/config/bfin/elf.h
gcc/config/bfin/t-bfin-elf
gcc/config/bfin/uclinux.h

index b74289a..67964a9 100644 (file)
@@ -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 c747711..5234bfd 100644 (file)
@@ -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 }
 };
 \f
+/* 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);
+}
+\f
 /* 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
 
index 777303e..0fb9299 100644 (file)
@@ -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 :      \
index 6992de3..b2b7cff 100644 (file)
    (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)
 
 ;;  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 "" ""))
   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 43f56c4..5fe54c9 100644 (file)
@@ -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 5a13df1..c975359 100644 (file)
@@ -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 69a17c0..06af2be 100644 (file)
@@ -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 621b786..39d0688 100644 (file)
@@ -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"
 #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 64e71b0..8b30cf6 100644 (file)
@@ -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
index 7476df8..57e062d 100644 (file)
@@ -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 \
 #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