]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
m68k.md: Add Coldfire FPU support.
authorPaul Brook <paul@codesourcery.com>
Sun, 22 Jan 2006 15:01:02 +0000 (15:01 +0000)
committerPaul Brook <pbrook@gcc.gnu.org>
Sun, 22 Jan 2006 15:01:02 +0000 (15:01 +0000)
2006-01-22  Paul Brook  <paul@codesourcery.com>
Peter Barada  <peter@the-baradas.com>

* config/m68k/m68k.md: Add Coldfire FPU support.
Define FP mode macro and associated attributes.
Use it for float mode patterns.
* config/m68k/linux.h (FUNCTION_VALUE): Use m68k_function_value.
(LIBCALL_VALUE): Use m68k_libcall_value.
* config/m68k/m68k-protos.h (m68k_libcall_value): Add prototype.
(m68k_function_value): Ditto.
(emit_move_sequence): Ditto.
* config/m68k/m68kemb.h (LIBCALL_VALUE): Use m68k_libcall_value.
* config/m68k/m68k-none.h (ASM_SPEC): Add mcfv4e.
* config/m68k/t-m68kelf (MULTILIB_OPTIONS): Add mcfv4e.
(MULTILIB_EXCEPTIONS): Ditto.
* config/m68k/m68k.opt: Add mcfv4e.
* config/m68k/m68k.c (m68k_handle_option): Handle OPT_mcfv4e.
(m68k_compute_frame_layout): Include space for ColdFire FPU regs.
(m68k_output_function_prologue): Save ColdFire FPU registers.
(m68k_output_function_epilogue): Restore ColdFire FPU registers.
(force_mode, fp_reg_operand, emit_move_sequence): New functions.
(m68k_regno_mode_ok): Don't allow types larget than 8 bytes in
ColdFire FPU registers.
(m68k_libcall_value, m68k_function_value): New functions.
* config/m68k/netbsd-elf.h (FUNCTION_VALUE): Use m68k_function_value.
(LIBCALL_VALUE): Use m68k_libcall_value.
* config/m68k/m68k.h (TARGET_CPU_CPP_BUILTINS): Define __mcfv4e__.
(MASK_COLDFIRE): Add MASK_CFV4E.
(TARGET_COLDFIRE_FPU, TARGET_HARD_FLOAT, TARGET_FP_REG_SIZE): New.
(MODES_TIEABLE_P): Use TARGET_HARD_FLOAT.
(REG_CLASS_FROM_LETTER, PREFERRED_RELOAD_CLASS): Ditto.
(GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Define.
(GO_IF_LEGITIMATE_ADDRESS): Use it.
(LEGITIMIZE_ADDRESS): Handle ColdFire FPU addresses.
* doc/invoke.tex: Document -mcfv4e on m68k.

Co-Authored-By: Peter Barada <peter@the-baradas.com>
From-SVN: r110091

12 files changed:
gcc/ChangeLog
gcc/config/m68k/linux.h
gcc/config/m68k/m68k-none.h
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md
gcc/config/m68k/m68k.opt
gcc/config/m68k/m68kemb.h
gcc/config/m68k/netbsd-elf.h
gcc/config/m68k/t-m68kelf
gcc/doc/invoke.texi

index f15c4552a54e3431f6accc392c6223bb830411a2..0c396413477d351523373d4cccbf5fb0c258a953 100644 (file)
@@ -1,3 +1,39 @@
+2006-01-22  Paul Brook  <paul@codesourcery.com>
+       Peter Barada  <peter@the-baradas.com>
+
+       * config/m68k/m68k.md: Add Coldfire FPU support.
+       Define FP mode macro and associated attributes.
+       Use it for float mode patterns.
+       * config/m68k/linux.h (FUNCTION_VALUE): Use m68k_function_value.
+       (LIBCALL_VALUE): Use m68k_libcall_value.
+       * config/m68k/m68k-protos.h (m68k_libcall_value): Add prototype.
+       (m68k_function_value): Ditto.
+       (emit_move_sequence): Ditto.
+       * config/m68k/m68kemb.h (LIBCALL_VALUE): Use m68k_libcall_value.
+       * config/m68k/m68k-none.h (ASM_SPEC): Add mcfv4e.
+       * config/m68k/t-m68kelf (MULTILIB_OPTIONS): Add mcfv4e.
+       (MULTILIB_EXCEPTIONS): Ditto.
+       * config/m68k/m68k.opt: Add mcfv4e.
+       * config/m68k/m68k.c (m68k_handle_option): Handle OPT_mcfv4e.
+       (m68k_compute_frame_layout): Include space for ColdFire FPU regs.
+       (m68k_output_function_prologue): Save ColdFire FPU registers.
+       (m68k_output_function_epilogue): Restore ColdFire FPU registers.
+       (force_mode, fp_reg_operand, emit_move_sequence): New functions.
+       (m68k_regno_mode_ok): Don't allow types larget than 8 bytes in
+       ColdFire FPU registers.
+       (m68k_libcall_value, m68k_function_value): New functions.
+       * config/m68k/netbsd-elf.h (FUNCTION_VALUE): Use m68k_function_value.
+       (LIBCALL_VALUE): Use m68k_libcall_value.
+       * config/m68k/m68k.h (TARGET_CPU_CPP_BUILTINS): Define __mcfv4e__.
+       (MASK_COLDFIRE): Add MASK_CFV4E.
+       (TARGET_COLDFIRE_FPU, TARGET_HARD_FLOAT, TARGET_FP_REG_SIZE): New.
+       (MODES_TIEABLE_P): Use TARGET_HARD_FLOAT.
+       (REG_CLASS_FROM_LETTER, PREFERRED_RELOAD_CLASS): Ditto.
+       (GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Define.
+       (GO_IF_LEGITIMATE_ADDRESS): Use it.
+       (LEGITIMIZE_ADDRESS): Handle ColdFire FPU addresses.
+       * doc/invoke.tex: Document -mcfv4e on m68k.
+
 2006-01-22  Ranjit Mathew  <rmathew@gcc.gnu.org>
 
        * doc/contribute.texi: Change CVS to SVN and update the corresponding
index 5036af9f24c4749142fd09454973ba25509286d5..4f51a021af00bc24fb00331bd878f31269276031 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for Motorola 68k running Linux-based GNU systems with
    ELF format.
-   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -224,11 +224,7 @@ Boston, MA 02110-1301, USA.  */
 
 #undef FUNCTION_VALUE
 #define FUNCTION_VALUE(VALTYPE, FUNC)                                  \
-  (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881                    \
-   ? gen_rtx_REG (TYPE_MODE (VALTYPE), 16)                             \
-   : (POINTER_TYPE_P (VALTYPE)                                         \
-      ? gen_rtx_REG (TYPE_MODE (VALTYPE), 8)                           \
-      : gen_rtx_REG (TYPE_MODE (VALTYPE), 0)))
+  m68k_function_value (VALTYPE, FUNC)
 
 /* For compatibility with the large body of existing code which does
    not always properly declare external functions returning pointer
@@ -251,10 +247,7 @@ do {                                                                       \
 
 #undef LIBCALL_VALUE
 #define LIBCALL_VALUE(MODE)                                            \
-  ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)         \
-    && TARGET_68881)                                                   \
-   ? gen_rtx_REG ((MODE), 16)                                          \
-   : gen_rtx_REG ((MODE), 0))
+  m68k_libcall_value (MODE)
 
 /* For m68k SVR4, structures are returned using the reentrant
    technique.  */
index b3e84c57bfccf74ddd32d6ccb58b01a0b35b82b6..a8618cd033779d8ccad7f36800a6ef2e877555d0 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler.  "naked" 68020.
-   Copyright (C) 1994, 1996, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1996, 2003, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -81,7 +81,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 
 #undef ASM_SPEC
 #define ASM_SPEC "\
-%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881} %{m68000}%{m68302}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040} %{m68020-60:-mc68040} %{m68060}%{mcpu32}%{m68332}%{m5200}%{m5206e}%{m528x}%{m5307}%{m5407}%{!mc68000:%{!m68000:%{!m68302:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68020-60:%{!m68060:%{!mcpu32:%{!m68332:%{!m5200:%{!m5206e:%{!m528x:%{!m5307:%{!m5407:%(asm_cpu_default)}}}}}}}}}}}}}}}}}} \
+%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881} %{m68000}%{m68302}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040} %{m68020-60:-mc68040} %{m68060}%{mcpu32}%{m68332}%{m5200}%{m5206e}%{m528x}%{m5307}%{m5407}%{mcfv4e}%{!mc68000:%{!m68000:%{!m68302:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68020-60:%{!m68060:%{!mcpu32:%{!m68332:%{!m5200:%{!m5206e:%{!m528x:%{!m5307:%{!m5407:%{!mcfv4e:%(asm_cpu_default)}}}}}}}}}}}}}}}}}}} \
 %{fPIC:--pcrel} %{fpic:--pcrel} %{msep-data:--pcrel} %{mid-shared-library:--pcrel} \
 "
 
index 028e2939c49dddc8efd0ca4913e9ec6266de12c1..531c695871331f0fa0475b97a72a3378ef6fcf13 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler.  Sun 68000/68020 version.
-   Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -51,6 +51,9 @@ extern void print_operand (FILE *, rtx, int);
 extern void notice_update_cc (rtx, rtx);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
+extern rtx m68k_libcall_value (enum machine_mode);
+extern rtx m68k_function_value (tree, tree);
+extern int emit_move_sequence (rtx *, enum machine_mode, rtx);
 
 #endif /* RTX_CODE */
 
index c2e9022713805f2b97e2ff49dc0bcc33897dc679..1e753dfcd66e534ea7ae9074e4ff29e6a8aaa713 100644 (file)
@@ -240,6 +240,11 @@ m68k_handle_option (size_t code, const char *arg, int value)
       target_flags |= MASK_CFV4 | MASK_CF_HWDIV;
       return true;
 
+    case OPT_mcfv4e:
+      target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);
+      target_flags |= MASK_CFV4 | MASK_CF_HWDIV | MASK_CFV4E;
+      return true;
+
     case OPT_m68000:
     case OPT_mc68000:
       target_flags &= ~(MASK_ALL_CPU_BITS | MASK_68881);
@@ -411,7 +416,7 @@ m68k_compute_frame_layout (void)
 
   current_frame.foffset = 0;
   mask = rmask = saved = 0;
-  if (TARGET_68881 /* || TARGET_CFV4E */)
+  if (TARGET_HARD_FLOAT)
     {
       for (regno = 16; regno < 24; regno++)
        if (m68k_save_reg (regno, interrupt_handler))
@@ -420,7 +425,7 @@ m68k_compute_frame_layout (void)
            rmask |= 1 << (23 - regno);
            saved++;
          }
-      current_frame.foffset = saved * 12 /* (TARGET_CFV4E ? 8 : 12) */;
+      current_frame.foffset = saved * TARGET_FP_REG_SIZE;
       current_frame.offset += current_frame.foffset;
     }
   current_frame.fpu_no = saved;
@@ -535,8 +540,13 @@ m68k_output_function_prologue (FILE *stream,
 
   /* On ColdFire add register save into initial stack frame setup, if possible.  */
   fsize_with_regs = current_frame.size;
-  if (TARGET_COLDFIRE && current_frame.reg_no > 2)
-    fsize_with_regs += current_frame.reg_no * 4;
+  if (TARGET_COLDFIRE)
+    {
+      if (current_frame.reg_no > 2)
+       fsize_with_regs += current_frame.reg_no * 4;
+      if (current_frame.fpu_no)
+       fsize_with_regs += current_frame.fpu_no * 8;
+    }
 
   if (frame_pointer_needed)
     {
@@ -616,22 +626,46 @@ m68k_output_function_prologue (FILE *stream,
 
   if (current_frame.fpu_mask)
     {
-      asm_fprintf (stream, (MOTOROLA
-                           ? "\tfmovm %I0x%x,-(%Rsp)\n"
-                           : "\tfmovem %I0x%x,%Rsp@-\n"),
-                  current_frame.fpu_mask);
+      if (TARGET_68881)
+       {
+         asm_fprintf (stream, (MOTOROLA
+                               ? "\tfmovm %I0x%x,-(%Rsp)\n"
+                               : "\tfmovem %I0x%x,%Rsp@-\n"),
+                      current_frame.fpu_mask);
+       }
+      else
+       {
+         int offset;
+
+         /* stack already has registers in it.  Find the offset from
+            the bottom of stack to where the FP registers go */
+         if (current_frame.reg_no <= 2)
+           offset = 0;
+         else
+           offset = current_frame.reg_no * 4;
+         if (offset)
+           asm_fprintf (stream,
+                        "\tfmovem %I0x%x,%d(%Rsp)\n",
+                        current_frame.fpu_rev_mask,
+                        offset);
+         else
+           asm_fprintf (stream,
+                        "\tfmovem %I0x%x,(%Rsp)\n",
+                        current_frame.fpu_rev_mask);
+       }
 
       if (dwarf2out_do_frame ())
        {
          char *l = (char *) dwarf2out_cfi_label ();
          int n_regs, regno;
 
-         cfa_offset += current_frame.fpu_no * 12;
+         cfa_offset += current_frame.fpu_no * TARGET_FP_REG_SIZE;
          if (! frame_pointer_needed)
            dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
          for (regno = 16, n_regs = 0; regno < 24; regno++)
            if (current_frame.fpu_mask & (1 << (regno - 16)))
-             dwarf2out_reg_save (l, regno, -cfa_offset + n_regs++ * 12);
+             dwarf2out_reg_save (l, regno, -cfa_offset
+                                 + n_regs++ * TARGET_FP_REG_SIZE);
        }
     }
 
@@ -799,8 +833,13 @@ m68k_output_function_epilogue (FILE *stream,
      after restoring registers. When the frame pointer isn't used,
      we can merge movem adjustment into frame unlinking
      made immediately after it.  */
-  if (TARGET_COLDFIRE && restore_from_sp && (current_frame.reg_no > 2))
-    fsize_with_regs += current_frame.reg_no * 4;
+  if (TARGET_COLDFIRE && restore_from_sp)
+    {
+      if (current_frame.reg_no > 2)
+       fsize_with_regs += current_frame.reg_no * 4;
+      if (current_frame.fpu_no)
+       fsize_with_regs += current_frame.fpu_no * 8;
+    }
 
   if (current_frame.offset + fsize >= 0x8000
       && ! restore_from_sp
@@ -936,7 +975,21 @@ m68k_output_function_epilogue (FILE *stream,
     {
       if (big)
        {
-         if (MOTOROLA)
+         if (TARGET_COLDFIRE)
+           {
+             if (current_frame.reg_no)
+               asm_fprintf (stream, MOTOROLA ?
+                            "\tfmovem.d %d(%Ra1),%I0x%x\n" :
+                            "\tfmovmd (%d,%Ra1),%I0x%x\n",
+                            current_frame.reg_no * 4,
+                            current_frame.fpu_rev_mask);
+             else
+               asm_fprintf (stream, MOTOROLA ?
+                            "\tfmovem.d (%Ra1),%I0x%x\n" :
+                            "\tfmovmd (%Ra1),%I0x%x\n",
+                            current_frame.fpu_rev_mask);
+           }
+         else if (MOTOROLA)
            asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n",
                         current_frame.foffset + fsize,
                         M68K_REGNAME (FRAME_POINTER_REGNUM),
@@ -949,16 +1002,34 @@ m68k_output_function_epilogue (FILE *stream,
        }
       else if (restore_from_sp)
        {
-         if (MOTOROLA)
-           asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n",
-                        current_frame.fpu_rev_mask);
-         else
-           asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n",
-                        current_frame.fpu_rev_mask);
+         if (TARGET_COLDFIRE)
+           {
+             int offset;
+
+             /* stack already has registers in it.  Find the offset from
+                the bottom of stack to where the FP registers go */
+             if (current_frame.reg_no <= 2)
+               offset = 0;
+             else
+               offset = current_frame.reg_no * 4;
+             if (offset)
+                asm_fprintf (stream,
+                            "\tfmovem %Rsp@(%wd), %I0x%x\n",
+                            offset, current_frame.fpu_rev_mask);
+             else
+                asm_fprintf (stream,
+                            "\tfmovem %Rsp@, %I0x%x\n",
+                            current_frame.fpu_rev_mask);
+           }
+          else
+                 asm_fprintf (stream, MOTOROLA ?
+                              "\tfmovm (%Rsp)+,%I0x%x\n" :
+                              "\tfmovem %Rsp@+,%I0x%x\n",
+                              current_frame.fpu_rev_mask);
        }
       else
        {
-         if (MOTOROLA)
+         if (MOTOROLA && !TARGET_COLDFIRE)
            asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n",
                         current_frame.foffset + fsize,
                         M68K_REGNAME (FRAME_POINTER_REGNUM),
@@ -2242,6 +2313,192 @@ output_move_double (rtx *operands)
   return "";
 }
 
+
+/* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a
+   new rtx with the correct mode.  */
+
+static rtx
+force_mode (enum machine_mode mode, rtx orig)
+{
+  if (mode == GET_MODE (orig))
+    return orig;
+
+  if (REGNO (orig) >= FIRST_PSEUDO_REGISTER)
+    abort ();
+
+  return gen_rtx_REG (mode, REGNO (orig));
+}
+
+static int
+fp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return reg_renumber && FP_REG_P (op);
+}
+
+/* Emit insns to move operands[1] into operands[0].
+
+   Return 1 if we have written out everything that needs to be done to
+   do the move.  Otherwise, return 0 and the caller will emit the move
+   normally.
+
+   Note SCRATCH_REG may not be in the proper mode depending on how it
+   will be used.  This routine is resposible for creating a new copy
+   of SCRATCH_REG in the proper mode.  */
+
+int
+emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
+{
+  register rtx operand0 = operands[0];
+  register rtx operand1 = operands[1];
+  register rtx tem;
+
+  if (scratch_reg
+      && reload_in_progress && GET_CODE (operand0) == REG
+      && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
+    operand0 = reg_equiv_mem[REGNO (operand0)];
+  else if (scratch_reg
+          && reload_in_progress && GET_CODE (operand0) == SUBREG
+          && GET_CODE (SUBREG_REG (operand0)) == REG
+          && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
+    {
+     /* We must not alter SUBREG_BYTE (operand0) since that would confuse
+       the code which tracks sets/uses for delete_output_reload.  */
+      rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
+                                reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
+                                SUBREG_BYTE (operand0));
+      operand0 = alter_subreg (&temp);
+    }
+
+  if (scratch_reg
+      && reload_in_progress && GET_CODE (operand1) == REG
+      && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
+    operand1 = reg_equiv_mem[REGNO (operand1)];
+  else if (scratch_reg
+          && reload_in_progress && GET_CODE (operand1) == SUBREG
+          && GET_CODE (SUBREG_REG (operand1)) == REG
+          && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
+    {
+     /* We must not alter SUBREG_BYTE (operand0) since that would confuse
+       the code which tracks sets/uses for delete_output_reload.  */
+      rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
+                                reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
+                                SUBREG_BYTE (operand1));
+      operand1 = alter_subreg (&temp);
+    }
+
+  if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
+      && ((tem = find_replacement (&XEXP (operand0, 0)))
+         != XEXP (operand0, 0)))
+    operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
+  if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
+      && ((tem = find_replacement (&XEXP (operand1, 0)))
+         != XEXP (operand1, 0)))
+    operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
+
+  /* Handle secondary reloads for loads/stores of FP registers where
+     the address is symbolic by using the scratch register */
+  if (fp_reg_operand (operand0, mode)
+      && ((GET_CODE (operand1) == MEM
+          && ! memory_address_p (DFmode, XEXP (operand1, 0)))
+         || ((GET_CODE (operand1) == SUBREG
+              && GET_CODE (XEXP (operand1, 0)) == MEM
+              && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
+      && scratch_reg)
+    {
+      if (GET_CODE (operand1) == SUBREG)
+       operand1 = XEXP (operand1, 0);
+
+      /* SCRATCH_REG will hold an address.  We want
+        it in SImode regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* D might not fit in 14 bits either; for such cases load D into
+        scratch reg.  */
+      if (!memory_address_p (Pmode, XEXP (operand1, 0)))
+       {
+         emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
+         emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
+                                                      Pmode,
+                                                      XEXP (XEXP (operand1, 0), 0),
+                                                      scratch_reg));
+       }
+      else
+       emit_move_insn (scratch_reg, XEXP (operand1, 0));
+      emit_insn (gen_rtx_SET (VOIDmode, operand0,
+                             gen_rtx_MEM (mode, scratch_reg)));
+      return 1;
+    }
+  else if (fp_reg_operand (operand1, mode)
+          && ((GET_CODE (operand0) == MEM
+               && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+              || ((GET_CODE (operand0) == SUBREG)
+                  && GET_CODE (XEXP (operand0, 0)) == MEM
+                  && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
+          && scratch_reg)
+    {
+      if (GET_CODE (operand0) == SUBREG)
+       operand0 = XEXP (operand0, 0);
+
+      /* SCRATCH_REG will hold an address and maybe the actual data.  We want
+        it in SIMODE regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* D might not fit in 14 bits either; for such cases load D into
+        scratch reg.  */
+      if (!memory_address_p (Pmode, XEXP (operand0, 0)))
+       {
+         emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
+         emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
+                                                                       0)),
+                                                      Pmode,
+                                                      XEXP (XEXP (operand0, 0),
+                                                                  0),
+                                                      scratch_reg));
+       }
+      else
+       emit_move_insn (scratch_reg, XEXP (operand0, 0));
+      emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg),
+                             operand1));
+      return 1;
+    }
+  /* Handle secondary reloads for loads of FP registers from constant
+     expressions by forcing the constant into memory.
+
+     use scratch_reg to hold the address of the memory location.
+
+     The proper fix is to change PREFERRED_RELOAD_CLASS to return
+     NO_REGS when presented with a const_int and an register class
+     containing only FP registers.  Doing so unfortunately creates
+     more problems than it solves.   Fix this for 2.5.  */
+  else if (fp_reg_operand (operand0, mode)
+          && CONSTANT_P (operand1)
+          && scratch_reg)
+    {
+      rtx xoperands[2];
+
+      /* SCRATCH_REG will hold an address and maybe the actual data.  We want
+        it in SIMODE regardless of what mode it was originally given
+        to us.  */
+      scratch_reg = force_mode (SImode, scratch_reg);
+
+      /* Force the constant into memory and put the address of the
+        memory location into scratch_reg.  */
+      xoperands[0] = scratch_reg;
+      xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);
+      emit_insn (gen_rtx_SET (mode, scratch_reg, xoperands[1]));
+
+      /* Now load the destination register.  */
+      emit_insn (gen_rtx_SET (mode, operand0,
+                             gen_rtx_MEM (mode, scratch_reg)));
+      return 1;
+    }
+
+  /* Now have insn-emit do whatever it normally does.  */
+  return 0;
+}
+
 /* Return a REG that occurs in ADDR with coefficient 1.
    ADDR can be effectively incremented by incrementing REG.  */
 
@@ -3381,8 +3638,54 @@ m68k_regno_mode_ok (int regno, enum machine_mode mode)
         smaller.  */
       if ((GET_MODE_CLASS (mode) == MODE_FLOAT
           || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
-         && GET_MODE_UNIT_SIZE (mode) <= 12)
+         && GET_MODE_UNIT_SIZE (mode) <= TARGET_FP_REG_SIZE)
        return true;
     }
   return false;
 }
+
+/* Return floating point values in a 68881 register.  This makes 68881 code
+   a little bit faster.  It also makes -msoft-float code incompatible with
+   hard-float code, so people have to be careful not to mix the two.
+   For ColdFire it was decided the ABI incopmatibility is undesirable.
+   If there is need for a hard-float ABI it is probably worth doing it
+   properly and also passing function arguments in FP registers.  */
+rtx
+m68k_libcall_value (enum machine_mode mode)
+{
+  switch (mode) {
+  case SFmode:
+  case DFmode:
+  case XFmode:
+    if (TARGET_68881)
+      return gen_rtx_REG (mode, 16);
+    break;
+  default:
+    break;
+  }
+  return gen_rtx_REG (mode, 0);
+}
+
+rtx
+m68k_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode;
+
+  mode = TYPE_MODE (valtype);
+  switch (mode) {
+  case SFmode:
+  case DFmode:
+  case XFmode:
+    if (TARGET_68881)
+      return gen_rtx_REG (mode, 16);
+    break;
+  default:
+    break;
+  }
+
+  /* If the function returns a pointer, push that into %a0 */
+  if (POINTER_TYPE_P (valtype))
+    return gen_rtx_REG (mode, 8);
+  else
+    return gen_rtx_REG (mode, 0);
+}
index 245747fcf5ce656e684662bf66d416851e9f44c9..e4d92576f3d85f72ea892c38dd73ea542791f548 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GCC for Motorola 680x0/ColdFire.
    Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -90,6 +90,10 @@ Boston, MA 02110-1301, USA.  */
          builtin_define ("__mcf5400__");       \
          builtin_define ("__mcf5407__");       \
        }                                       \
+      if (TARGET_CFV4E)                                \
+       {                                       \
+         builtin_define ("__mcfv4e__");        \
+       }                                       \
       if (TARGET_CF_HWDIV)                     \
        builtin_define ("__mcfhwdiv__");        \
       builtin_assert ("cpu=m68k");             \
@@ -112,9 +116,17 @@ Boston, MA 02110-1301, USA.  */
 #define TARGET_CPU32   (TARGET_68020 && !TARGET_BITFIELD)
 
 /* Is the target a ColdFire?  */
-#define MASK_COLDFIRE  (MASK_5200 | MASK_528x | MASK_CFV3 | MASK_CFV4)
+#define MASK_COLDFIRE \
+  (MASK_5200 | MASK_528x | MASK_CFV3 | MASK_CFV4 | MASK_CFV4E)
 #define TARGET_COLDFIRE        ((target_flags & MASK_COLDFIRE) != 0)
 
+#define TARGET_COLDFIRE_FPU    TARGET_CFV4E
+
+#define TARGET_HARD_FLOAT      (TARGET_68881 || TARGET_COLDFIRE_FPU)
+/* Size (in bytes) of FPU registers.  */
+#define TARGET_FP_REG_SIZE     (TARGET_COLDFIRE ? 8 : 12)
+
+
 #define OVERRIDE_OPTIONS   override_options()
 
 /* These are meant to be redefined in the host dependent files */
@@ -229,7 +241,7 @@ Boston, MA 02110-1301, USA.  */
 {                                                              \
   int i;                                                       \
   HARD_REG_SET x;                                              \
-  if (! TARGET_68881)                                          \
+  if (!TARGET_HARD_FLOAT)                                      \
     {                                                          \
       COPY_HARD_REG_SET (x, reg_class_contents[(int)FP_REGS]); \
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)              \
@@ -262,7 +274,7 @@ Boston, MA 02110-1301, USA.  */
   m68k_regno_mode_ok ((REGNO), (MODE))
 
 #define MODES_TIEABLE_P(MODE1, MODE2)                  \
-  (! TARGET_68881                                      \
+  (! TARGET_HARD_FLOAT                                 \
    || ((GET_MODE_CLASS (MODE1) == MODE_FLOAT           \
        || GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)        \
        == (GET_MODE_CLASS (MODE2) == MODE_FLOAT                \
@@ -336,8 +348,8 @@ extern enum reg_class regno_reg_class[];
 #define REG_CLASS_FROM_LETTER(C) \
   ((C) == 'a' ? ADDR_REGS :                    \
    ((C) == 'd' ? DATA_REGS :                   \
-    ((C) == 'f' ? (TARGET_68881 ? FP_REGS :    \
-                  NO_REGS) :                   \
+    ((C) == 'f' ? (TARGET_HARD_FLOAT ?         \
+                  FP_REGS : NO_REGS) :         \
      NO_REGS)))
 
 /* For the m68k, `I' is used for the range 1 to 8
@@ -407,7 +419,7 @@ extern enum reg_class regno_reg_class[];
    ? DATA_REGS                                 \
    : (GET_CODE (X) == CONST_DOUBLE                                     \
       && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT)                  \
-   ? (TARGET_68881 && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS)   \
+   ? (TARGET_HARD_FLOAT && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS) \
       ? FP_REGS : NO_REGS)                                             \
    : (TARGET_PCREL                             \
       && (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
@@ -752,16 +764,34 @@ __transfer_from_trampoline ()                                     \
        && GET_CODE (XEXP (X, 1)) == CONST_INT          \
        && (INTVAL (XEXP (X, 1)) == 2                   \
            || INTVAL (XEXP (X, 1)) == 4                \
-           || (INTVAL (XEXP (X, 1)) == 8 && !TARGET_COLDFIRE))))
+           || (INTVAL (XEXP (X, 1)) == 8               \
+               && (TARGET_CFV4E || !TARGET_COLDFIRE)))))
+
+/* Coldfire FPU only accepts addressing modes 2-5 */
+#define GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS(MODE, X, ADDR)           \
+{ if (LEGITIMATE_BASE_REG_P (X)                                                \
+      || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC)                \
+          && LEGITIMATE_BASE_REG_P (XEXP (X, 0)))                      \
+      || ((GET_CODE (X) == PLUS) && LEGITIMATE_BASE_REG_P (XEXP (X, 0))        \
+          && (GET_CODE (XEXP (X, 1)) == CONST_INT)                     \
+          && ((((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))))        \
+  goto ADDR;}
 
 /* If pic, we accept INDEX+LABEL, which is what do_tablejump makes.  */
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                                \
-{ GO_IF_NONINDEXED_ADDRESS (X, ADDR);                                  \
-  GO_IF_INDEXED_ADDRESS (X, ADDR);                                     \
-  if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS     \
-      && LEGITIMATE_INDEX_P (XEXP (X, 0))                              \
-      && GET_CODE (XEXP (X, 1)) == LABEL_REF)                          \
-    goto ADDR; }
+{ if (TARGET_COLDFIRE_FPU && (GET_MODE_CLASS (MODE) == MODE_FLOAT))    \
+    {                                                                  \
+      GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS (MODE, X, ADDR);           \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      GO_IF_NONINDEXED_ADDRESS (X, ADDR);                              \
+      GO_IF_INDEXED_ADDRESS (X, ADDR);                                 \
+      if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS \
+         && LEGITIMATE_INDEX_P (XEXP (X, 0))                           \
+         && GET_CODE (XEXP (X, 1)) == LABEL_REF)                       \
+       goto ADDR;                                                      \
+    }}
 
 /* Don't call memory_address_noforce for the address to fetch
    the switch offset.  This address is ok as it stands (see above),
@@ -783,7 +813,9 @@ __transfer_from_trampoline ()                                       \
        { COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);} \
       if (ch && GET_CODE (XEXP (X, 1)) == REG                          \
          && GET_CODE (XEXP (X, 0)) == REG)                             \
-       goto WIN;                                                       \
+       { if (TARGET_CFV4E && GET_MODE_CLASS (MODE) == MODE_FLOAT)      \
+           { COPY_ONCE (X); X = force_operand (X, 0);}                 \
+         goto WIN; }                                                   \
       if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); }             \
       if (GET_CODE (XEXP (X, 0)) == REG                                        \
               || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND                \
@@ -794,6 +826,9 @@ __transfer_from_trampoline ()                                       \
          emit_move_insn (temp, val);                                   \
          COPY_ONCE (X);                                                \
          XEXP (X, 1) = temp;                                           \
+         if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+             && GET_CODE (XEXP (X, 0)) == REG)                         \
+           X = force_operand (X, 0);                                   \
          goto WIN; }                                                   \
       else if (GET_CODE (XEXP (X, 1)) == REG                           \
               || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND                \
@@ -804,6 +839,9 @@ __transfer_from_trampoline ()                                       \
          emit_move_insn (temp, val);                                   \
          COPY_ONCE (X);                                                \
          XEXP (X, 0) = temp;                                           \
+         if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+             && GET_CODE (XEXP (X, 1)) == REG)                         \
+           X = force_operand (X, 0);                                   \
          goto WIN; }}}
 
 /* On the 68000, only predecrement and postincrement address depend thus
index 11c5ab04a9c8c4ff57933e167adc16791c304b3a..4c24756770cfbb689035ec3c6335b0e4be46f74e 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for GNU compiler, Motorola 68000 Version
 ;;  Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001,
-;;  2002, 2003, 2004, 2005
+;;  2002, 2003, 2004, 2005, 2006
 ;;  Free Software Foundation, Inc.
 
 ;; This file is part of GCC.
@@ -46,7 +46,7 @@
 ;;- Operand classes for the register allocator:
 ;;- 'a' one of the address registers can be used.
 ;;- 'd' one of the data registers can be used.
-;;- 'f' one of the m68881 registers can be used
+;;- 'f' one of the m68881/fpu registers can be used
 ;;- 'r' either a data or an address register can be used.
 
 ;;- Immediate Floating point operator constraints
 
 (include "predicates.md")
 \f
+;; Mode macros for floating point operations.
+;; Valid floating point modes
+(define_mode_macro FP [SF DF (XF "TARGET_68881")])
+;; Mnemonic infix to round result
+(define_mode_attr round [(SF "%$") (DF "%&") (XF "")])
+;; Mnemonic infix to round result for mul or div instruction
+(define_mode_attr round_mul [(SF "sgl") (DF "%&") (XF "")])
+;; Suffix specifiying source operand format
+(define_mode_attr prec [(SF "s") (DF "d") (XF "x")])
+;; Allowable D registers
+(define_mode_attr dreg [(SF "d") (DF "") (XF "")])
+;; Allowable 68881 constant constraints
+(define_mode_attr const [(SF "F") (DF "G") (XF "")])
+\f
 (define_insn ""
   [(set (match_operand:DF 0 "push_operand" "=m")
        (match_operand:DF 1 "general_operand" "ro<>fyE"))]
   ""
   "tst%.b %0")
 
-(define_expand "tstsf"
+(define_expand "tst<mode>"
   [(set (cc0)
-       (match_operand:SF 0 "general_operand" ""))]
-  "TARGET_68881"
+       (match_operand:FP 0 "general_operand" ""))]
+  "TARGET_HARD_FLOAT"
 {
   m68k_last_compare_had_fp_operands = 1;
 })
 
-(define_insn ""
+(define_insn "tst<mode>_68881"
   [(set (cc0)
-       (match_operand:SF 0 "general_operand" "fdm"))]
+       (match_operand:FP 0 "general_operand" "f<FP:dreg>m"))]
   "TARGET_68881"
 {
   cc_status.flags = CC_IN_68881;
   if (FP_REG_P (operands[0]))
     return "ftst%.x %0";
-  return "ftst%.s %0";
-})
-
-(define_expand "tstdf"
-  [(set (cc0)
-       (match_operand:DF 0 "general_operand" ""))]
-  "TARGET_68881"
-{
-  m68k_last_compare_had_fp_operands = 1;
+  return "ftst%.<FP:prec> %0";
 })
 
-(define_insn ""
+(define_insn "tst<mode>_cf"
   [(set (cc0)
-       (match_operand:DF 0 "general_operand" "fm"))]
-  "TARGET_68881"
+       (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U"))]
+  "TARGET_COLDFIRE_FPU"
 {
   cc_status.flags = CC_IN_68881;
   if (FP_REG_P (operands[0]))
-    return "ftst%.x %0";
-  return "ftst%.d %0";
+    return "ftst%.d %0";
+  return "ftst%.<FP:prec> %0";
 })
+
 \f
 ;; compare instructions.
 
   return "cmp%.b %d1,%d0";
 })
 
-(define_expand "cmpdf"
+(define_expand "cmp<mode>"
   [(set (cc0)
-       (compare (match_operand:DF 0 "general_operand" "")
-                (match_operand:DF 1 "general_operand" "")))]
-  "TARGET_68881"
+       (compare (match_operand:FP 0 "general_operand" "")
+                (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
 {
   m68k_last_compare_had_fp_operands = 1;
+  if (TARGET_COLDFIRE && !reload_completed)
+    operands[1] = force_reg (<MODE>mode, operands[1]);
 })
 
-(define_insn ""
+(define_insn "cmp<mode>_68881"
   [(set (cc0)
-       (compare (match_operand:DF 0 "general_operand" "f,mG")
-                (match_operand:DF 1 "general_operand" "fmG,f")))]
+       (compare (match_operand:FP 0 "general_operand" "f,m<FP:const>")
+                (match_operand:FP 1 "general_operand" "f<FP:dreg>m<FP:const>,f")))]
   "TARGET_68881"
 {
   cc_status.flags = CC_IN_68881;
-  if (REG_P (operands[0]))
+  if (FP_REG_P (operands[0]))
     {
-      if (REG_P (operands[1]))
+      if (FP_REG_P (operands[1]))
        return "fcmp%.x %1,%0";
       else
-        return "fcmp%.d %f1,%0";
+        return "fcmp%.<FP:prec> %f1,%0";
     }
   cc_status.flags |= CC_REVERSED;
-  return "fcmp%.d %f0,%1";
+  return "fcmp%.<FP:prec> %f0,%1";
 })
 
-(define_expand "cmpsf"
- [(set (cc0)
-       (compare (match_operand:SF 0 "general_operand" "")
-               (match_operand:SF 1 "general_operand" "")))]
- "TARGET_68881"
-{
-  m68k_last_compare_had_fp_operands = 1;
-})
-
-(define_insn ""
+(define_insn "cmp<mode>_cf"
   [(set (cc0)
-       (compare (match_operand:SF 0 "general_operand" "f,mdG")
-                (match_operand:SF 1 "general_operand" "fmdG,f")))]
-  "TARGET_68881"
+       (compare (match_operand:FP 0 "general_operand" "f,<FP:dreg><Q>U")
+                (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U,f")))]
+  "TARGET_COLDFIRE_FPU"
 {
   cc_status.flags = CC_IN_68881;
   if (FP_REG_P (operands[0]))
     {
       if (FP_REG_P (operands[1]))
-       return "fcmp%.x %1,%0";
+       return "fcmp%.d %1,%0";
       else
-        return "fcmp%.s %f1,%0";
+       return "fcmp%.<FP:prec> %f1,%0";
     }
   cc_status.flags |= CC_REVERSED;
-  return "fcmp%.s %f0,%1";
+  return "fcmp%.<FP:prec> %f0,%1";
 })
 \f
 ;; Recognizers for btst instructions.
   "!TARGET_COLDFIRE"
   "")
 
+(define_expand "reload_insf"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
+        (match_operand:SF 1 "general_operand" "mf"))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (emit_move_sequence (operands, SFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves. */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "reload_outsf"
+  [(set (match_operand:SF 0 "general_operand" "")
+        (match_operand:SF 1 "register_operand" "f"))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (emit_move_sequence (operands, SFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves. */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+})
+
 (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
        (match_operand:SF 1 "general_operand" ""))]
   return "move%.l %1,%0";
 })
 
-(define_insn ""
+(define_insn "movsf_cf_soft"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,g")
        (match_operand:SF 1 "general_operand" "g,r"))]
-  "TARGET_COLDFIRE"
+  "TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
 {
   return "move%.l %1,%0";
 })
 
+(define_insn "movsf_cf_hard"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>U, f,    f,mr,f,r<Q>,f
+,m")
+        (match_operand:SF 1 "general_operand"      " f,     r<Q>U,f,rm,F,F,   m
+,f"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (which_alternative == 4 || which_alternative == 5) {
+    rtx xoperands[2];
+    REAL_VALUE_TYPE r;
+    long l;
+    REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+    REAL_VALUE_TO_TARGET_SINGLE (r, l);
+    xoperands[0] = operands[0];
+    xoperands[1] = GEN_INT (l);
+    if (which_alternative == 5) {
+      if (l == 0) {
+        if (ADDRESS_REG_P (xoperands[0]))
+          output_asm_insn ("sub%.l %0,%0", xoperands);
+        else
+          output_asm_insn ("clr%.l %0", xoperands);
+      } else
+        if (GET_CODE (operands[0]) == MEM
+            && symbolic_operand (XEXP (operands[0], 0), SImode))
+          output_asm_insn ("move%.l %1,%-;move%.l %+,%0", xoperands);
+        else
+          output_asm_insn ("move%.l %1,%0", xoperands);
+      return "";
+    }
+    if (l != 0)
+      output_asm_insn ("move%.l %1,%-;fsmove%.s %+,%0", xoperands);
+    else
+      output_asm_insn ("clr%.l %-;fsmove%.s %+,%0", xoperands);
+    return "";
+  }
+  if (FP_REG_P (operands[0]))
+    {
+      if (ADDRESS_REG_P (operands[1]))
+        return "move%.l %1,%-;f%$smove%.s %+,%0";
+      if (FP_REG_P (operands[1]))
+        return "f%$move%.d %1,%0";
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+        return output_move_const_single (operands);
+      return "f%$move%.s %f1,%0";
+    }
+  if (FP_REG_P (operands[1]))
+    {
+      if (ADDRESS_REG_P (operands[0]))
+        return "fmove%.s %1,%-;move%.l %+,%0";
+      return "fmove%.s %f1,%0";
+    }
+  if (operands[1] == CONST0_RTX (SFmode))
+    {
+      if (ADDRESS_REG_P (operands[0]))
+       return "sub%.l %0,%0";
+      return "clr%.l %0";
+    }
+  return "move%.l %1,%0";
+})
+
+(define_expand "reload_indf"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
+        (match_operand:DF 1 "general_operand" "mf"))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (emit_move_sequence (operands, DFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves. */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+})
+
+(define_expand "reload_outdf"
+  [(set (match_operand:DF 0 "general_operand" "")
+        (match_operand:DF 1 "register_operand" "f"))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (emit_move_sequence (operands, DFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves. */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+})
+
 (define_expand "movdf"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
   ""
-  "")
+{
+  if (TARGET_COLDFIRE_FPU)
+    if (emit_move_sequence (operands, DFmode, 0))
+      DONE;
+})
 
 (define_insn ""
   [(set (match_operand:DF 0 "nonimmediate_operand" "=rm,rf,rf,&rof<>")
   return output_move_double (operands);
 })
 
-(define_insn ""
+(define_insn "movdf_cf_soft"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
        (match_operand:DF 1 "general_operand" "g,r"))]
-  "TARGET_COLDFIRE"
+  "TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
 {
   return output_move_double (operands);
 })
 
+(define_insn "movdf_cf_hard"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,    <Q>U,r,f,r,r,m,f")
+        (match_operand:DF 1 "general_operand"      " f<Q>U,f,   f,r,r,m,r,E"))]
+  "TARGET_COLDFIRE_FPU"
+{
+  rtx xoperands[3];
+  REAL_VALUE_TYPE r;
+  long l[2];
+
+  switch (which_alternative)
+    {
+    default:
+      return "fmove%.d %1,%0";
+    case 2:
+      return "fmove%.d %1,%-;move%.l %+,%0;move%.l %+,%R0";
+    case 3:
+      return "move%.l %R1,%-;move%.l %1,%-;f%&move%.d %+,%0";
+    case 4:
+      return "move%.l %1,%0;move%.l %R1,%R0";
+    case 5: case 6:
+      return output_move_double (operands);
+    case 7:
+      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+      REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+      xoperands[0] = operands[0];
+      xoperands[1] = GEN_INT (l[0]);
+      xoperands[2] = GEN_INT (l[1]);
+      if (operands[1] == CONST0_RTX (DFmode))
+       output_asm_insn ("clr%.l %-;clr%.l %-;fdmove%.d %+,%0",
+                       xoperands);
+      else
+       if (l[1] == 0)
+         output_asm_insn ("clr%.l %-;move%.l %1,%-;fdmove%.d %+,%0",
+                         xoperands);
+       else
+         output_asm_insn ("move%.l %2,%-;move%.l %1,%-;fdmove%.d %+,%0",
+                         xoperands);
+      return "";
+    }
+})
+
 ;; ??? The XFmode patterns are schizophrenic about whether constants are
 ;; allowed.  Most but not all have predicates and constraint that disallow
 ;; constants.  Most but not all have output templates that handle constants.
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (float_extend:DF
         (match_operand:SF 1 "general_operand" "")))]
-  "TARGET_68881"
+  "TARGET_HARD_FLOAT"
   "")
 
 (define_insn ""
   return "fmove%.d %f1,%0";
 })
 
+(define_insn "extendsfdf2_cf"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
+       (float_extend:DF
+        (match_operand:SF 1 "general_operand" "f,<Q>U")))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
+    {
+      if (REGNO (operands[0]) == REGNO (operands[1]))
+       {
+         /* Extending float to double in an fp-reg is a no-op.
+            NOTICE_UPDATE_CC has already assumed that the
+            cc will be set.  So cancel what it did.  */
+         cc_status = cc_prev_status;
+         return "";
+       }
+      return "f%&move%.d %1,%0";
+    }
+  return "f%&move%.s %f1,%0";
+})
+
 ;; This cannot output into an f-reg because there is no way to be
 ;; sure of truncating in that case.
 (define_expand "truncdfsf2"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
        (float_truncate:SF
          (match_operand:DF 1 "general_operand" "")))]
-  "TARGET_68881"
+  "TARGET_HARD_FLOAT"
   "")
 
 ;; On the '040 we can truncate in a register accurately and easily.
   return "f%$move%.d %f1,%0";
 })
 
+(define_insn "truncdfsf2_cf"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,d<Q>U")
+       (float_truncate:SF
+         (match_operand:DF 1 "general_operand" "<Q>U,f")))]
+  "TARGET_COLDFIRE_FPU"
+  "@
+  f%$move%.d %1,%0
+  fmove%.s %1,%0")
+
 (define_insn ""
   [(set (match_operand:SF 0 "nonimmediate_operand" "=dm")
        (float_truncate:SF
 ;; will be recognized as SImode (which is always valid)
 ;; rather than as QImode or HImode.
 
-(define_expand "floatsisf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (float:SF (match_operand:SI 1 "general_operand" "")))]
-  "TARGET_68881"
+(define_expand "floatsi<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (float:FP (match_operand:SI 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
   "")
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (float:SF (match_operand:SI 1 "general_operand" "dmi")))]
+(define_insn "floatsi<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (float:FP (match_operand:SI 1 "general_operand" "dmi")))]
   "TARGET_68881"
-  "f%$move%.l %1,%0")
+  "f<FP:round>move%.l %1,%0")
 
-(define_expand "floatsidf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (float:DF (match_operand:SI 1 "general_operand" "")))]
-  "TARGET_68881"
-  "")
+(define_insn "floatsi<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (float:FP (match_operand:SI 1 "general_operand" "d<Q>U")))]
+  "TARGET_COLDFIRE_FPU"
+  "f<FP:prec>move%.l %1,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (float:DF (match_operand:SI 1 "general_operand" "dmi")))]
-  "TARGET_68881"
-  "f%&move%.l %1,%0")
 
-(define_insn "floathisf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (float:SF (match_operand:HI 1 "general_operand" "dmn")))]
-  "TARGET_68881"
-  "f%$move%.w %1,%0")
+(define_expand "floathi<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (float:FP (match_operand:HI 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
 
-(define_insn "floathidf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (float:DF (match_operand:HI 1 "general_operand" "dmn")))]
+(define_insn "floathi<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (float:FP (match_operand:HI 1 "general_operand" "dmn")))]
   "TARGET_68881"
   "fmove%.w %1,%0")
 
-(define_insn "floatqisf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (float:SF (match_operand:QI 1 "general_operand" "dmn")))]
+(define_insn "floathi<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+        (float:FP (match_operand:HI 1 "general_operand" "d<Q>U")))]
+  "TARGET_COLDFIRE_FPU"
+  "fmove%.w %1,%0")
+
+
+(define_expand "floatqi<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (float:FP (match_operand:QI 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
+
+(define_insn "floatqi<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (float:FP (match_operand:QI 1 "general_operand" "dmn")))]
   "TARGET_68881"
   "fmove%.b %1,%0")
 
-(define_insn "floatqidf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (float:DF (match_operand:QI 1 "general_operand" "dmn")))]
-  "TARGET_68881"
-  "f%&move%.b %1,%0")
+(define_insn "floatqi<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (float:FP (match_operand:QI 1 "general_operand" "d<Q>U")))]
+  "TARGET_COLDFIRE_FPU"
+  "fmove%.b %1,%0")
+
 
 ;; New routines to convert floating-point values to integers
 ;; to be used on the '040.  These should be faster than trapping
 ;; Convert a float to a float whose value is an integer.
 ;; This is the first stage of converting it to an integer type.
 
-(define_insn "ftruncdf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
+(define_expand "ftrunc<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (fix:FP (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT && !TARGET_68040"
+  "")
+
+(define_insn "ftrunc<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (fix:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m")))]
   "TARGET_68881 && !TARGET_68040"
 {
   if (FP_REG_P (operands[1]))
     return "fintrz%.x %f1,%0";
-  return "fintrz%.d %f1,%0";
+  return "fintrz%.<FP:prec> %f1,%0";
 })
 
-(define_insn "ftruncsf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
-  "TARGET_68881 && !TARGET_68040"
+(define_insn "ftrunc<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+        (fix:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U")))]
+  "TARGET_COLDFIRE_FPU"
 {
   if (FP_REG_P (operands[1]))
-    return "fintrz%.x %f1,%0";
-  return "fintrz%.s %f1,%0";
+    return "fintrz%.d %f1,%0";
+  return "fintrz%.<FP:prec> %f1,%0";
 })
 
 ;; Convert a float whose value is an integer
 ;; to an actual integer.  Second stage of converting float to integer type.
-(define_insn "fixsfqi2"
+(define_expand "fix<mode>qi2"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
+       (fix:QI (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
+
+(define_insn "fix<mode>qi2_68881"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-       (fix:QI (match_operand:SF 1 "general_operand" "f")))]
+       (fix:QI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_68881"
   "fmove%.b %1,%0")
 
-(define_insn "fixsfhi2"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
-       (fix:HI (match_operand:SF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.w %1,%0")
-
-(define_insn "fixsfsi2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
-       (fix:SI (match_operand:SF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.l %1,%0")
-
-(define_insn "fixdfqi2"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-       (fix:QI (match_operand:DF 1 "general_operand" "f")))]
-  "TARGET_68881"
+(define_insn "fix<mode>qi2_cf"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>U")
+       (fix:QI (match_operand:FP 1 "general_operand" "f")))]
+  "TARGET_COLDFIRE_FPU"
   "fmove%.b %1,%0")
 
-(define_insn "fixdfhi2"
+(define_expand "fix<mode>hi2"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
+       (fix:HI (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
+
+(define_insn "fix<mode>hi2_68881"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
-       (fix:HI (match_operand:DF 1 "general_operand" "f")))]
+       (fix:HI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_68881"
   "fmove%.w %1,%0")
 
-(define_insn "fixdfsi2"
+(define_insn "fix<mode>hi2_cf"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d<Q>U")
+       (fix:HI (match_operand:FP 1 "general_operand" "f")))]
+  "TARGET_COLDFIRE_FPU"
+  "fmove%.w %1,%0")
+
+(define_expand "fix<mode>si2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+       (fix:SI (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
+
+(define_insn "fix<mode>si2_68881"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
-       (fix:SI (match_operand:DF 1 "general_operand" "f")))]
+       (fix:SI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_68881"
   "fmove%.l %1,%0")
+
+(define_insn "fix<mode>si2_cf"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d<Q>U")
+       (fix:SI (match_operand:FP 1 "general_operand" "f")))]
+  "TARGET_COLDFIRE_FPU"
+  "fmove%.l %1,%0")
+
 \f
 ;; add instructions
 
   return "add%.b %1,%0";
 })
 
-(define_expand "adddf3"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (plus:DF (match_operand:DF 1 "general_operand" "")
-                (match_operand:DF 2 "general_operand" "")))]
-  "TARGET_68881"
+(define_expand "add<mode>3"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (plus:FP (match_operand:FP 1 "general_operand" "")
+                (match_operand:FP 2 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
   "")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (plus:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "add<mode>3_floatsi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (plus:FP (float:FP (match_operand:SI 2 "general_operand" "dmi"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&add%.l %2,%0")
+  "f<FP:round>add%.l %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (plus:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "add<mode>3_floathi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (plus:FP (float:FP (match_operand:HI 2 "general_operand" "dmn"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&add%.w %2,%0")
+  "f<FP:round>add%.w %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (plus:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "add<mode>3_floatqi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (plus:FP (float:FP (match_operand:QI 2 "general_operand" "dmn"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&add%.b %2,%0")
+  "f<FP:round>add%.b %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (plus:DF (match_operand:DF 1 "general_operand" "%0")
-                (match_operand:DF 2 "general_operand" "fmG")))]
+(define_insn "add<mode>3_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (plus:FP (match_operand:FP 1 "general_operand" "%0")
+                (match_operand:FP 2 "general_operand" "f<FP:dreg>m<FP:const>")))]
   "TARGET_68881"
 {
-  if (REG_P (operands[2]))
-    return "f%&add%.x %2,%0";
-  return "f%&add%.d %f2,%0";
+  if (FP_REG_P (operands[2]))
+    return "f<FP:round>add%.x %2,%0";
+  return "f<FP:round>add%.<FP:prec> %f2,%0";
 })
 
-(define_expand "addsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (plus:SF (match_operand:SF 1 "general_operand" "")
-                (match_operand:SF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (plus:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-  "f%$add%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (plus:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-  "f%$add%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (plus:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-  "f%$add%.b %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (plus:SF (match_operand:SF 1 "general_operand" "%0")
-                (match_operand:SF 2 "general_operand" "fdmF")))]
-  "TARGET_68881"
+(define_insn "add<mode>3_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (plus:FP (match_operand:FP 1 "general_operand" "%0")
+                (match_operand:FP 2 "general_operand" "f<FP:dreg><Q>U")))]
+  "TARGET_COLDFIRE_FPU"
 {
-  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
-    return "f%$add%.x %2,%0";
-  return "f%$add%.s %f2,%0";
+  if (FP_REG_P (operands[2]))
+    return "f<FP:round>add%.d %2,%0";
+  return "f<FP:round>add%.<FP:prec> %2,%0";
 })
 \f
 ;; subtract instructions
   "!TARGET_COLDFIRE"
   "sub%.b %1,%0")
 
-(define_expand "subdf3"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (minus:DF (match_operand:DF 1 "general_operand" "")
-                 (match_operand:DF 2 "general_operand" "")))]
-  "TARGET_68881"
+(define_expand "sub<mode>3"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (minus:FP (match_operand:FP 1 "general_operand" "")
+                 (match_operand:FP 2 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
   "")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (minus:DF (match_operand:DF 1 "general_operand" "0")
-                 (float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
+(define_insn "sub<mode>3_floatsi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (minus:FP (match_operand:FP 1 "general_operand" "0")
+                 (float:FP (match_operand:SI 2 "general_operand" "dmi"))))]
   "TARGET_68881"
-  "f%&sub%.l %2,%0")
+  "f<FP:round>sub%.l %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (minus:DF (match_operand:DF 1 "general_operand" "0")
-                 (float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
+(define_insn "sub<mode>3_floathi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (minus:FP (match_operand:FP 1 "general_operand" "0")
+                 (float:FP (match_operand:HI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
-  "f%&sub%.w %2,%0")
+  "f<FP:round>sub%.w %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (minus:DF (match_operand:DF 1 "general_operand" "0")
-                 (float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
+(define_insn "sub<mode>3_floatqi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (minus:FP (match_operand:FP 1 "general_operand" "0")
+                 (float:FP (match_operand:QI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
-  "f%&sub%.b %2,%0")
+  "f<FP:round>sub%.b %2,%0")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (minus:DF (match_operand:DF 1 "general_operand" "0")
-                 (match_operand:DF 2 "general_operand" "fmG")))]
+(define_insn "sub<mode>3_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (minus:FP (match_operand:FP 1 "general_operand" "0")
+                 (match_operand:FP 2 "general_operand" "f<FP:dreg>m<FP:const>")))]
   "TARGET_68881"
 {
-  if (REG_P (operands[2]))
-    return "f%&sub%.x %2,%0";
-  return "f%&sub%.d %f2,%0";
+  if (FP_REG_P (operands[2]))
+    return "f<FP:round>sub%.x %2,%0";
+  return "f<FP:round>sub%.<FP:prec> %f2,%0";
 })
 
-(define_expand "subsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (minus:SF (match_operand:SF 1 "general_operand" "")
-                 (match_operand:SF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (minus:SF (match_operand:SF 1 "general_operand" "0")
-                 (float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
-  "TARGET_68881"
-  "f%$sub%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (minus:SF (match_operand:SF 1 "general_operand" "0")
-                 (float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "f%$sub%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (minus:SF (match_operand:SF 1 "general_operand" "0")
-                 (float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "f%$sub%.b %2,%0")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (minus:SF (match_operand:SF 1 "general_operand" "0")
-                 (match_operand:SF 2 "general_operand" "fdmF")))]
-  "TARGET_68881"
+(define_insn "sub<mode>3_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+        (minus:FP (match_operand:FP 1 "general_operand" "0")
+                  (match_operand:FP 2 "general_operand" "f<FP:dreg><Q>U")))]
+  "TARGET_COLDFIRE_FPU"
 {
-  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
-    return "f%$sub%.x %2,%0";
-  return "f%$sub%.s %f2,%0";
+  if (FP_REG_P (operands[2]))
+    return "f<FP:round>sub%.d %2,%0";
+  return "f<FP:round>sub%.<FP:prec> %2,%0";
 })
 \f
 ;; multiply instructions
   "TARGET_68020 && !TARGET_68060 && !TARGET_COLDFIRE"
   "muls%.l %3,%0:%1")
 
-(define_expand "muldf3"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (mult:DF (match_operand:DF 1 "general_operand" "")
-                (match_operand:DF 2 "general_operand" "")))]
-  "TARGET_68881"
+(define_expand "mul<mode>3"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (mult:FP (match_operand:FP 1 "general_operand" "")
+                (match_operand:FP 2 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
   "")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (mult:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "mul<mode>3_floatsi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (mult:FP (float:FP (match_operand:SI 2 "general_operand" "dmi"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&mul%.l %2,%0")
+{
+  return TARGET_68040_ONLY
+        ? "f<FP:round>mul%.l %2,%0"
+        : "f<FP:round_mul>mul%.l %2,%0";
+})
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (mult:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "mul<mode>3_floathi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (mult:FP (float:FP (match_operand:HI 2 "general_operand" "dmn"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&mul%.w %2,%0")
+{
+  return TARGET_68040_ONLY
+        ? "f<FP:round>mul%.w %2,%0"
+        : "f<FP:round_mul>mul%.w %2,%0";
+})
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (mult:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:DF 1 "general_operand" "0")))]
+(define_insn "mul<mode>3_floatqi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (mult:FP (float:FP (match_operand:QI 2 "general_operand" "dmn"))
+                (match_operand:FP 1 "general_operand" "0")))]
   "TARGET_68881"
-  "f%&mul%.b %2,%0")
+{
+  return TARGET_68040_ONLY
+        ? "f<FP:round>mul%.b %2,%0"
+        : "f<FP:round_mul>mul%.b %2,%0";
+})
 
-(define_insn ""
+(define_insn "muldf_68881"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
        (mult:DF (match_operand:DF 1 "general_operand" "%0")
                 (match_operand:DF 2 "general_operand" "fmG")))]
   return "f%&mul%.d %f2,%0";
 })
 
-(define_expand "mulsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (mult:SF (match_operand:SF 1 "general_operand" "")
-                (match_operand:SF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "")
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (mult:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-{
-  return (TARGET_68040_ONLY
-          ? "fsmul%.l %2,%0"
-          : "fsglmul%.l %2,%0");
-})
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (mult:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-{
-  return (TARGET_68040_ONLY
-          ? "fsmul%.w %2,%0"
-          : "fsglmul%.w %2,%0");
-})
-
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (mult:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:SF 1 "general_operand" "0")))]
-  "TARGET_68881"
-{
-  return (TARGET_68040_ONLY
-          ? "fsmul%.b %2,%0"
-          : "fsglmul%.b %2,%0");
-})
-
-(define_insn ""
+(define_insn "mulsf_68881"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
        (mult:SF (match_operand:SF 1 "general_operand" "%0")
                 (match_operand:SF 2 "general_operand" "fdmF")))]
   "TARGET_68881"
 {
-  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+  if (FP_REG_P (operands[2]))
     return (TARGET_68040_ONLY
            ? "fsmul%.x %2,%0"
            : "fsglmul%.x %2,%0");
          ? "fsmul%.s %f2,%0"
          : "fsglmul%.s %f2,%0");
 })
-\f
-;; divide instructions
-
-(define_expand "divdf3"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
-       (div:DF (match_operand:DF 1 "general_operand" "")
-               (match_operand:DF 2 "general_operand" "")))]
-  "TARGET_68881"
-  "")
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (div:DF (match_operand:DF 1 "general_operand" "0")
-               (float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
-  "TARGET_68881"
-  "f%&div%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (div:DF (match_operand:DF 1 "general_operand" "0")
-               (float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "f%&div%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (div:DF (match_operand:DF 1 "general_operand" "0")
-               (float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
+(define_insn "mulxf3_68881"
+  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
+       (mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
+                (match_operand:XF 2 "nonimmediate_operand" "fm")))]
   "TARGET_68881"
-  "f%&div%.b %2,%0")
+{
+  return "fmul%.x %f2,%0";
+})
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (div:DF (match_operand:DF 1 "general_operand" "0")
-               (match_operand:DF 2 "general_operand" "fmG")))]
-  "TARGET_68881"
+(define_insn "fmul<mode>3_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (mult:FP (match_operand:FP 1 "general_operand" "%0")
+                (match_operand:FP 2 "general_operand" "f<Q>U<FP:dreg>")))]
+  "TARGET_COLDFIRE_FPU"
 {
-  if (REG_P (operands[2]))
-    return "f%&div%.x %2,%0";
-  return "f%&div%.d %f2,%0";
+  if (FP_REG_P (operands[2]))
+    return "f<FP:prec>mul%.d %2,%0";
+  return "f<FP:prec>mul%.<FP:prec> %2,%0";
 })
+\f
+;; divide instructions
 
-(define_expand "divsf3"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "")
-       (div:SF (match_operand:SF 1 "general_operand" "")
-               (match_operand:SF 2 "general_operand" "")))]
-  "TARGET_68881"
+(define_expand "div<mode>3"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (div:FP (match_operand:FP 1 "general_operand" "")
+               (match_operand:FP 2 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
   "")
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (div:SF (match_operand:SF 1 "general_operand" "0")
-               (float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
+(define_insn "div<mode>3_floatsi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (div:FP (match_operand:FP 1 "general_operand" "0")
+               (float:FP (match_operand:SI 2 "general_operand" "dmi"))))]
   "TARGET_68881"
 {
-  return (TARGET_68040_ONLY
-          ? "fsdiv%.l %2,%0"
-          : "fsgldiv%.l %2,%0");
+  return TARGET_68040_ONLY
+        ? "f<FP:round>div%.l %2,%0"
+        : "f<FP:round_mul>div%.l %2,%0";
 })
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (div:SF (match_operand:SF 1 "general_operand" "0")
-               (float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
+(define_insn "div<mode>3_floathi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (div:FP (match_operand:FP 1 "general_operand" "0")
+               (float:FP (match_operand:HI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
 {
-  return (TARGET_68040_ONLY
-          ? "fsdiv%.w %2,%0"
-          : "fsgldiv%.w %2,%0");
+  return TARGET_68040_ONLY
+        ? "f<FP:round>div%.w %2,%0"
+        : "f<FP:round_mul>div%.w %2,%0";
 })
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (div:SF (match_operand:SF 1 "general_operand" "0")
-               (float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
+(define_insn "div<mode>3_floatqi_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (div:FP (match_operand:FP 1 "general_operand" "0")
+               (float:FP (match_operand:QI 2 "general_operand" "dmn"))))]
   "TARGET_68881"
 {
-  return (TARGET_68040_ONLY
-          ? "fsdiv%.b %2,%0"
-          : "fsgldiv%.b %2,%0");
+  return TARGET_68040_ONLY
+        ? "f<FP:round>div%.b %2,%0"
+        : "f<FP:round_mul>div%.b %2,%0";
 })
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (div:SF (match_operand:SF 1 "general_operand" "0")
-               (match_operand:SF 2 "general_operand" "fdmF")))]
+(define_insn "div<mode>3_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (div:FP (match_operand:FP 1 "general_operand" "0")
+               (match_operand:FP 2 "general_operand" "f<FP:dreg>m<FP:const>")))]
   "TARGET_68881"
 {
-  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+  if (FP_REG_P (operands[2]))
     return (TARGET_68040_ONLY
-           ? "fsdiv%.x %2,%0"
-           : "fsgldiv%.x %2,%0");
+           ? "f<FP:round>div%.x %2,%0"
+           : "f<FP:round_mul>div%.x %2,%0");
   return (TARGET_68040_ONLY
-         ? "fsdiv%.s %f2,%0"
-         : "fsgldiv%.s %f2,%0");
+         ? "f<FP:round>div%.<FP:prec> %f2,%0"
+         : "f<FP:round_mul>div%.<FP:prec> %f2,%0");
+})
+
+(define_insn "div<mode>3_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (div:FP (match_operand:FP 1 "general_operand" "0")
+               (match_operand:FP 2 "general_operand" "f<Q>U<FP:dreg>")))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (FP_REG_P (operands[2]))
+    return "f<FP:prec>div%.d %2,%0";
+  return "f<FP:prec>div%.<FP:prec> %2,%0";
 })
 \f
 ;; Remainder instructions.
        (neg:SF (match_operand:SF 1 "general_operand" "")))]
   ""
 {
-  if (!TARGET_68881)
+  if (!TARGET_HARD_FLOAT)
     {
       rtx result;
       rtx target;
     }
 })
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,d")
-       (neg:SF (match_operand:SF 1 "general_operand" "fdmF,0")))]
-  "TARGET_68881"
-{
-  if (DATA_REG_P (operands[0]))
-    {
-      operands[1] = GEN_INT (31);
-      return "bchg %1,%0";
-    }
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "f%$neg%.x %1,%0";
-  return "f%$neg%.s %f1,%0";
-})
-
 (define_expand "negdf2"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (neg:DF (match_operand:DF 1 "general_operand" "")))]
   ""
 {
-  if (!TARGET_68881)
+  if (!TARGET_HARD_FLOAT)
     {
       rtx result;
       rtx target;
     }
 })
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,d")
-       (neg:DF (match_operand:DF 1 "general_operand" "fmF,0")))]
+(define_expand "negxf2"
+  [(set (match_operand:XF 0 "nonimmediate_operand" "")
+       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
+  ""
+{
+  if (!TARGET_68881)
+    {
+      rtx result;
+      rtx target;
+      rtx insns;
+
+      start_sequence ();
+      target = operand_subword (operands[0], 0, 1, XFmode);
+      result = expand_binop (SImode, xor_optab,
+                            operand_subword_force (operands[1], 0, XFmode),
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
+      gcc_assert (result);
+
+      if (result != target)
+       emit_move_insn (result, target);
+
+      emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
+                     operand_subword_force (operands[1], 1, XFmode));
+      emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
+                     operand_subword_force (operands[1], 2, XFmode));
+
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+      DONE;
+    }
+})
+
+(define_insn "neg<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d")
+       (neg:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m<FP:const>,0")))]
   "TARGET_68881"
 {
   if (DATA_REG_P (operands[0]))
       operands[1] = GEN_INT (31);
       return "bchg %1,%0";
     }
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "f%&neg%.x %1,%0";
-  return "f%&neg%.d %f1,%0";
+  if (FP_REG_P (operands[1]))
+    return "f<FP:round>neg%.x %1,%0";
+  return "f<FP:round>neg%.<FP:prec> %f1,%0";
+})
+
+(define_insn "neg<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d")
+       (neg:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U,0")))]
+  "TARGET_COLDFIRE_FPU"
+{
+  if (DATA_REG_P (operands[0]))
+    {
+      operands[1] = GEN_INT (31);
+      return "bchg %1,%0";
+    }
+  if (FP_REG_P (operands[1]))
+    return "f<FP:prec>neg%.d %1,%0";
+  return "f<FP:prec>neg%.<FP:prec> %1,%0";
 })
 \f
 ;; Sqrt instruction for the 68881
 
-(define_insn "sqrtsf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (sqrt:SF (match_operand:SF 1 "general_operand" "fm")))]
+(define_expand "sqrt<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "")
+       (sqrt:FP (match_operand:FP 1 "general_operand" "")))]
+  "TARGET_HARD_FLOAT"
+  "")
+
+(define_insn "sqrt<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (sqrt:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m")))]
   "TARGET_68881"
 {
   if (FP_REG_P (operands[1]))
-    return "f%$sqrt%.x %1,%0";
-  else
-    return "f%$sqrt%.s %1,%0";
+    return "f<FP:round>sqrt%.x %1,%0";
+  return "f<FP:round>sqrt%.<FP:prec> %1,%0";
 })
 
-(define_insn "sqrtdf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (sqrt:DF (match_operand:DF 1 "general_operand" "fm")))]
-  "TARGET_68881"
+(define_insn "sqrt<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (sqrt:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U")))]
+  "TARGET_COLDFIRE_FPU"
 {
   if (FP_REG_P (operands[1]))
-    return "f%&sqrt%.x %1,%0";
-  else
-    return "f%&sqrt%.d %1,%0";
+    return "f<FP:prec>sqrt%.d %1,%0";
+  return "f<FP:prec>sqrt%.<FP:prec> %1,%0";
 })
-
 ;; Absolute value instructions
 ;; If using software floating point, just zero the sign bit.
 
        (abs:SF (match_operand:SF 1 "general_operand" "")))]
   ""
 {
-  if (!TARGET_68881)
+  if (!TARGET_HARD_FLOAT)
     {
       rtx result;
       rtx target;
     }
 })
 
-(define_insn ""
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (abs:SF (match_operand:SF 1 "general_operand" "fdmF")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "f%$abs%.x %1,%0";
-  return "f%$abs%.s %f1,%0";
-})
-
 (define_expand "absdf2"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (abs:DF (match_operand:DF 1 "general_operand" "")))]
   ""
 {
-  if (!TARGET_68881)
+  if (!TARGET_HARD_FLOAT)
     {
       rtx result;
       rtx target;
     }
 })
 
-(define_insn ""
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
-  "TARGET_68881"
+(define_expand "absxf2"
+  [(set (match_operand:XF 0 "nonimmediate_operand" "")
+       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
+  ""
+{
+  if (!TARGET_68881)
+    {
+      rtx result;
+      rtx target;
+      rtx insns;
+
+      start_sequence ();
+      target = operand_subword (operands[0], 0, 1, XFmode);
+      result = expand_binop (SImode, and_optab,
+                            operand_subword_force (operands[1], 0, XFmode),
+                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
+      gcc_assert (result);
+
+      if (result != target)
+       emit_move_insn (result, target);
+
+      emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
+                     operand_subword_force (operands[1], 1, XFmode));
+      emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
+                     operand_subword_force (operands[1], 2, XFmode));
+
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+      DONE;
+    }
+})
+
+(define_insn "abs<mode>2_68881"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d")
+       (abs:FP (match_operand:FP 1 "general_operand" "f<FP:dreg>m<FP:const>,0")))]
+  "TARGET_68881"
+{
+  if (DATA_REG_P (operands[0]))
+    {
+      operands[1] = GEN_INT (31);
+      return "bclr %1,%0";
+    }
+  if (FP_REG_P (operands[1]))
+    return "f<FP:round>abs%.x %1,%0";
+  return "f<FP:round>abs%.<FP:prec> %f1,%0";
+})
+
+(define_insn "abs<mode>2_cf"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d")
+       (abs:FP (match_operand:FP 1 "general_operand" "f<FP:dreg><Q>U,0")))]
+  "TARGET_COLDFIRE_FPU"
 {
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "f%&abs%.x %1,%0";
-  return "f%&abs%.d %f1,%0";
+  if (DATA_REG_P (operands[0]))
+    {
+      operands[1] = GEN_INT (31);
+      return "bclr %1,%0";
+    }
+  if (FP_REG_P (operands[1]))
+    return "f<FP:prec>abs%.d %1,%0";
+  return "f<FP:prec>abs%.<FP:prec> %1,%0";
 })
 \f
 ;; one complement instructions
        (eq:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
        (ne:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
        (gt:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
        (lt:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
        (ge:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
        (le:QI (cc0) (const_int 0)))]
   ""
 {
-  if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+  if ((TARGET_68060 || TARGET_COLDFIRE_FPU)
+      && m68k_last_compare_had_fp_operands)
     {
       m68k_last_compare_had_fp_operands = 0;
       FAIL;
 })
 
 \f
-(define_expand "tstxf"
-  [(set (cc0)
-       (match_operand:XF 0 "nonimmediate_operand" ""))]
-  "TARGET_68881"
-  "m68k_last_compare_had_fp_operands = 1;")
-
-(define_insn ""
-  [(set (cc0)
-       (match_operand:XF 0 "nonimmediate_operand" "fm"))]
-  "TARGET_68881"
-{
-  cc_status.flags = CC_IN_68881;
-  return "ftst%.x %0";
-})
-
-(define_expand "cmpxf"
-  [(set (cc0)
-       (compare (match_operand:XF 0 "nonimmediate_operand" "")
-                (match_operand:XF 1 "nonimmediate_operand" "")))]
-  "TARGET_68881"
-  "m68k_last_compare_had_fp_operands = 1;")
-
-(define_insn ""
-  [(set (cc0)
-       (compare (match_operand:XF 0 "nonimmediate_operand" "f,m")
-                (match_operand:XF 1 "nonimmediate_operand" "fm,f")))]
-  "TARGET_68881"
-{
-  cc_status.flags = CC_IN_68881;
-  if (REG_P (operands[0]))
-    {
-      if (REG_P (operands[1]))
-       return "fcmp%.x %1,%0";
-      else
-        return "fcmp%.x %f1,%0";
-    }
-  cc_status.flags |= CC_REVERSED;
-  return "fcmp%.x %f0,%1";
-})
-
 (define_insn "extendsfxf2"
   [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
        (float_extend:XF (match_operand:SF 1 "general_operand" "f,rmF")))]
   return "fmove%.d %f1,%0";
 })
 
-(define_insn "truncxfsf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=dm")
-       (float_truncate:SF
-         (match_operand:XF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.s %f1,%0")
-
-(define_insn "floatsixf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (float:XF (match_operand:SI 1 "general_operand" "dmi")))]
-  "TARGET_68881"
-  "fmove%.l %1,%0")
-
-(define_insn "floathixf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (float:XF (match_operand:HI 1 "general_operand" "dmn")))]
-  "TARGET_68881"
-  "fmove%.w %1,%0")
-
-(define_insn "floatqixf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (float:XF (match_operand:QI 1 "general_operand" "dmn")))]
-  "TARGET_68881"
-  "fmove%.b %1,%0")
-
-(define_insn "ftruncxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (fix:XF (match_operand:XF 1 "general_operand" "fFm")))]
-  "TARGET_68881"
-{
-  if (FP_REG_P (operands[1]))
-    return "fintrz%.x %f1,%0";
-  return "fintrz%.x %f1,%0";
-})
-
-(define_insn "fixxfqi2"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
-       (fix:QI (match_operand:XF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.b %1,%0")
-
-(define_insn "fixxfhi2"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
-       (fix:HI (match_operand:XF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.w %1,%0")
-
-(define_insn "fixxfsi2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
-       (fix:SI (match_operand:XF 1 "general_operand" "f")))]
-  "TARGET_68881"
-  "fmove%.l %1,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (plus:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:XF 1 "nonimmediate_operand" "0")))]
-  "TARGET_68881"
-  "fadd%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (plus:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "nonimmediate_operand" "0")))]
-  "TARGET_68881"
-  "fadd%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (plus:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "general_operand" "0")))]
-  "TARGET_68881"
-  "fadd%.b %2,%0")
-
-(define_insn "addxf3"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (plus:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
-                (match_operand:XF 2 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[2]))
-    return "fadd%.x %2,%0";
-  return "fadd%.x %f2,%0";
-})
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-                 (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
-  "TARGET_68881"
-  "fsub%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-                 (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "fsub%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-                 (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "fsub%.b %2,%0")
-
-(define_insn "subxf3"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-                 (match_operand:XF 2 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[2]))
-    return "fsub%.x %2,%0";
-  return "fsub%.x %f2,%0";
-})
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (mult:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
-                (match_operand:XF 1 "nonimmediate_operand" "0")))]
-  "TARGET_68881"
-  "fmul%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (mult:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "nonimmediate_operand" "0")))]
-  "TARGET_68881"
-  "fmul%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (mult:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
-                (match_operand:XF 1 "nonimmediate_operand" "0")))]
-  "TARGET_68881"
-  "fmul%.b %2,%0")
-
-(define_insn "mulxf3"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
-                (match_operand:XF 2 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[2]))
-    return "fmul%.x %2,%0";
-  return "fmul%.x %f2,%0";
-})
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-               (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
-  "TARGET_68881"
-  "fdiv%.l %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-               (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "fdiv%.w %2,%0")
-
-(define_insn ""
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-               (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
-  "TARGET_68881"
-  "fdiv%.b %2,%0")
-
-(define_insn "divxf3"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
-               (match_operand:XF 2 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[2]))
-    return "fdiv%.x %2,%0";
-  return "fdiv%.x %f2,%0";
-})
-
-(define_expand "negxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "")
-       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
-  ""
-{
-  if (!TARGET_68881)
-    {
-      rtx result;
-      rtx target;
-      rtx insns;
-
-      start_sequence ();
-      target = operand_subword (operands[0], 0, 1, XFmode);
-      result = expand_binop (SImode, xor_optab,
-                            operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
-      gcc_assert (result);
-
-      if (result != target)
-       emit_move_insn (result, target);
-
-      emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
-                     operand_subword_force (operands[1], 1, XFmode));
-      emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
-                     operand_subword_force (operands[1], 2, XFmode));
-
-      insns = get_insns ();
-      end_sequence ();
-
-      emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
-      DONE;
-    }
-})
-
-(define_insn "negxf2_68881"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "fneg%.x %1,%0";
-  return "fneg%.x %f1,%0";
-})
-
-(define_expand "absxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "")
-       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
-  ""
-{
-  if (!TARGET_68881)
-    {
-      rtx result;
-      rtx target;
-      rtx insns;
-
-      start_sequence ();
-      target = operand_subword (operands[0], 0, 1, XFmode);
-      result = expand_binop (SImode, and_optab,
-                            operand_subword_force (operands[1], 0, XFmode),
-                            GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN);
-      gcc_assert (result);
-
-      if (result != target)
-       emit_move_insn (result, target);
-
-      emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
-                     operand_subword_force (operands[1], 1, XFmode));
-      emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
-                     operand_subword_force (operands[1], 2, XFmode));
-
-      insns = get_insns ();
-      end_sequence ();
-
-      emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
-      DONE;
-    }
-})
-
-(define_insn "absxf2_68881"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-{
-  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
-    return "fabs%.x %1,%0";
-  return "fabs%.x %f1,%0";
-})
-
-(define_insn "sqrtxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (sqrt:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
-  "TARGET_68881"
-  "fsqrt%.x %1,%0")
-
-(define_insn "sinsf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] UNSPEC_SIN))]
-  "TARGET_68881 && flag_unsafe_math_optimizations"
-{
-  if (FP_REG_P (operands[1]))
-    return "fsin%.x %1,%0";
-  else
-    return "fsin%.s %1,%0";
-})
-
-(define_insn "sindf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] UNSPEC_SIN))]
+(define_insn "sin<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (unspec:FP
+         [(match_operand:FP 1 "general_operand" "f<FP:dreg>m")] UNSPEC_SIN))]
   "TARGET_68881 && flag_unsafe_math_optimizations"
 {
   if (FP_REG_P (operands[1]))
     return "fsin%.x %1,%0";
   else
-    return "fsin%.d %1,%0";
-})
-
-(define_insn "sinxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] UNSPEC_SIN))]
-  "TARGET_68881 && flag_unsafe_math_optimizations"
-  "fsin%.x %1,%0")
-
-(define_insn "cossf2"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
-       (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] UNSPEC_COS))]
-  "TARGET_68881 && flag_unsafe_math_optimizations"
-{
-  if (FP_REG_P (operands[1]))
-    return "fcos%.x %1,%0";
-  else
-    return "fcos%.s %1,%0";
+    return "fsin%.<FP:prec> %1,%0";
 })
 
-(define_insn "cosdf2"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
-       (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] UNSPEC_COS))]
+(define_insn "cos<mode>2"
+  [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
+       (unspec:FP
+         [(match_operand:FP 1 "general_operand" "f<FP:dreg>m")] UNSPEC_COS))]
   "TARGET_68881 && flag_unsafe_math_optimizations"
 {
   if (FP_REG_P (operands[1]))
     return "fcos%.x %1,%0";
   else
-    return "fcos%.d %1,%0";
+    return "fcos%.<FP:prec> %1,%0";
 })
 
-(define_insn "cosxf2"
-  [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
-       (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] UNSPEC_COS))]
-  "TARGET_68881 && flag_unsafe_math_optimizations"
-  "fcos%.x %1,%0")
-
 (define_insn "trap"
   [(trap_if (const_int -1) (const_int 7))]
   ""
index 08c48bd27de476c75bd073942c010f0b7f7e3418..ec2c46655e77b538e2ba2ad123b9fba91e6ebe9e 100644 (file)
@@ -1,6 +1,6 @@
 ; Options for the Motorola 68000 port of the compiler.
 
-; Copyright (C) 2005 Free Software Foundation, Inc.
+; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 ;
 ; This file is part of GCC.
 ;
@@ -39,6 +39,10 @@ m5407
 Target RejectNegative Mask(CFV4)
 Generate code for a 5407
 
+mcfv4e
+Target RejectNegative Mask(CFV4E)
+Generate code for a ColdFire v4e
+
 m68000
 Target RejectNegative
 Generate code for a 68000
index 9a6ced23555782a232f04a7909de97935aa03e0a..f7beb90b0af2defc8c4a680e7cb7ff0f7ce71e64 100644 (file)
@@ -1,6 +1,7 @@
 /* Definitions of target machine for GNU compiler.  "embedded" 68XXX.
    This is meant to be included after m68k.h.
-   Copyright (C) 1994, 1995, 1998, 1999, 2004 Free Software Foundation, Inc.  */
+   Copyright (C) 1994, 1995, 1998, 1999, 2004, 2006
+   Free Software Foundation, Inc.  */
 
 /* Override the SVR4 ABI for this target.  */
 
    and unions in registers, which is slightly more efficient.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
-/* Return floating point values in a fp register.  This make fp code a
-   little bit faster.  It also makes -msoft-float code incompatible with
-   -m68881 code, so people have to be careful not to mix the two.  */
 #undef FUNCTION_VALUE
 #define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
 
 #undef LIBCALL_VALUE
 #define LIBCALL_VALUE(MODE)                                    \
- gen_rtx_REG ((MODE),                                          \
-             ((TARGET_68881                                    \
-               && ((MODE) == SFmode || (MODE) == DFmode        \
-                   || (MODE) == XFmode))                       \
-           ? 16 : 0))
+  m68k_libcall_value (MODE)
 
 #undef FUNCTION_VALUE_REGNO_P
 #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (TARGET_68881 && (N) == 16))
index 897da9cb54116bacd94b537f0fa096e03f891303..afec0bb3e57c1ac77e07123cbd530bfb25e245df 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions of target machine for GNU compiler,
    for m68k (including m68010) NetBSD platforms using the
    ELF object format.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    Contributed by Wasabi Systems. Inc.
 
    This file is derived from <m68k/m68kv4.h>, <m68k/m68kelf.h>,
@@ -307,11 +307,7 @@ while (0)
 
 #undef FUNCTION_VALUE
 #define FUNCTION_VALUE(VALTYPE, FUNC)                                  \
-  (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881                    \
-   ? gen_rtx_REG (TYPE_MODE (VALTYPE), 16)                             \
-   : (POINTER_TYPE_P (VALTYPE)                                         \
-      ? gen_rtx_REG (TYPE_MODE (VALTYPE), 8)                           \
-      : gen_rtx_REG (TYPE_MODE (VALTYPE), 0)))
+  m68k_function_value (VALTYPE, FUNC)
 
 
 /* For compatibility with the large body of existing code which does
@@ -339,10 +335,7 @@ while (0)
 
 #undef LIBCALL_VALUE
 #define LIBCALL_VALUE(MODE)                                            \
-  ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)         \
-    && TARGET_68881)                                                   \
-   ? gen_rtx_REG (MODE, 16)                                            \
-   : gen_rtx_REG (MODE, 0))
+  m68k_libcall_value (MODE)
 
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.
index a1d57a04c2641d3de8a8060c9d022749a1ea23ea..ecf738f491991a50fed9d641f74587a7e38879a5 100644 (file)
@@ -12,14 +12,15 @@ xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
        echo '#define EXTFLOAT' > xfgnulib.c
        cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
 
-MULTILIB_OPTIONS = m68000/m68020/m5200/m5206e/m528x/m5307/m5407/mcpu32/m68040/m68060 m68881/msoft-float
+MULTILIB_OPTIONS = m68000/m68020/m5200/m5206e/m528x/m5307/m5407/mcfv4e/mcpu32/m68040/m68060 m68881/msoft-float
 MULTILIB_DIRNAMES =
 MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 mcpu32=m68332 m68020=mc68020 m5206e=m5272
 MULTILIB_EXCEPTIONS = m68000/msoft-float m5200/m68881 m5200/msoft-float \
                    m5206e/m68881 m5206e/msoft-float m528x/m68881 m528x/msoft-float \
                    m5307/m68881 m5307/msoft-float m5407/m68881 m5407/msoft-float \
                    mcpu32/m68881 mcpu32/msoft-float m68040/m68881 m68040/msoft-float \
-                   m68060/m68881 m68060/msoft-float 
+                   m68060/m68881 m68060/msoft-float \
+                   mcfv4e/msoft-float mcfv4e/m68881
 LIBGCC = stmp-multilib
 INSTALL_LIBGCC = install-multilib
 
index 0d0c521424ac8583391985c181736b97805f7cde..1a21c00105b553e62379fdc70869805e4a604548 100644 (file)
@@ -565,7 +565,8 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{M680x0 Options}
 @gccoptlist{-m68000  -m68020  -m68020-40  -m68020-60  -m68030  -m68040 @gol
--m68060  -mcpu32  -m5200  -m68881  -mbitfield  -mc68000  -mc68020   @gol
+-m68060  -mcpu32  -m5200  -mcfv4e -m68881  -mbitfield  @gol
+-mc68000  -mc68020   @gol
 -mnobitfield  -mrtd  -mshort  -msoft-float  -mpcrel @gol
 -malign-int  -mstrict-align  -msep-data  -mno-sep-data @gol
 -mshared-library-id=n  -mid-shared-library  -mno-id-shared-library}
@@ -9906,6 +9907,10 @@ when the compiler is configured for 520X-based systems.
 Use this option for microcontroller with a 5200 core, including
 the MCF5202, MCF5203, MCF5204 and MCF5202.
 
+@item -mcfv4e
+@opindex mcfv4e
+Generate output for a ColdFire V4e family cpu (e.g.@: 547x/548x).
+This includes use of hardware floating point instructions.
 
 @item -m68020-40
 @opindex m68020-40