OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.md
index a2f0cfd..4c0878a 100644 (file)
 ;; UNSPEC usage:
 
 (define_constants
-  [(UNSPEC_SIN  1)
-   (UNSPEC_COS  2)
+  [(UNSPEC_SIN 1)
+   (UNSPEC_COS 2)
+   (UNSPEC_GOT 3)
   ])
 
 ;; UNSPEC_VOLATILE usage:
 (define_constants
   [(D0_REG             0)
    (A0_REG             8)
+   (A1_REG             9)
+   (PIC_REG            13)
    (SP_REG             15)
+   (FP0_REG            16)
   ])
 
 (include "predicates.md")
   ""
   "nop")
 
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+{
+  m68k_expand_prologue ();
+  DONE;
+})
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+{
+  m68k_expand_epilogue ();
+  DONE;
+})
+
 ;; Used for frameless functions which save no regs and allocate no locals.
-(define_insn "return"
+(define_expand "return"
   [(return)]
   "m68k_use_return_insn ()"
+  "")
+
+(define_insn "*return"
+  [(return)]
+  ""
 {
-  if (current_function_pops_args == 0)
+  if (m68k_interrupt_function_p (current_function_decl))
+    return "rte";
+  else if (current_function_pops_args)
+    {
+      operands[0] = GEN_INT (current_function_pops_args);
+      return "rtd %0";
+    }
+  else
     return "rts";
-  operands[0] = GEN_INT (current_function_pops_args);
-  return "rtd %0";
+})
+
+(define_insn "*m68k_store_multiple"
+  [(match_parallel 0 "" [(match_operand 1 "")])]
+  "m68k_movem_pattern_p (operands[0], NULL, 0, true)"
+{
+  return m68k_output_movem (operands, operands[0], 0, true);
+})
+
+(define_insn "*m68k_store_multiple_automod"
+  [(match_parallel 0 ""
+     [(set (match_operand:SI 1 "register_operand" "=a")
+          (plus:SI (match_operand:SI 2 "register_operand" "1")
+                   (match_operand:SI 3 "const_int_operand")))])]
+  "m68k_movem_pattern_p (operands[0], operands[1], INTVAL (operands[3]), true)"
+{
+  return m68k_output_movem (operands, operands[0], INTVAL (operands[3]), true);
+})
+
+(define_insn "*m68k_load_multiple"
+  [(match_parallel 0 "" [(match_operand 1 "")])]
+  "m68k_movem_pattern_p (operands[0], NULL, 0, false)"
+{
+  return m68k_output_movem (operands, operands[0], 0, false);
+})
+
+(define_insn "*m68k_load_multiple_automod"
+  [(match_parallel 0 ""
+     [(set (match_operand:SI 1 "register_operand" "=a")
+          (plus:SI (match_operand:SI 2 "register_operand" "1")
+                   (match_operand:SI 3 "const_int_operand")))])]
+  "m68k_movem_pattern_p (operands[0], operands[1],
+                        INTVAL (operands[3]), false)"
+{
+  return m68k_output_movem (operands, operands[0],
+                           INTVAL (operands[3]), false);
+})
+
+(define_expand "link"
+  [(parallel
+       [(set (match_operand:SI 0 "register_operand")
+            (plus:SI (reg:SI SP_REG) (const_int -4)))
+       (set (match_dup 2)
+            (match_dup 0))
+       (set (reg:SI SP_REG)
+            (plus:SI (reg:SI SP_REG)
+                     (match_operand:SI 1 "const_int_operand")))])]
+  "TARGET_68020 || INTVAL (operands[1]) >= -0x8004"
+{
+  operands[2] = gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, -4));
+})
+
+(define_insn "*link"
+  [(set (match_operand:SI 0 "register_operand" "+r")
+       (plus:SI (reg:SI SP_REG) (const_int -4)))
+   (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+       (match_dup 0))
+   (set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 1 "const_int_operand")))]
+  "TARGET_68020 || INTVAL (operands[1]) >= -0x8004"
+{
+  operands[1] = GEN_INT (INTVAL (operands[1]) + 4);
+  if (!MOTOROLA)
+    return "link %0,%1";
+  else if (INTVAL (operands[1]) >= -0x8000)
+    return "link.w %0,%1";
+  else
+    return "link.l %0,%1";
+})
+
+(define_expand "unlink"
+  [(parallel
+      [(set (match_operand:SI 0 "register_operand")
+           (match_dup 1))
+       (set (reg:SI SP_REG)
+           (plus:SI (match_dup 0)
+                    (const_int 4)))])]
+  ""
+{
+  operands[1] = gen_frame_mem (SImode, copy_rtx (operands[0]));
+})
+
+(define_insn "*unlink"
+  [(set (match_operand:SI 0 "register_operand" "+r")
+       (mem:SI (match_dup 0)))
+   (set (reg:SI SP_REG)
+       (plus:SI (match_dup 0)
+                (const_int 4)))]
+  ""
+  "unlk %0")
+
+(define_insn "load_got"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(const_int 0)] UNSPEC_GOT))]
+  ""
+{
+  if (TARGET_ID_SHARED_LIBRARY)
+    {
+      operands[1] = gen_rtx_REG (Pmode, PIC_REG);
+      return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0";
+    }
+  else if (MOTOROLA)
+    {
+      if (TARGET_COLDFIRE)
+       /* Load the full 32-bit PC-relative offset of
+          _GLOBAL_OFFSET_TABLE_ into the PIC register, then use it to
+          calculate the absolute value.  The offset and "lea"
+          operation word together occupy 6 bytes.  */
+       return ("move.l #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t"
+               "lea (-6, %%pc, %0), %0");
+      else
+       return "lea (%%pc, _GLOBAL_OFFSET_TABLE_@GOTPC), %0";
+    }
+  else
+    return ("movel #_GLOBAL_OFFSET_TABLE_, %0\n\t"
+           "lea %%pc@(0,%0:l),%0");
 })
 
 (define_insn "indirect_jump"