OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jan 2007 19:40:12 +0000 (19:40 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jan 2007 19:40:12 +0000 (19:40 +0000)
* config/m68k/m68k-protos.h (m68k_output_pic_call): Delete.
(output_call, m68k_legitimize_call_address): Declare.
* config/m68k/m68k.h (EXTRA_CONSTRAINT): Remove unnecessary
parenthesees.  Add support for a 'W' constraint.
(LEGITIMATE_PIC_OPERAND_P): Remove SYMBOL_REF_FLAG handling.
(PRINT_OPERAND_PUNCT_VALID_P): Remove comment about 'o'.
(m68k_symbolic_call, m68k_symbolic_jump): Declare.
* config/m68k/m68k.c (m68k_symbolic_call, m68k_symbolic_jump): New
variables.
(override_options): Initialize them.  Do not set flag_no_function_cse
for TARGET_ID_SHARED_LIBRARY.
(m68k_output_pic_call): Delete.
(m68k_legitimize_call_address): New function.
(print_operand): Remove the %o prefix.  Handle the %p prefix.
(output_call): New function.
(m68k_output_mi_thunk): Use m68k_symbolic_jump.  Always load the
target address from the GOT if symbolic jumps are not allowed.
* config/m68k/m68k.md (call, general_operand): Do not set
SYMBOL_REF_FLAG.  Use m68k_legitimize_call_address instead.
Merge separate flag_pic and !flag_pic define_insns into...
(*call, *call_value): ...these new patterns.  Match the address
rather than the containing MEM and require it to be a call_operand.
Use output_call to generate the asm template.
* config/m68k/predicates.md (const_call_operand): New predicate.
(call_operand): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120921 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md
gcc/config/m68k/predicates.md

index 9719e09..2459a97 100644 (file)
@@ -1,3 +1,31 @@
+2007-01-18  Richard Sandiford  <richard@codesourcery.com>
+
+       * config/m68k/m68k-protos.h (m68k_output_pic_call): Delete.
+       (output_call, m68k_legitimize_call_address): Declare.
+       * config/m68k/m68k.h (EXTRA_CONSTRAINT): Remove unnecessary
+       parenthesees.  Add support for a 'W' constraint.
+       (LEGITIMATE_PIC_OPERAND_P): Remove SYMBOL_REF_FLAG handling.
+       (PRINT_OPERAND_PUNCT_VALID_P): Remove comment about 'o'.
+       (m68k_symbolic_call, m68k_symbolic_jump): Declare.
+       * config/m68k/m68k.c (m68k_symbolic_call, m68k_symbolic_jump): New
+       variables.
+       (override_options): Initialize them.  Do not set flag_no_function_cse
+       for TARGET_ID_SHARED_LIBRARY.
+       (m68k_output_pic_call): Delete.
+       (m68k_legitimize_call_address): New function.
+       (print_operand): Remove the %o prefix.  Handle the %p prefix.
+       (output_call): New function.
+       (m68k_output_mi_thunk): Use m68k_symbolic_jump.  Always load the
+       target address from the GOT if symbolic jumps are not allowed.
+       * config/m68k/m68k.md (call, general_operand): Do not set
+       SYMBOL_REF_FLAG.  Use m68k_legitimize_call_address instead.
+       Merge separate flag_pic and !flag_pic define_insns into...
+       (*call, *call_value): ...these new patterns.  Match the address
+       rather than the containing MEM and require it to be a call_operand.
+       Use output_call to generate the asm template.
+       * config/m68k/predicates.md (const_call_operand): New predicate.
+       (call_operand): Likewise.
+
 2007-01-18  Nathan Sidwell  <nathan@codesourcery.com>
 
        * config/m68k/m68k.h (REGISTER_MOVE_COST): Simplify definition.
index 75f6f25..30d25b7 100644 (file)
@@ -39,7 +39,7 @@ extern const char *output_addsi3 (rtx *);
 extern const char *output_andsi3 (rtx *);
 extern const char *output_iorsi3 (rtx *);
 extern const char *output_xorsi3 (rtx *);
-extern void m68k_output_pic_call (rtx dest);
+extern const char *output_call (rtx);
 extern void output_dbcc_and_branch (rtx *);
 extern int floating_exact_log2 (rtx);
 extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target);
@@ -64,4 +64,5 @@ extern void override_options (void);
 extern const char *m68k_cpp_cpu_ident (const char *);
 extern const char *m68k_cpp_cpu_family (const char *);
 extern void init_68881_table (void);
+extern rtx m68k_legitimize_call_address (rtx);
 extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);
index 25b8f0c..03d59b9 100644 (file)
@@ -327,6 +327,12 @@ enum fpu_type m68k_fpu;
 
 /* The set of FL_* flags that apply to the target processor.  */
 unsigned int m68k_cpu_flags;
+
+/* Asm templates for calling or jumping to an arbitrary symbolic address,
+   or NULL if such calls or jumps are not supported.  The address is held
+   in operand 0.  */
+const char *m68k_symbolic_call;
+const char *m68k_symbolic_jump;
 \f
 /* See whether TABLE has an entry with name NAME.  Return true and
    store the entry in *ENTRY if so, otherwise return false and
@@ -530,13 +536,42 @@ override_options (void)
   if (TARGET_PCREL && flag_pic == 0)
     flag_pic = 1;
 
-  /* Turn off function cse if we are doing PIC.  We always want function call
-     to be done as `bsr foo@PLTPC', so it will force the assembler to create
-     the PLT entry for `foo'. Doing function cse will cause the address of
-     `foo' to be loaded into a register, which is exactly what we want to
-     avoid when we are doing PIC on svr4 m68k.  */
-  if (flag_pic)
-    flag_no_function_cse = 1;
+  if (!flag_pic)
+    {
+#if MOTOROLA && !defined (USE_GAS)
+      m68k_symbolic_call = "jsr %a0";
+      m68k_symbolic_jump = "jmp %a0";
+#else
+      m68k_symbolic_call = "jbsr %a0";
+      m68k_symbolic_jump = "jra %a0";
+#endif
+    }
+  else if (TARGET_ID_SHARED_LIBRARY)
+    /* All addresses must be loaded from the GOT.  */
+    ;
+  else if (TARGET_68020 || TARGET_ISAB)
+    {
+      if (TARGET_PCREL)
+       {
+         m68k_symbolic_call = "bsr.l %c0";
+         m68k_symbolic_jump = "bra.l %c0";
+       }
+      else
+       {
+#if defined(USE_GAS)
+         m68k_symbolic_call = "bsr.l %p0";
+         m68k_symbolic_jump = "bra.l %p0";
+#else
+         m68k_symbolic_call = "bsr %p0";
+         m68k_symbolic_jump = "bra %p0";
+#endif
+       }
+      /* Turn off function cse if we are doing PIC.  We always want
+        function call to be done as `bsr foo@PLTPC'.  */
+      /* ??? It's traditional to do this for -mpcrel too, but it isn't
+        clear how intentional that is.  */
+      flag_no_function_cse = 1;
+    }
 
   SUBTARGET_OVERRIDE_OPTIONS;
 }
@@ -1332,33 +1367,16 @@ flags_in_68881 (void)
   return cc_status.flags & CC_IN_68881;
 }
 
-/* Output a BSR instruction suitable for PIC code.  */
-void
-m68k_output_pic_call (rtx dest)
-{
-  const char *out;
-
-  if (!(GET_CODE (dest) == MEM && GET_CODE (XEXP (dest, 0)) == SYMBOL_REF))
-    out = "jsr %0";
-      /* We output a BSR instruction if we're building for a target that
-        supports long branches.  Otherwise we generate one of two sequences:
-        a shorter one that uses a GOT entry or a longer one that doesn't.
-        We'll use the -Os command-line flag to decide which to generate.
-        Both sequences take the same time to execute on the ColdFire.  */
-  else if (TARGET_PCREL)
-    out = "bsr.l %o0";
-  else if (TARGET_68020)
-#if defined(USE_GAS)
-    out = "bsr.l %0@PLTPC";
-#else
-    out = "bsr %0@PLTPC";
-#endif
-  else if (optimize_size || TARGET_ID_SHARED_LIBRARY)
-    out = "move.l %0@GOT(%%a5), %%a1\n\tjsr (%%a1)";
-  else
-    out = "lea %0-.-8,%%a1\n\tjsr 0(%%pc,%%a1)";
+/* Convert X to a legitimate function call memory reference and return the
+   result.  */
 
-  output_asm_insn (out, &dest);
+rtx
+m68k_legitimize_call_address (rtx x)
+{
+  gcc_assert (MEM_P (x));
+  if (call_operand (XEXP (x, 0), VOIDmode))
+    return x;
+  return replace_equiv_address (x, force_reg (Pmode, XEXP (x, 0)));
 }
 
 /* Output a dbCC; jCC sequence.  Note we do not handle the 
@@ -3083,12 +3101,10 @@ floating_exact_log2 (rtx x)
    'b' for byte insn (no effect, on the Sun; this is for the ISI).
    'd' to force memory addressing to be absolute, not relative.
    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
-   'o' for operands to go directly to output_operand_address (bypassing
-       print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
        or print pair of registers as rx:ry.
-
-   */
+   'p' print an address with @PLTPC attached, but only if the operand
+       is not locally-bound.  */
 
 void
 print_operand (FILE *file, rtx op, int letter)
@@ -3120,13 +3136,11 @@ print_operand (FILE *file, rtx op, int letter)
     }
   else if (letter == '/')
     asm_fprintf (file, "%R");
-  else if (letter == 'o')
+  else if (letter == 'p')
     {
-      /* This is only for direct addresses with TARGET_PCREL */
-      gcc_assert (GET_CODE (op) == MEM
-                 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-                 && TARGET_PCREL);
-      output_addr_const (file, XEXP (op, 0));
+      output_addr_const (file, op);
+      if (!(GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op)))
+       fprintf (file, "@PLTPC");
     }
   else if (GET_CODE (op) == REG)
     {
@@ -3693,6 +3707,18 @@ output_xorsi3 (rtx *operands)
   return "eor%.l %2,%0";
 }
 
+/* Return the instruction that should be used for a call to address X,
+   which is known to be in operand 0.  */
+
+const char *
+output_call (rtx x)
+{
+  if (symbolic_operand (x, VOIDmode))
+    return m68k_symbolic_call;
+  else
+    return "jsr %a0";
+}
+
 #ifdef M68K_TARGET_COFF
 
 /* Output assembly to switch to section NAME with attribute FLAGS.  */
@@ -3759,43 +3785,13 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
 
   xops[0] = DECL_RTL (function);
 
-  /* Logic taken from call patterns in m68k.md.  */
-  if (flag_pic)
-    {
-      if (TARGET_PCREL)
-       fmt = "bra.l %o0";
-      else if (flag_pic == 1 || TARGET_68020)
-       {
-         if (MOTOROLA)
-           {
-#if defined (USE_GAS)
-             fmt = "bra.l %0@PLTPC";
-#else
-             fmt = "bra %0@PLTPC";
-#endif
-           }
-         else /* !MOTOROLA */
-           {
-#ifdef USE_GAS
-             fmt = "bra.l %0";
-#else
-             fmt = "jra %0,a1";
-#endif
-           }
-       }
-      else if (optimize_size || TARGET_ID_SHARED_LIBRARY)
-        fmt = "move.l %0@GOT(%%a5), %%a1\n\tjmp (%%a1)";
-      else
-        fmt = "lea %0-.-8,%%a1\n\tjmp 0(%%pc,%%a1)";
-    }
-  else
-    {
-#if MOTOROLA && !defined (USE_GAS)
-      fmt = "jmp %0";
-#else
-      fmt = "jra %0";
-#endif
-    }
+  gcc_assert (MEM_P (xops[0])
+             && symbolic_operand (XEXP (xops[0], 0), VOIDmode));
+  xops[0] = XEXP (xops[0], 0);
+
+  fmt = m68k_symbolic_jump;
+  if (m68k_symbolic_jump == NULL)
+    fmt = "move.l %%a1@GOT(%%a5), %%a1\n\tjmp (%%a1)";
 
   output_asm_insn (fmt, xops);
 }
index 3d46ee9..2b72781 100644 (file)
@@ -513,32 +513,35 @@ extern enum reg_class regno_reg_class[];
 /* `Q' means address register indirect addressing mode.
    `S' is for operands that satisfy 'm' when -mpcrel is in effect.
    `T' is for operands that satisfy 's' when -mpcrel is not in effect.
-   `U' is for register offset addressing.  */
+   `U' is for register offset addressing.
+   `W' is for const_call_operands.  */
 #define EXTRA_CONSTRAINT(OP,CODE)                      \
-  (((CODE) == 'S')                                     \
+  ((CODE) == 'S'                                       \
    ? (TARGET_PCREL                                     \
       && GET_CODE (OP) == MEM                          \
       && (GET_CODE (XEXP (OP, 0)) == SYMBOL_REF                \
          || GET_CODE (XEXP (OP, 0)) == LABEL_REF       \
          || GET_CODE (XEXP (OP, 0)) == CONST))         \
    :                                                   \
-  (((CODE) == 'T')                                     \
+   (CODE) == 'T'                                       \
    ? ( !TARGET_PCREL                                   \
       && (GET_CODE (OP) == SYMBOL_REF                  \
          || GET_CODE (OP) == LABEL_REF                 \
          || GET_CODE (OP) == CONST))                   \
    :                                                   \
-  (((CODE) == 'Q')                                     \
+   (CODE) == 'Q'                                       \
    ? (GET_CODE (OP) == MEM                             \
       && GET_CODE (XEXP (OP, 0)) == REG)               \
    :                                                   \
-  (((CODE) == 'U')                                     \
+   (CODE) == 'U'                                       \
    ? (GET_CODE (OP) == MEM                             \
       && GET_CODE (XEXP (OP, 0)) == PLUS               \
       && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG      \
       && GET_CODE (XEXP (XEXP (OP, 0), 1)) == CONST_INT) \
    :                                                   \
-   0))))
+   (CODE) == 'W'                                       \
+   ? const_call_operand (OP, VOIDmode)                 \
+   : 0)
 
 /* On the m68k, use a data reg if possible when the
    value is a constant in the range where moveq could be used
@@ -803,7 +806,6 @@ __transfer_from_trampoline ()                                       \
 
 #define LEGITIMATE_PIC_OPERAND_P(X)    \
   (! symbolic_operand (X, VOIDmode)                            \
-   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X))      \
    || PCREL_GENERAL_OPERAND_OK)
 
 #ifndef REG_OK_STRICT
@@ -1232,8 +1234,6 @@ do { if (cc_prev_status.flags & CC_IN_68881)                      \
    'b' for byte insn (no effect, on the Sun; this is for the ISI).
    'd' to force memory addressing to be absolute, not relative.
    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
-   'o' for operands to go directly to output_operand_address (bypassing
-       print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
        or print pair of registers as rx:ry.  */
 
@@ -1292,3 +1292,5 @@ extern enum target_device m68k_cpu;
 extern enum uarch_type m68k_tune;
 extern enum fpu_type m68k_fpu;
 extern unsigned int m68k_cpu_flags;
+extern const char *m68k_symbolic_call;
+extern const char *m68k_symbolic_jump;
index f797192..91b95fb 100644 (file)
     "subql #1,%0\;cmpl #-1,%0\;jne %l1";
 })
 
-
-;; For PIC calls, in order to be able to support
-;; dynamic linker LAZY BINDING, all the procedure calls need to go
-;; through the PLT (Procedure Linkage Table) section in PIC mode.
-;;
-;; PIC calls are handled by loading the address of the function into a
-;; register (via movsi), then emitting a register indirect call using
-;; the "jsr" function call syntax.
-;;
-;; When outputting MIT syntax (e.g. on Suns), we add a bogus extra
-;; operand to the jbsr statement to indicate that this call should
-;; go through the PLT (why? because this is the way that Sun does it).
-;;
-;; We have different patterns for PIC calls and non-PIC calls.  The
-;; different patterns are only used to choose the right syntax.
-;;
-;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it
-;; will create the correct relocation entry (R_68K_PLT32) for `FUNC',
-;; that tells the linker editor to create an entry for `FUNC' in PLT
-;; section at link time. However, all global objects reference are still
-;; done by using `OBJ@GOT'. So, the goal here is to output the function
-;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'.
-;; We need to have a way to differentiate these two different operands.
-;;
-;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate
-;; these two different operands. The macro LEGITIMATE_PIC_OPERAND_P needs
-;; to be changed to recognize function calls symbol_ref operand as a valid
-;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will
-;; avoid the compiler to load this symbol_ref operand into a register.
-;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly
-;; since the value is a PC relative offset, not a real address.
-;;
-;; All global objects are treated in the similar way as in SUN3. The only
-;; difference is: on m68k svr4, the reference of such global object needs
-;; to end with a suffix "@GOT" so the assembler and linker know to create
-;; an entry for it in GOT (Global Offset Table) section. This is done in
-;; m68k.c.
-
 ;; Call subroutine with no return value.
 (define_expand "call"
   [(call (match_operand:QI 0 "memory_operand" "")
         (match_operand:SI 1 "general_operand" ""))]
   ;; Operand 1 not really used on the m68000.
-
   ""
 {
-  if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
-    SYMBOL_REF_FLAG (XEXP (operands[0], 0)) = 1;
+  operands[0] = m68k_legitimize_call_address (operands[0]);
 })
 
-;; This is a normal call sequence.
-(define_insn ""
-  [(call (match_operand:QI 0 "memory_operand" "o")
-        (match_operand:SI 1 "general_operand" "g"))]
+(define_insn "*call"
+  [(call (mem:QI (match_operand:SI 0 "call_operand" "a,W"))
+        (match_operand:SI 1 "general_operand" "g,g"))]
   ;; Operand 1 not really used on the m68000.
-
-  "! flag_pic"
-{
-#if MOTOROLA && !defined (USE_GAS)
-  return "jsr %0";
-#else
-  return "jbsr %0";
-#endif
-})
-
-;; This is a PIC call sequence.
-(define_insn ""
-  [(call (match_operand:QI 0 "memory_operand" "o")
-        (match_operand:SI 1 "general_operand" "g"))]
-  ;; Operand 1 not really used on the m68000.
-
-  "flag_pic"
+  ""
 {
-  m68k_output_pic_call(operands[0]);
-  return "";
+  return output_call (operands[0]);
 })
 
 ;; Call subroutine, returning value in operand 0
 ;; (which must be a hard register).
-;; See comments before "call" regarding PIC calls.
 (define_expand "call_value"
   [(set (match_operand 0 "" "")
        (call (match_operand:QI 1 "memory_operand" "")
-     (match_operand:SI 2 "general_operand" "")))]
+             (match_operand:SI 2 "general_operand" "")))]
   ;; Operand 2 not really used on the m68000.
   ""
 {
-  if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
-    SYMBOL_REF_FLAG (XEXP (operands[1], 0)) = 1;
+  operands[1] = m68k_legitimize_call_address (operands[1]);
 })
 
-;; This is a normal call_value
-(define_insn ""
-  [(set (match_operand 0 "" "=rf")
-       (call (match_operand:QI 1 "memory_operand" "o")
-             (match_operand:SI 2 "general_operand" "g")))]
+(define_insn "*call_value"
+  [(set (match_operand 0 "" "=rf,rf")
+       (call (mem:QI (match_operand:SI 1 "call_operand" "a,W"))
+             (match_operand:SI 2 "general_operand" "g,g")))]
   ;; Operand 2 not really used on the m68000.
-  "! flag_pic"
-{
-#if MOTOROLA && !defined (USE_GAS)
-  return "jsr %1";
-#else
-  return "jbsr %1";
-#endif
-})
-
-;; This is a PIC call_value
-(define_insn ""
-  [(set (match_operand 0 "" "=rf")
-       (call (match_operand:QI 1 "memory_operand" "o")
-             (match_operand:SI 2 "general_operand" "g")))]
-  ;; Operand 2 not really used on the m68000.
-  "flag_pic"
+  ""
 {
-  m68k_output_pic_call(operands[1]);
-  return "";
+  operands[0] = operands[1];
+  return output_call (operands[0]);
 })
 
 ;; Call subroutine returning any type.
index ca97e0b..11e10f1 100644 (file)
     }
 })
 
+;; A constant that can be used the address in a call insn.
+(define_predicate "const_call_operand"
+  (ior (match_operand 0 "const_int_operand")
+       (and (match_test "m68k_symbolic_call != NULL")
+           (match_operand 0 "symbolic_operand"))))
+
+;; An operand that can be used as the address in a call insn.
+(define_predicate "call_operand"
+  (ior (match_operand 0 "const_call_operand")
+       (match_operand 0 "register_operand")))
+
 ;; TODO: Add a comment here.
 
 (define_predicate "post_inc_operand"