summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog36
-rw-r--r--gcc/config/m68k/linux.h13
-rw-r--r--gcc/config/m68k/m68k-none.h4
-rw-r--r--gcc/config/m68k/m68k-protos.h5
-rw-r--r--gcc/config/m68k/m68k.c345
-rw-r--r--gcc/config/m68k/m68k.h68
-rw-r--r--gcc/config/m68k/m68k.md1471
-rw-r--r--gcc/config/m68k/m68k.opt6
-rw-r--r--gcc/config/m68k/m68kemb.h12
-rw-r--r--gcc/config/m68k/netbsd-elf.h13
-rw-r--r--gcc/config/m68k/t-m68kelf5
-rw-r--r--gcc/doc/invoke.texi7
12 files changed, 1114 insertions, 871 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f15c4552a54..0c396413477 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
index 5036af9f24c..4f51a021af0 100644
--- a/gcc/config/m68k/linux.h
+++ b/gcc/config/m68k/linux.h
@@ -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. */
diff --git a/gcc/config/m68k/m68k-none.h b/gcc/config/m68k/m68k-none.h
index b3e84c57bfc..a8618cd0337 100644
--- a/gcc/config/m68k/m68k-none.h
+++ b/gcc/config/m68k/m68k-none.h
@@ -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} \
"
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index 028e2939c49..531c6958713 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -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 */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index c2e90227138..1e753dfcd66 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -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);
+}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 245747fcf5c..e4d92576f3d 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -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
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 11c5ab04a9c..4c24756770c 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -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
@@ -131,6 +131,20 @@
(include "predicates.md")
+;; 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 "")])
+
(define_insn ""
[(set (match_operand:DF 0 "push_operand" "=m")
(match_operand:DF 1 "general_operand" "ro<>fyE"))]
@@ -237,43 +251,36 @@
""
"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";
+ return "ftst%.<FP:prec> %0";
})
-(define_expand "tstdf"
+(define_insn "tst<mode>_cf"
[(set (cc0)
- (match_operand:DF 0 "general_operand" ""))]
- "TARGET_68881"
-{
- m68k_last_compare_had_fp_operands = 1;
-})
-
-(define_insn ""
- [(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";
})
+
;; compare instructions.
@@ -408,58 +415,51 @@
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";
})
;; Recognizers for btst instructions.
@@ -782,6 +782,34 @@
"!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" ""))]
@@ -833,19 +861,111 @@
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<>")
@@ -884,14 +1004,55 @@
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.
@@ -1434,7 +1595,7 @@
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_extend:DF
(match_operand:SF 1 "general_operand" "")))]
- "TARGET_68881"
+ "TARGET_HARD_FLOAT"
"")
(define_insn ""
@@ -1466,13 +1627,34 @@
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.
@@ -1487,6 +1669,15 @@
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
@@ -1502,53 +1693,62 @@
;; 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
@@ -1591,63 +1791,88 @@
;; 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")
+
;; add instructions
@@ -2099,82 +2324,54 @@
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";
})
;; subtract instructions
@@ -2336,82 +2533,54 @@
"!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";
})
;; multiply instructions
@@ -2655,35 +2824,47 @@
"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")))]
@@ -2701,53 +2882,13 @@
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");
@@ -2755,101 +2896,93 @@
? "fsmul%.s %f2,%0"
: "fsglmul%.s %f2,%0");
})
-
-;; 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";
})
+
+;; 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";
})
;; Remainder instructions.
@@ -3580,7 +3713,7 @@
(neg:SF (match_operand:SF 1 "general_operand" "")))]
""
{
- if (!TARGET_68881)
+ if (!TARGET_HARD_FLOAT)
{
rtx result;
rtx target;
@@ -3600,27 +3733,12 @@
}
})
-(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;
@@ -3647,9 +3765,43 @@
}
})
-(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]))
@@ -3657,35 +3809,53 @@
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";
})
;; 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.
@@ -3694,7 +3864,7 @@
(abs:SF (match_operand:SF 1 "general_operand" "")))]
""
{
- if (!TARGET_68881)
+ if (!TARGET_HARD_FLOAT)
{
rtx result;
rtx target;
@@ -3714,22 +3884,12 @@
}
})
-(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;
@@ -3756,14 +3916,68 @@
}
})
-(define_insn ""
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
- (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
+(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 (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: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 (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";
})
;; one complement instructions
@@ -4987,7 +5201,8 @@
(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;
@@ -5008,7 +5223,8 @@
(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;
@@ -5029,7 +5245,8 @@
(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;
@@ -5065,7 +5282,8 @@
(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;
@@ -5101,7 +5319,8 @@
(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;
@@ -5137,7 +5356,8 @@
(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;
@@ -6614,46 +6834,6 @@
})
-(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")))]
@@ -6735,337 +6915,30 @@
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";
+ return "fsin%.<FP:prec> %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))]
+(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%.s %1,%0";
+ return "fcos%.<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))]
- "TARGET_68881 && flag_unsafe_math_optimizations"
-{
- if (FP_REG_P (operands[1]))
- return "fcos%.x %1,%0";
- else
- return "fcos%.d %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))]
""
diff --git a/gcc/config/m68k/m68k.opt b/gcc/config/m68k/m68k.opt
index 08c48bd27de..ec2c46655e7 100644
--- a/gcc/config/m68k/m68k.opt
+++ b/gcc/config/m68k/m68k.opt
@@ -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
diff --git a/gcc/config/m68k/m68kemb.h b/gcc/config/m68k/m68kemb.h
index 9a6ced23555..f7beb90b0af 100644
--- a/gcc/config/m68k/m68kemb.h
+++ b/gcc/config/m68k/m68kemb.h
@@ -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. */
@@ -21,19 +22,12 @@
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))
diff --git a/gcc/config/m68k/netbsd-elf.h b/gcc/config/m68k/netbsd-elf.h
index 897da9cb541..afec0bb3e57 100644
--- a/gcc/config/m68k/netbsd-elf.h
+++ b/gcc/config/m68k/netbsd-elf.h
@@ -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.
diff --git a/gcc/config/m68k/t-m68kelf b/gcc/config/m68k/t-m68kelf
index a1d57a04c26..ecf738f4919 100644
--- a/gcc/config/m68k/t-m68kelf
+++ b/gcc/config/m68k/t-m68kelf
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0d0c521424a..1a21c00105b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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