From 58c23110615071a5addd5f14bb287f568eef7b4d Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 22 Jan 2006 15:01:02 +0000 Subject: [PATCH] 2006-01-22 Paul Brook Peter Barada * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110091 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 36 + gcc/config/m68k/linux.h | 13 +- gcc/config/m68k/m68k-none.h | 4 +- gcc/config/m68k/m68k-protos.h | 5 +- gcc/config/m68k/m68k.c | 345 +++++++++- gcc/config/m68k/m68k.h | 68 +- gcc/config/m68k/m68k.md | 1473 +++++++++++++++++++---------------------- gcc/config/m68k/m68k.opt | 6 +- gcc/config/m68k/m68kemb.h | 12 +- gcc/config/m68k/netbsd-elf.h | 13 +- gcc/config/m68k/t-m68kelf | 5 +- gcc/doc/invoke.texi | 7 +- 12 files changed, 1115 insertions(+), 872 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 + Peter Barada + + * 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 * 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" [(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_68881" [(set (cc0) - (match_operand:SF 0 "general_operand" "fdm"))] + (match_operand:FP 0 "general_operand" "fm"))] "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%. %0"; }) -(define_insn "" +(define_insn "tst_cf" [(set (cc0) - (match_operand:DF 0 "general_operand" "fm"))] - "TARGET_68881" + (match_operand:FP 0 "general_operand" "fU"))] + "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%. %0"; }) + ;; compare instructions. @@ -408,58 +415,51 @@ return "cmp%.b %d1,%d0"; }) -(define_expand "cmpdf" +(define_expand "cmp" [(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, operands[1]); }) -(define_insn "" +(define_insn "cmp_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") + (match_operand:FP 1 "general_operand" "fm,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%. %f1,%0"; } cc_status.flags |= CC_REVERSED; - return "fcmp%.d %f0,%1"; + return "fcmp%. %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_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,U") + (match_operand:FP 1 "general_operand" "fU,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%. %f1,%0"; } cc_status.flags |= CC_REVERSED; - return "fcmp%.s %f0,%1"; + return "fcmp%. %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" "=rU, f, f,mr,f,r,f +,m") + (match_operand:SF 1 "general_operand" " f, rU,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, U,r,f,r,r,m,f") + (match_operand:DF 1 "general_operand" " fU,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,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,dU") + (float_truncate:SF + (match_operand:DF 1 "general_operand" "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 "floatsi2" + [(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 "floatsi2_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") + "fmove%.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 "floatsi2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (float:FP (match_operand:SI 1 "general_operand" "dU")))] + "TARGET_COLDFIRE_FPU" + "fmove%.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 "floathi2" + [(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 "floathi2_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 "floathi2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (float:FP (match_operand:HI 1 "general_operand" "dU")))] + "TARGET_COLDFIRE_FPU" + "fmove%.w %1,%0") + + +(define_expand "floatqi2" + [(set (match_operand:FP 0 "nonimmediate_operand" "") + (float:FP (match_operand:QI 1 "general_operand" "")))] + "TARGET_HARD_FLOAT" + "") + +(define_insn "floatqi2_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 "floatqi2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (float:FP (match_operand:QI 1 "general_operand" "dU")))] + "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 "ftrunc2" + [(set (match_operand:FP 0 "nonimmediate_operand" "") + (fix:FP (match_operand:FP 1 "general_operand" "")))] + "TARGET_HARD_FLOAT && !TARGET_68040" + "") + +(define_insn "ftrunc2_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (fix:FP (match_operand:FP 1 "general_operand" "fm")))] "TARGET_68881 && !TARGET_68040" { if (FP_REG_P (operands[1])) return "fintrz%.x %f1,%0"; - return "fintrz%.d %f1,%0"; + return "fintrz%. %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 "ftrunc2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (fix:FP (match_operand:FP 1 "general_operand" "fU")))] + "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%. %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 "fixqi2" + [(set (match_operand:QI 0 "nonimmediate_operand" "") + (fix:QI (match_operand:FP 1 "general_operand" "")))] + "TARGET_HARD_FLOAT" + "") + +(define_insn "fixqi2_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 "fixqi2_cf" + [(set (match_operand:QI 0 "nonimmediate_operand" "=dU") + (fix:QI (match_operand:FP 1 "general_operand" "f")))] + "TARGET_COLDFIRE_FPU" "fmove%.b %1,%0") -(define_insn "fixdfhi2" +(define_expand "fixhi2" + [(set (match_operand:HI 0 "nonimmediate_operand" "") + (fix:HI (match_operand:FP 1 "general_operand" "")))] + "TARGET_HARD_FLOAT" + "") + +(define_insn "fixhi2_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 "fixhi2_cf" + [(set (match_operand:HI 0 "nonimmediate_operand" "=dU") + (fix:HI (match_operand:FP 1 "general_operand" "f")))] + "TARGET_COLDFIRE_FPU" + "fmove%.w %1,%0") + +(define_expand "fixsi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (fix:SI (match_operand:FP 1 "general_operand" "")))] + "TARGET_HARD_FLOAT" + "") + +(define_insn "fixsi2_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 "fixsi2_cf" + [(set (match_operand:SI 0 "nonimmediate_operand" "=dU") + (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 "add3" + [(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 "add3_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") + "fadd%.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 "add3_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") + "fadd%.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 "add3_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") + "fadd%.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 "add3_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (plus:FP (match_operand:FP 1 "general_operand" "%0") + (match_operand:FP 2 "general_operand" "fm")))] "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 "fadd%.x %2,%0"; + return "fadd%. %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 "add3_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (plus:FP (match_operand:FP 1 "general_operand" "%0") + (match_operand:FP 2 "general_operand" "fU")))] + "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 "fadd%.d %2,%0"; + return "fadd%. %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 "sub3" + [(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 "sub3_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") + "fsub%.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 "sub3_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") + "fsub%.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 "sub3_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") + "fsub%.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 "sub3_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (minus:FP (match_operand:FP 1 "general_operand" "0") + (match_operand:FP 2 "general_operand" "fm")))] "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 "fsub%.x %2,%0"; + return "fsub%. %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 "sub3_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (minus:FP (match_operand:FP 1 "general_operand" "0") + (match_operand:FP 2 "general_operand" "fU")))] + "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 "fsub%.d %2,%0"; + return "fsub%. %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 "mul3" + [(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 "mul3_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 + ? "fmul%.l %2,%0" + : "fmul%.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 "mul3_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 + ? "fmul%.w %2,%0" + : "fmul%.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 "mul3_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 + ? "fmul%.b %2,%0" + : "fmul%.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 "fmul3_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (mult:FP (match_operand:FP 1 "general_operand" "%0") + (match_operand:FP 2 "general_operand" "fU")))] + "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 "fmul%.d %2,%0"; + return "fmul%. %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 "div3" + [(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 "div3_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 + ? "fdiv%.l %2,%0" + : "fdiv%.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 "div3_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 + ? "fdiv%.w %2,%0" + : "fdiv%.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 "div3_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 + ? "fdiv%.b %2,%0" + : "fdiv%.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 "div3_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (div:FP (match_operand:FP 1 "general_operand" "0") + (match_operand:FP 2 "general_operand" "fm")))] "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"); + ? "fdiv%.x %2,%0" + : "fdiv%.x %2,%0"); return (TARGET_68040_ONLY - ? "fsdiv%.s %f2,%0" - : "fsgldiv%.s %f2,%0"); + ? "fdiv%. %f2,%0" + : "fdiv%. %f2,%0"); +}) + +(define_insn "div3_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (div:FP (match_operand:FP 1 "general_operand" "0") + (match_operand:FP 2 "general_operand" "fU")))] + "TARGET_COLDFIRE_FPU" +{ + if (FP_REG_P (operands[2])) + return "fdiv%.d %2,%0"; + return "fdiv%. %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 "neg2_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") + (neg:FP (match_operand:FP 1 "general_operand" "fm,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 "fneg%.x %1,%0"; + return "fneg%. %f1,%0"; +}) + +(define_insn "neg2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") + (neg:FP (match_operand:FP 1 "general_operand" "fU,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 "fneg%.d %1,%0"; + return "fneg%. %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 "sqrt2" + [(set (match_operand:FP 0 "nonimmediate_operand" "") + (sqrt:FP (match_operand:FP 1 "general_operand" "")))] + "TARGET_HARD_FLOAT" + "") + +(define_insn "sqrt2_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (sqrt:FP (match_operand:FP 1 "general_operand" "fm")))] "TARGET_68881" { if (FP_REG_P (operands[1])) - return "f%$sqrt%.x %1,%0"; - else - return "f%$sqrt%.s %1,%0"; + return "fsqrt%.x %1,%0"; + return "fsqrt%. %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 "sqrt2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (sqrt:FP (match_operand:FP 1 "general_operand" "fU")))] + "TARGET_COLDFIRE_FPU" { if (FP_REG_P (operands[1])) - return "f%&sqrt%.x %1,%0"; - else - return "f%&sqrt%.d %1,%0"; + return "fsqrt%.d %1,%0"; + return "fsqrt%. %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 "abs2_68881" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") + (abs:FP (match_operand:FP 1 "general_operand" "fm,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 "fabs%.x %1,%0"; + return "fabs%. %f1,%0"; +}) + +(define_insn "abs2_cf" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f,d") + (abs:FP (match_operand:FP 1 "general_operand" "fU,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 "fabs%.d %1,%0"; + return "fabs%. %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 "sin2" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (unspec:FP + [(match_operand:FP 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%.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%. %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 "cos2" + [(set (match_operand:FP 0 "nonimmediate_operand" "=f") + (unspec:FP + [(match_operand:FP 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"; + return "fcos%. %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 , , @@ -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 -- 2.11.4.GIT