Commit dcc21c4c by Paul Brook Committed by Paul Brook

m68k.md: Add Coldfire FPU support.

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
parent d54d5437
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
......
/* 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. */
......
/* 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} \
"
......
/* 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 */
......
......@@ -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);
}
/* 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
......
;;- 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";
})
(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";
})
;; 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")))]
"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";
})
;; 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";
})
(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))]
""
......
; 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
......
/* 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))
......
/* 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.
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment