This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

128bit long double support for i386


Hi
This patch adds support to TFmode arithmetics to i386 port.  Like on IA-64, the
operations are still 80 bit, but using sizeof (long double) == 16 is faster
over sizeof (long double) == 12, because of better alignment of data.

According to my simple experiment that did matrix multiplication over 1024*1024
matrix, the speedup on PentiumPro is roughly 50%, on the Athlon speed is the
same, since the long double accesses are slow anyway. In the future some speedup
can be got also by using SSE moves for moving long doubles around.

The patch adds new ABI breaking option -m128bit-long-double to control size of
long double.  To make it more useable in "normal" programs, I would like to get
working construct like:

typedef          float fast_long_double     __attribute__ ((mode (TF)));

So programs would be able to use fast_long_double internally and cast it to
long double before calling library.  Some work is needed on the generic code to
accept idea of two different long-double types living together as well as I
will need float_extend version of the patterns added by this patch to get sane
code.

HARD_REGNO_NREGS returns 3 for TFmode and ix86_split_long_move moves just first
12bytes, so the extra cost of unused 4 bytes is almost eliminated except for
cache trashing and function calls (that need to push one dumy argument)

This work is mainly important for the x86_64 port, where ABI specifies 16byte
long double and by installing it to the mainline I would like to avoid
desynchronization of both threes.

Honza

Út čec 18 02:23:56 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* i386.c (ix86_split_to_parts): Return number of part required;
	handle TFmodes.
	(print_operand, ix86_expand_branch, ix86_expand_fp_movcc): Handle
	TFmodes.
	(ix86_split_long_move): Use number of part returned
	by ix86_split_to_parts
	* i386.h (MASK_128BIT_LONG_DOUBLE, TARGET_128BIT_LONG_DOUBLE):
	New macros.
	(TARGET_SWITCHES): Add 128bit-long-double and 96bit-long-double
	(LONG_DOUBLE_TYPE_SIZE): Change from constant.
	(MAX_LONG_DOUBLE_TYPE_SIZE): New macro.
	(INTEL_EXTENDED_IEEE_FORMAT): Likewise.
	(ALIGN_MODE_128): Add TFmode.
	(IS_STACK_MODE): Likewise.
	(HARD_REGNO_NREGS): TFmode needs 3 registers.
	(HARD_REGNO_OK): Support TFmodes.
	(ASM_OUTPUT_LONG_DOUBLE): Handle TFmodes.
	* i386.md (scheduler definitions): Use memory operand to determine
	fst/fld instructions; use mode attribute to determine real mode of
	the instruction.
	(*tf): New patterns, expanders and splitters; based on XFmode patterns.
	* invoke.texi (128bit-long-double, 96bit-long-double): Document.
	
diff -Nrc3p config/i386.old/i386.c config/i386/i386.c
*** config/i386.old/i386.c	Sun Jun 18 03:11:47 2000
--- config/i386/i386.c	Sun Jun 18 03:43:06 2000
*************** static rtx * ix86_pent_find_pair PARAMS 
*** 404,410 ****
  					 rtx));
  static void ix86_init_machine_status PARAMS ((struct function *));
  static void ix86_mark_machine_status PARAMS ((struct function *));
! static void ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
  static int ix86_safe_length_prefix PARAMS ((rtx));
  static HOST_WIDE_INT ix86_compute_frame_size PARAMS((HOST_WIDE_INT,
  						     int *, int *, int *));
--- 404,410 ----
  					 rtx));
  static void ix86_init_machine_status PARAMS ((struct function *));
  static void ix86_mark_machine_status PARAMS ((struct function *));
! static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
  static int ix86_safe_length_prefix PARAMS ((rtx));
  static HOST_WIDE_INT ix86_compute_frame_size PARAMS((HOST_WIDE_INT,
  						     int *, int *, int *));
*************** print_operand (file, x, code)
*** 3354,3359 ****
--- 3354,3360 ----
  	      return;
  
  	    case 12:
+ 	    case 16:
  	      putc ('t', file);
  	      return;
  
*************** print_operand (file, x, code)
*** 3483,3489 ****
        fprintf (file, "%s", dstr);
      }
  
!   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
      {
        REAL_VALUE_TYPE r;
        char dstr[30];
--- 3484,3491 ----
        fprintf (file, "%s", dstr);
      }
  
!   else if (GET_CODE (x) == CONST_DOUBLE
! 	   && (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode))
      {
        REAL_VALUE_TYPE r;
        char dstr[30];
*************** ix86_prepare_fp_compare_args (code, pop0
*** 4796,4801 ****
--- 4798,4804 ----
  
    if (fpcmp_mode == CCFPUmode
        || op_mode == XFmode
+       || op_mode == TFmode
        || ix86_use_fcomi_compare (code))
      {
        op0 = force_reg (op_mode, op0);
*************** ix86_expand_branch (code, label)
*** 5075,5080 ****
--- 5078,5084 ----
      case SFmode:
      case DFmode:
      case XFmode:
+     case TFmode:
        /* Don't expand the comparison early, so that we get better code
  	 when jump or whoever decides to reverse the comparison.  */
        {
*************** ix86_expand_fp_movcc (operands)
*** 5654,5666 ****
     For pushes, it returns just stack offsets; the values will be saved
     in the right order.  Maximally three parts are generated.  */
  
! static void
  ix86_split_to_parts (operand, parts, mode)
       rtx operand;
       rtx *parts;
       enum machine_mode mode;
  {
!   int size = GET_MODE_SIZE (mode) / 4;
  
    if (GET_CODE (operand) == REG && MMX_REGNO_P (REGNO (operand)))
      abort ();
--- 5658,5670 ----
     For pushes, it returns just stack offsets; the values will be saved
     in the right order.  Maximally three parts are generated.  */
  
! static int
  ix86_split_to_parts (operand, parts, mode)
       rtx operand;
       rtx *parts;
       enum machine_mode mode;
  {
!   int size = mode == TFmode ? 3 : GET_MODE_SIZE (mode) / 4;
  
    if (GET_CODE (operand) == REG && MMX_REGNO_P (REGNO (operand)))
      abort ();
*************** ix86_split_to_parts (operand, parts, mod
*** 5710,5721 ****
  	  else if (GET_CODE (operand) == CONST_DOUBLE)
  	    {
  	      REAL_VALUE_TYPE r;
! 	      long l[3];
  
  	      REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
  	      switch (mode)
  		{
  		case XFmode:
  		  REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
  		  parts[2] = GEN_INT (l[2]);
  		  break;
--- 5714,5726 ----
  	  else if (GET_CODE (operand) == CONST_DOUBLE)
  	    {
  	      REAL_VALUE_TYPE r;
! 	      long l[4];
  
  	      REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
  	      switch (mode)
  		{
  		case XFmode:
+ 		case TFmode:
  		  REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
  		  parts[2] = GEN_INT (l[2]);
  		  break;
*************** ix86_split_to_parts (operand, parts, mod
*** 5733,5739 ****
  	}
      }
  
!   return;
  }
  
  /* Emit insns to perform a move or push of DI, DF, and XF values.
--- 5738,5744 ----
  	}
      }
  
!   return size;
  }
  
  /* Emit insns to perform a move or push of DI, DF, and XF values.
*************** ix86_split_long_move (operands1)
*** 5747,5753 ****
  {
    rtx part[2][3];
    rtx operands[2];
!   int size = GET_MODE_SIZE (GET_MODE (operands1[0])) / 4;
    int push = 0;
    int collisions = 0;
  
--- 5752,5758 ----
  {
    rtx part[2][3];
    rtx operands[2];
!   int size;
    int push = 0;
    int collisions = 0;
  
*************** ix86_split_long_move (operands1)
*** 5755,5763 ****
    operands[0] = copy_rtx (operands1[0]);
    operands[1] = copy_rtx (operands1[1]);
  
-   if (size < 2 || size > 3)
-     abort ();
- 
    /* The only non-offsettable memory we handle is push.  */
    if (push_operand (operands[0], VOIDmode))
      push = 1;
--- 5760,5765 ----
*************** ix86_split_long_move (operands1)
*** 5765,5771 ****
  	   && ! offsettable_memref_p (operands[0]))
      abort ();
  
!   ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
    ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
  
    /* When emitting push, take care for source operands on the stack.  */
--- 5767,5773 ----
  	   && ! offsettable_memref_p (operands[0]))
      abort ();
  
!   size = ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
    ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
  
    /* When emitting push, take care for source operands on the stack.  */
*************** ix86_split_long_move (operands1)
*** 5815,5821 ****
    if (push)
      {
        if (size == 3)
! 	emit_insn (gen_push (part[1][2]));
        emit_insn (gen_push (part[1][1]));
        emit_insn (gen_push (part[1][0]));
        return 1;
--- 5817,5831 ----
    if (push)
      {
        if (size == 3)
! 	{
! 	  /* We use only first 12 bytes of TFmode value, but for pushing we
! 	     are required to adjust stack as if we were pushing real 16byte
! 	     value.  */
! 	  if (GET_MODE (operands1[0]) == TFmode)
! 	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! 				   GEN_INT (-4)));
! 	  emit_insn (gen_push (part[1][2]));
! 	}
        emit_insn (gen_push (part[1][1]));
        emit_insn (gen_push (part[1][0]));
        return 1;
diff -Nrc3p config/i386.old/i386.h config/i386/i386.h
*** config/i386.old/i386.h	Sun Jun 18 03:11:47 2000
--- config/i386/i386.h	Sun Jun 18 03:11:45 2000
*************** extern int target_flags;
*** 104,109 ****
--- 104,110 ----
  #define MASK_ACCUMULATE_OUTGOING_ARGS 0x00008000/* Accumulate outgoing args */
  #define MASK_MMX		0x00010000	/* Support MMX regs/builtins */
  #define MASK_SSE		0x00020000	/* Support SSE regs/builtins */
+ #define MASK_128BIT_LONG_DOUBLE 0x00040000	/* long double size is 128bit */
  
  /* Temporary codegen switches */
  #define MASK_INTEL_SYNTAX	0x00000200
*************** extern int target_flags;
*** 144,149 ****
--- 145,155 ----
     the 387 to be used, which is compatible with most calling conventions. */
  #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & MASK_FLOAT_RETURNS)
  
+ /* Long double is 128bit instead of 96bit, even when only 80bits are used.
+    This mode wastes cache, but avoid missaligned data accesses and simplifies
+    address calculations.  */
+ #define TARGET_128BIT_LONG_DOUBLE (target_flags & MASK_128BIT_LONG_DOUBLE)
+ 
  /* Disable generation of FP sin, cos and sqrt operations for 387.
     This is because FreeBSD lacks these in the math-emulator-code */
  #define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387)
*************** extern const int x86_partial_reg_depende
*** 295,300 ****
--- 301,310 ----
      N_("Support MMX and SSE builtins") },				      \
    { "no-sse",			-MASK_SSE,				      \
      N_("Do not support MMX and SSE builtins") },			      \
+   { "128bit-long-double",	 MASK_128BIT_LONG_DOUBLE,		      \
+     N_("sizeof(long double) is 16.") },					      \
+   { "96bit-long-double",	-MASK_128BIT_LONG_DOUBLE,		      \
+     N_("sizeof(long double) is 12.") },					      \
    SUBTARGET_SWITCHES							      \
    { "", TARGET_DEFAULT, 0 }}
  
*************** extern int ix86_arch;
*** 446,454 ****
  
  /* target machine storage layout */
  
! /* Define for XFmode extended real floating point support.
!    This will automatically cause REAL_ARITHMETIC to be defined.  */
! #define LONG_DOUBLE_TYPE_SIZE 96
  
  /* Define if you don't want extended real, but do want to use the
     software floating point emulator for REAL_ARITHMETIC and
--- 456,473 ----
  
  /* target machine storage layout */
  
! /* Define for XFmode or TFmode extended real floating point support.
!    This will automatically cause REAL_ARITHMETIC to be defined.
!  
!    The XFmode is specified by i386 ABI, while TFmode may be faster
!    due to alignment and simplifications in the address calculations.
!  */
! #define LONG_DOUBLE_TYPE_SIZE (TARGET_128BIT_LONG_DOUBLE ? 128 : 96)
! #define MAX_LONG_DOUBLE_TYPE_SIZE 128
! /* Tell real.c that this is the 80-bit Intel extended float format
!    packaged in a 128-bit or 96bit entity.  */
! #define INTEL_EXTENDED_IEEE_FORMAT
! 
  
  /* Define if you don't want extended real, but do want to use the
     software floating point emulator for REAL_ARITHMETIC and
*************** extern int ix86_arch;
*** 515,522 ****
  
  /* Decide whether a variable of mode MODE must be 128 bit aligned.  */
  #define ALIGN_MODE_128(MODE) \
!  ((MODE) == XFmode || ((MODE) == TImode) || (MODE) == V4SFmode	\
!   || (MODE) == V4SImode)
  
  /* The published ABIs say that doubles should be aligned on word
     boundaries, so lower the aligment for structure fields unless
--- 534,541 ----
  
  /* Decide whether a variable of mode MODE must be 128 bit aligned.  */
  #define ALIGN_MODE_128(MODE) \
!  ((MODE) == XFmode || (MODE) == TFmode || ((MODE) == TImode) \
!   || (MODE) == V4SFmode	|| (MODE) == V4SImode)
  
  /* The published ABIs say that doubles should be aligned on word
     boundaries, so lower the aligment for structure fields unless
*************** extern int ix86_arch;
*** 596,602 ****
     for details. */
  
  #define STACK_REGS
! #define IS_STACK_MODE(mode) (mode==DFmode || mode==SFmode || mode==XFmode)
  
  /* Number of actual hardware registers.
     The hardware registers are assigned numbers for the compiler
--- 615,622 ----
     for details. */
  
  #define STACK_REGS
! #define IS_STACK_MODE(mode) (mode==DFmode || mode==SFmode \
! 			     || mode==XFmode || mode==TFmode)
  
  /* Number of actual hardware registers.
     The hardware registers are assigned numbers for the compiler
*************** extern int ix86_arch;
*** 740,746 ****
  
  #define HARD_REGNO_NREGS(REGNO, MODE)   \
    (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) ? 1 \
!    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
  #define VALID_SSE_REG_MODE(MODE) \
      ((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode)
--- 760,768 ----
  
  #define HARD_REGNO_NREGS(REGNO, MODE)   \
    (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) ? 1 \
!    : (MODE == TFmode							\
!       ? 3								\
!       : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
  
  #define VALID_SSE_REG_MODE(MODE) \
      ((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode)
*************** extern int ix86_arch;
*** 765,771 ****
     : FP_REGNO_P (REGNO)						\
     ? ((GET_MODE_CLASS (MODE) == MODE_FLOAT			\
         || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)		\
!       && GET_MODE_UNIT_SIZE (MODE) <= (LONG_DOUBLE_TYPE_SIZE == 96 ? 12 : 8))\
     : SSE_REGNO_P (REGNO) ? VALID_SSE_REG_MODE (MODE)		\
     : MMX_REGNO_P (REGNO) ? VALID_MMX_REG_MODE (MODE)		\
     /* Only SSE and MMX regs can hold vector modes.  */		\
--- 787,793 ----
     : FP_REGNO_P (REGNO)						\
     ? ((GET_MODE_CLASS (MODE) == MODE_FLOAT			\
         || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)		\
!       && GET_MODE_UNIT_SIZE (MODE) <= 16)\
     : SSE_REGNO_P (REGNO) ? VALID_SSE_REG_MODE (MODE)		\
     : MMX_REGNO_P (REGNO) ? VALID_MMX_REG_MODE (MODE)		\
     /* Only SSE and MMX regs can hold vector modes.  */		\
*************** do { long l[2];								\
*** 2614,2622 ****
  
  #undef ASM_OUTPUT_LONG_DOUBLE
  #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)  		\
! do { long l[3];						\
       REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);	\
!      fprintf (FILE, "%s\t0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \
     } while (0)
  
  /* This is how to output an assembler line defining a `float' constant.  */
--- 2636,2647 ----
  
  #undef ASM_OUTPUT_LONG_DOUBLE
  #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)  		\
! do { long l[4];						\
       REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);	\
!      if (TARGET_128BIT_LONG_DOUBLE)			\
!        fprintf (FILE, "%s\t0x%lx,0x%lx,0x%lx,0x0\n", ASM_LONG, l[0], l[1], l[2]); \
!      else \
!        fprintf (FILE, "%s\t0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \
     } while (0)
  
  /* This is how to output an assembler line defining a `float' constant.  */
diff -Nrc3p config/i386.old/i386.md config/i386/i386.md
*** config/i386.old/i386.md	Sun Jun 18 03:11:47 2000
--- config/i386/i386.md	Sun Jun 18 03:11:46 2000
***************
*** 372,390 ****
  (define_function_unit "fpu" 1 0
    (and (eq_attr "cpu" "pentium")
         (and (eq_attr "type" "fmov")
! 	    (ior (and (eq_attr "memory" "store")
! 		      (match_operand:XF 0 "memory_operand" ""))
! 		 (and (eq_attr "memory" "load")
! 		      (match_operand:XF 1 "memory_operand" "")))))
    3 3)
  
  (define_function_unit "pent_np" 1 0
    (and (eq_attr "cpu" "pentium")
         (and (eq_attr "type" "fmov")
! 	    (ior (and (eq_attr "memory" "store")
! 		      (match_operand:XF 0 "memory_operand" ""))
! 		 (and (eq_attr "memory" "load")
! 		      (match_operand:XF 1 "memory_operand" "")))))
    3 3)
  
  (define_function_unit "fpu" 1 0
--- 372,386 ----
  (define_function_unit "fpu" 1 0
    (and (eq_attr "cpu" "pentium")
         (and (eq_attr "type" "fmov")
! 	    (and (eq_attr "memory" "load,store")
! 		 (eq_attr "mode" "XF"))))
    3 3)
  
  (define_function_unit "pent_np" 1 0
    (and (eq_attr "cpu" "pentium")
         (and (eq_attr "type" "fmov")
! 	    (and (eq_attr "memory" "load,store")
! 		 (eq_attr "mode" "XF"))))
    3 3)
  
  (define_function_unit "fpu" 1 0
***************
*** 832,839 ****
                (match_operand 1 "memory_operand" ""))
  	   (const_string "vector")
           (and (eq_attr "type" "fmov")
!               (ior (match_operand:XF 0 "memory_operand" "")
!                    (match_operand:XF 1 "memory_operand" "")))
  	   (const_string "vector")]
  	(const_string "direct")))
  
--- 828,835 ----
                (match_operand 1 "memory_operand" ""))
  	   (const_string "vector")
           (and (eq_attr "type" "fmov")
! 	      (and (eq_attr "memory" "load,store")
! 		   (eq_attr "mode" "XF")))
  	   (const_string "vector")]
  	(const_string "direct")))
  
***************
*** 928,934 ****
  (define_function_unit "athlon_fp" 3 0
    (and (eq_attr "cpu" "athlon")
         (and (eq_attr "type" "fmov")
! 	    (match_operand:XF 1 "memory_operand" "")))
    10 1)
  
  (define_function_unit "athlon_fp" 3 0
--- 924,931 ----
  (define_function_unit "athlon_fp" 3 0
    (and (eq_attr "cpu" "athlon")
         (and (eq_attr "type" "fmov")
! 	    (and (eq_attr "memory" "load")
! 		 (eq_attr "mode" "XF"))))
    10 1)
  
  (define_function_unit "athlon_fp" 3 0
***************
*** 1254,1259 ****
--- 1251,1268 ----
    DONE;
  }")
  
+ (define_expand "cmptf"
+   [(set (reg:CC 17)
+ 	(compare:CC (match_operand:TF 0 "cmp_fp_expander_operand" "")
+ 		    (match_operand:TF 1 "cmp_fp_expander_operand" "")))]
+   "TARGET_80387"
+   "
+ {
+   ix86_compare_op0 = operands[0];
+   ix86_compare_op1 = operands[1];
+   DONE;
+ }")
+ 
  (define_expand "cmpdf"
    [(set (reg:CC 17)
  	(compare:CC (match_operand:DF 0 "cmp_fp_expander_operand" "")
***************
*** 1369,1374 ****
--- 1378,1393 ----
    [(set_attr "type" "fcmp")
     (set_attr "mode" "XF")])
  
+ (define_insn "*cmpfp_2_tf"
+   [(set (reg:CCFP 18)
+ 	(compare:CCFP
+ 	  (match_operand:TF 0 "register_operand" "f")
+ 	  (match_operand:TF 1 "register_operand" "f")))]
+   "TARGET_80387"
+   "* return output_fp_compare (insn, operands, 0, 0);"
+   [(set_attr "type" "fcmp")
+    (set_attr "mode" "XF")])
+ 
  (define_insn "*cmpfp_2_xf_1"
    [(set (match_operand:HI 0 "register_operand" "=a")
  	(unspec:HI
***************
*** 1380,1385 ****
--- 1399,1415 ----
    [(set_attr "type" "multi")
     (set_attr "mode" "XF")])
  
+ (define_insn "*cmpfp_2_tf_1"
+   [(set (match_operand:HI 0 "register_operand" "=a")
+ 	(unspec:HI
+ 	  [(compare:CCFP
+ 	     (match_operand:TF 1 "register_operand" "f")
+ 	     (match_operand:TF 2 "register_operand" "f"))] 9))]
+   "TARGET_80387"
+   "* return output_fp_compare (insn, operands, 2, 0);"
+   [(set_attr "type" "multi")
+    (set_attr "mode" "XF")])
+ 
  (define_insn "*cmpfp_2u"
    [(set (reg:CCFPU 18)
  	(compare:CCFPU
***************
*** 2427,2432 ****
--- 2457,2468 ----
    ""
    "ix86_expand_move (XFmode, operands); DONE;")
  
+ (define_expand "movtf"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ 	(match_operand:TF 1 "general_operand" ""))]
+   ""
+   "ix86_expand_move (TFmode, operands); DONE;")
+ 
  ;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
  ;; Size of pushdf using integer insturctions is 3+3*memory operand size
  ;; Pushing using integer instructions is longer except for constants
***************
*** 2463,2468 ****
--- 2499,2533 ----
    [(set_attr "type" "multi")
     (set_attr "mode" "XF,SI,SI")])
  
+ (define_insn "*pushtf_nointeger"
+   [(set (match_operand:TF 0 "push_operand" "=<,<,<")
+ 	(match_operand:TF 1 "general_no_elim_operand" "f,Fo,*r"))]
+   "optimize_size"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       /* %%% We loose REG_DEAD notes for controling pops if we split late.  */
+       operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx);
+       operands[2] = stack_pointer_rtx;
+       operands[3] = GEN_INT (12);
+       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ 	return \"sub{l}\\t{%3, %2|%2, %3}\;fstp%z0\\t%y0\";
+       else
+ 	return \"sub{l}\\t{%3, %2|%2, %3}\;fst%z0\\t%y0\";
+ 
+     case 1:
+     case 2:
+       return \"#\";
+ 
+     default:
+       abort ();
+     }
+ }"
+   [(set_attr "type" "multi")
+    (set_attr "mode" "XF,SI,SI")])
+ 
  (define_insn "*pushxf_integer"
    [(set (match_operand:XF 0 "push_operand" "=<,<")
  	(match_operand:XF 1 "general_no_elim_operand" "f#r,rFo#f"))]
***************
*** 2491,2500 ****
    [(set_attr "type" "multi")
     (set_attr "mode" "XF,SI")])
  
  (define_split
!   [(set (match_operand:XF 0 "push_operand" "")
! 	(match_operand:XF 1 "general_operand" ""))]
    "reload_completed
     && (!REG_P (operands[1]) || !FP_REGNO_P (REGNO (operands[1])))"
    [(const_int 0)]
    "if (!ix86_split_long_move (operands)) abort (); DONE;")
--- 2556,2596 ----
    [(set_attr "type" "multi")
     (set_attr "mode" "XF,SI")])
  
+ (define_insn "*pushtf_integer"
+   [(set (match_operand:TF 0 "push_operand" "=<,<")
+ 	(match_operand:TF 1 "general_no_elim_operand" "f#r,rFo#f"))]
+   "!optimize_size"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       /* %%% We loose REG_DEAD notes for controling pops if we split late.  */
+       operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx);
+       operands[2] = stack_pointer_rtx;
+       operands[3] = GEN_INT (12);
+       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ 	return \"sub{l}\\t{%3, %2|%2, %3}\;fstp%z0\\t%y0\";
+       else
+ 	return \"sub{l}\\t{%3, %2|%2, %3}\;fst%z0\\t%y0\";
+ 
+     case 1:
+       return \"#\";
+ 
+     default:
+       abort ();
+     }
+ }"
+   [(set_attr "type" "multi")
+    (set_attr "mode" "XF,SI")])
+ 
  (define_split
!   [(set (match_operand 0 "push_operand" "")
! 	(match_operand 1 "general_operand" ""))]
    "reload_completed
+    && (GET_MODE (operands[0]) == XFmode
+        || GET_MODE (operands[0]) == TFmode
+        || GET_MODE (operands[0]) == DFmode)
     && (!REG_P (operands[1]) || !FP_REGNO_P (REGNO (operands[1])))"
    [(const_int 0)]
    "if (!ix86_split_long_move (operands)) abort (); DONE;")
***************
*** 2506,2511 ****
--- 2602,2614 ----
    [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
     (set (mem:XF (reg:SI 7)) (match_dup 1))])
  
+ (define_split
+   [(set (match_operand:TF 0 "push_operand" "")
+ 	(match_operand:TF 1 "register_operand" ""))]
+   "FP_REGNO_P (REGNO (operands[1]))"
+   [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
+    (set (mem:TF (reg:SI 7)) (match_dup 1))])
+ 
  ;; Do not use integer registers when optimizing for size
  (define_insn "*movxf_nointeger"
    [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o")
***************
*** 2554,2559 ****
--- 2657,2709 ----
    [(set_attr "type" "fmov,fmov,fmov,multi,multi")
     (set_attr "mode" "XF,XF,XF,SI,SI")])
  
+ (define_insn "*movtf_nointeger"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m,f,*r,o")
+ 	(match_operand:TF 1 "general_operand" "fm,f,G,*roF,F*r"))]
+   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+    && optimize_size
+    && (reload_in_progress || reload_completed
+        || GET_CODE (operands[1]) != CONST_DOUBLE
+        || memory_operand (operands[0], TFmode))" 
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (REG_P (operands[1])
+           && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp\\t%y0\";
+       else if (STACK_TOP_P (operands[0]))
+         return \"fld%z1\\t%y1\";
+       else
+         return \"fst\\t%y0\";
+ 
+     case 1:
+       /* There is no non-popping store to memory for XFmode.  So if
+ 	 we need one, follow the store with a load.  */
+       if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp%z0\\t%y0\;fld%z0\\t%y0\";
+       else
+         return \"fstp%z0\\t%y0\";
+ 
+     case 2:
+       switch (standard_80387_constant_p (operands[1]))
+         {
+         case 1:
+ 	  return \"fldz\";
+ 	case 2:
+ 	  return \"fld1\";
+ 	}
+       break;
+ 
+     case 3: case 4:
+       return \"#\";
+     }
+   abort();
+ }"
+   [(set_attr "type" "fmov,fmov,fmov,multi,multi")
+    (set_attr "mode" "XF,XF,XF,SI,SI")])
+ 
  (define_insn "*movxf_integer"
    [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
  	(match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
***************
*** 2601,2611 ****
    [(set_attr "type" "fmov,fmov,fmov,multi,multi")
     (set_attr "mode" "XF,XF,XF,SI,SI")])
  
  (define_split
!   [(set (match_operand:XF 0 "nonimmediate_operand" "")
! 	(match_operand:XF 1 "general_operand" ""))]
    "reload_completed
     && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
     && ! (FP_REG_P (operands[0]) || 
  	 (GET_CODE (operands[0]) == SUBREG
  	  && FP_REG_P (SUBREG_REG (operands[0]))))
--- 2751,2809 ----
    [(set_attr "type" "fmov,fmov,fmov,multi,multi")
     (set_attr "mode" "XF,XF,XF,SI,SI")])
  
+ (define_insn "*movtf_integer"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o")
+ 	(match_operand:TF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))]
+   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+    && !optimize_size
+    && (reload_in_progress || reload_completed
+        || GET_CODE (operands[1]) != CONST_DOUBLE
+        || memory_operand (operands[0], TFmode))" 
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (REG_P (operands[1])
+           && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp\\t%y0\";
+       else if (STACK_TOP_P (operands[0]))
+         return \"fld%z1\\t%y1\";
+       else
+         return \"fst\\t%y0\";
+ 
+     case 1:
+       /* There is no non-popping store to memory for XFmode.  So if
+ 	 we need one, follow the store with a load.  */
+       if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp%z0\\t%y0\;fld%z0\\t%y0\";
+       else
+         return \"fstp%z0\\t%y0\";
+ 
+     case 2:
+       switch (standard_80387_constant_p (operands[1]))
+         {
+         case 1:
+ 	  return \"fldz\";
+ 	case 2:
+ 	  return \"fld1\";
+ 	}
+       break;
+ 
+     case 3: case 4:
+       return \"#\";
+     }
+   abort();
+ }"
+   [(set_attr "type" "fmov,fmov,fmov,multi,multi")
+    (set_attr "mode" "XF,XF,XF,SI,SI")])
+ 
  (define_split
!   [(set (match_operand 0 "nonimmediate_operand" "")
! 	(match_operand 1 "general_operand" ""))]
    "reload_completed
     && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+    && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == TFmode)
     && ! (FP_REG_P (operands[0]) || 
  	 (GET_CODE (operands[0]) == SUBREG
  	  && FP_REG_P (SUBREG_REG (operands[0]))))
***************
*** 2618,2627 ****
    "if (ix86_split_long_move (operands)) DONE;")
  
  (define_split
!   [(set (match_operand:XF 0 "register_operand" "")
! 	(match_operand:XF 1 "memory_operand" ""))]
    "reload_completed
     && GET_CODE (operands[1]) == MEM
     && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
     && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))
     && standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0)))"
--- 2816,2826 ----
    "if (ix86_split_long_move (operands)) DONE;")
  
  (define_split
!   [(set (match_operand 0 "register_operand" "")
! 	(match_operand 1 "memory_operand" ""))]
    "reload_completed
     && GET_CODE (operands[1]) == MEM
+    && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == TFmode)
     && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
     && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))
     && standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0)))"
***************
*** 2644,2649 ****
--- 2843,2864 ----
  }"
    [(set_attr "type" "fxch")
     (set_attr "mode" "XF")])
+ 
+ (define_insn "swaptf"
+   [(set (match_operand:TF 0 "register_operand" "+f")
+ 	(match_operand:TF 1 "register_operand" "+f"))
+    (set (match_dup 1)
+ 	(match_dup 0))]
+   ""
+   "*
+ {
+   if (STACK_TOP_P (operands[0]))
+     return \"fxch\\t%1\";
+   else
+     return \"fxch\\t%0\";
+ }"
+   [(set_attr "type" "fxch")
+    (set_attr "mode" "XF")])
  
  ;; Zero extension instructions
  
***************
*** 3032,3038 ****
  	(float_extend:XF (match_operand:SF 1 "register_operand" "")))]
    "FP_REGNO_P (REGNO (operands[1]))"
    [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
!    (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
  
  (define_insn "*dummy_extenddfxf2"
    [(set (match_operand:XF 0 "push_operand" "=<")
--- 3247,3266 ----
  	(float_extend:XF (match_operand:SF 1 "register_operand" "")))]
    "FP_REGNO_P (REGNO (operands[1]))"
    [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
!    (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
! 
! (define_insn "*dummy_extendsftf2"
!   [(set (match_operand:TF 0 "push_operand" "=<")
! 	(float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "f")))]
!   "0"
!   "#")
! 
! (define_split
!   [(set (match_operand:TF 0 "push_operand" "")
! 	(float_extend:TF (match_operand:SF 1 "register_operand" "")))]
!   "FP_REGNO_P (REGNO (operands[1]))"
!   [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
!    (set (mem:TF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
  
  (define_insn "*dummy_extenddfxf2"
    [(set (match_operand:XF 0 "push_operand" "=<")
***************
*** 3045,3051 ****
  	(float_extend:XF (match_operand:DF 1 "register_operand" "")))]
    "FP_REGNO_P (REGNO (operands[1]))"
    [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
!    (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
  
  (define_expand "extendsfdf2"
    [(set (match_operand:DF 0 "nonimmediate_operand" "")
--- 3273,3292 ----
  	(float_extend:XF (match_operand:DF 1 "register_operand" "")))]
    "FP_REGNO_P (REGNO (operands[1]))"
    [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
!    (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
! 
! (define_insn "*dummy_extenddftf2"
!   [(set (match_operand:TF 0 "push_operand" "=<")
! 	(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "f")))]
!   "0"
!   "#")
! 
! (define_split
!   [(set (match_operand:TF 0 "push_operand" "")
! 	(float_extend:TF (match_operand:DF 1 "register_operand" "")))]
!   "FP_REGNO_P (REGNO (operands[1]))"
!   [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
!    (set (mem:TF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
  
  (define_expand "extendsfdf2"
    [(set (match_operand:DF 0 "nonimmediate_operand" "")
***************
*** 3132,3137 ****
--- 3373,3421 ----
    [(set_attr "type" "fmov")
     (set_attr "mode" "SF,XF")])
  
+ (define_expand "extendsftf2"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "")
+         (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))]
+   "TARGET_80387"
+   "
+ {
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+     operands[1] = force_reg (SFmode, operands[1]);
+ }")
+ 
+ (define_insn "*extendsftf2_1"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m")
+         (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+   "TARGET_80387
+    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (REG_P (operands[1])
+           && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp\\t%y0\";
+       else if (STACK_TOP_P (operands[0]))
+         return \"fld%z1\\t%y1\";
+       else
+         return \"fst\\t%y0\";
+ 
+     case 1:
+       /* There is no non-popping store to memory for XFmode.  So if
+ 	 we need one, follow the store with a load.  */
+       if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp%z0\\t%y0\\n\\tfld%z0\\t%y0\";
+       else
+         return \"fstp%z0\\t%y0\";
+ 
+     default:
+       abort ();
+     }
+ }"
+   [(set_attr "type" "fmov")
+    (set_attr "mode" "SF,XF")])
+ 
  (define_expand "extenddfxf2"
    [(set (match_operand:XF 0 "nonimmediate_operand" "")
          (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))]
***************
*** 3175,3180 ****
--- 3459,3507 ----
    [(set_attr "type" "fmov")
     (set_attr "mode" "DF,XF")])
  
+ (define_expand "extenddftf2"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "")
+         (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))]
+   "TARGET_80387"
+   "
+ {
+   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+     operands[1] = force_reg (DFmode, operands[1]);
+ }")
+ 
+ (define_insn "*extenddftf2_1"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m")
+         (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
+   "TARGET_80387
+    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (REG_P (operands[1])
+           && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp\\t%y0\";
+       else if (STACK_TOP_P (operands[0]))
+         return \"fld%z1\\t%y1\";
+       else
+         return \"fst\\t%y0\";
+ 
+     case 1:
+       /* There is no non-popping store to memory for XFmode.  So if
+ 	 we need one, follow the store with a load.  */
+       if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+         return \"fstp%z0\\t%y0\\n\\tfld%z0\\t%y0\";
+       else
+         return \"fstp%z0\\t%y0\";
+ 
+     default:
+       abort ();
+     }
+ }"
+   [(set_attr "type" "fmov")
+    (set_attr "mode" "DF,XF")])
+ 
  ;; %%% This seems bad bad news.
  ;; This cannot output into an f-reg because there is no way to be sure
  ;; of truncating in that case.  Otherwise this is just like a simple move
***************
*** 3311,3316 ****
--- 3638,3709 ----
     (set (match_dup 0) (match_dup 2))]
    "")
  
+ (define_expand "trunctfsf2"
+   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ 		   (float_truncate:SF
+ 		    (match_operand:TF 1 "register_operand" "")))
+ 	      (clobber (match_dup 2))])]
+   "TARGET_80387"
+   "operands[2] = assign_386_stack_local (SFmode, 0);")
+ 
+ (define_insn "*trunctfsf2_1"
+   [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f")
+ 	(float_truncate:SF
+ 	 (match_operand:TF 1 "register_operand" "f,0")))
+    (clobber (match_operand:SF 2 "memory_operand" "=m,m"))]
+   "TARGET_80387"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ 	return \"fstp%z0\\t%y0\";
+       else
+ 	return \"fst%z0\\t%y0\";
+     case 1:
+       return \"fstp%z2\\t%y2\;fld%z2\\t%y2\";
+     }
+   abort ();
+ }"
+   [(set_attr "type" "fmov,multi")
+    (set_attr "mode" "SF")])
+ 
+ (define_insn "*truncxfsf2_2"
+   [(set (match_operand:SF 0 "nonimmediate_operand" "=m")
+ 	(float_truncate:SF
+ 	 (match_operand:TF 1 "register_operand" "f")))]
+   "TARGET_80387"
+   "*
+ {
+   if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+     return \"fstp%z0\\t%y0\";
+   else
+     return \"fst%z0\\t%y0\";
+ }"
+   [(set_attr "type" "fmov")
+    (set_attr "mode" "SF")])
+ 
+ (define_split
+   [(set (match_operand:SF 0 "memory_operand" "")
+ 	(float_truncate:SF
+ 	 (match_operand:TF 1 "register_operand" "")))
+    (clobber (match_operand:SF 2 "memory_operand" ""))]
+   "TARGET_80387"
+   [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:SF 0 "register_operand" "")
+ 	(float_truncate:SF
+ 	 (match_operand:TF 1 "register_operand" "")))
+    (clobber (match_operand:SF 2 "memory_operand" ""))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
+    (set (match_dup 0) (match_dup 2))]
+   "")
+ 
+ 
  (define_expand "truncxfdf2"
    [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
  		   (float_truncate:DF
***************
*** 3376,3393 ****
     (set (match_dup 0) (match_dup 2))]
    "")
  
  
  ;; %%% Break up all these bad boys.
  
  ;; Signed conversion to DImode.
  
! (define_expand "fix_truncxfdi2"
    [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
! 		   (fix:DI (match_operand:XF 1 "register_operand" "")))
  	      (clobber (match_dup 2))
  	      (clobber (match_dup 3))
  	      (clobber (match_scratch:SI 4 ""))
! 	      (clobber (match_scratch:XF 5 ""))])]
    "TARGET_80387"
    "operands[2] = assign_386_stack_local (SImode, 0);
     operands[3] = assign_386_stack_local (DImode, 1);")
--- 3769,3862 ----
     (set (match_dup 0) (match_dup 2))]
    "")
  
+ (define_expand "trunctfdf2"
+   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ 		   (float_truncate:DF
+ 		    (match_operand:TF 1 "register_operand" "")))
+ 	      (clobber (match_dup 2))])]
+   "TARGET_80387"
+   "operands[2] = assign_386_stack_local (DFmode, 0);")
+ 
+ (define_insn "*trunctfdf2_1"
+   [(set (match_operand:DF 0 "nonimmediate_operand" "=m,f")
+ 	(float_truncate:DF
+ 	 (match_operand:TF 1 "register_operand" "f,0")))
+    (clobber (match_operand:DF 2 "memory_operand" "=m,m"))]
+   "TARGET_80387"
+   "*
+ {
+   switch (which_alternative)
+     {
+     case 0:
+       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ 	return \"fstp%z0\\t%y0\";
+       else
+ 	return \"fst%z0\\t%y0\";
+     case 1:
+       return \"fstp%z2\\t%y2\;fld%z2\\t%y2\";
+     }
+   abort ();
+ }"
+   [(set_attr "type" "fmov,multi")
+    (set_attr "mode" "DF")])
+ 
+ (define_insn "*truncxfdf2_2"
+   [(set (match_operand:DF 0 "memory_operand" "=m")
+ 	(float_truncate:DF
+ 	  (match_operand:TF 1 "register_operand" "f")))]
+   "TARGET_80387"
+   "*
+ {
+   if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+     return \"fstp%z0\\t%y0\";
+   else
+     return \"fst%z0\\t%y0\";
+ }"
+   [(set_attr "type" "fmov")
+    (set_attr "mode" "DF")])
+ 
+ (define_split
+   [(set (match_operand:DF 0 "memory_operand" "")
+ 	(float_truncate:DF
+ 	 (match_operand:TF 1 "register_operand" "")))
+    (clobber (match_operand:DF 2 "memory_operand" ""))]
+   "TARGET_80387"
+   [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:DF 0 "register_operand" "")
+ 	(float_truncate:DF
+ 	 (match_operand:TF 1 "register_operand" "")))
+    (clobber (match_operand:DF 2 "memory_operand" ""))]
+   "TARGET_80387 && reload_completed"
+   [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
+    (set (match_dup 0) (match_dup 2))]
+   "")
+ 
  
  ;; %%% Break up all these bad boys.
  
  ;; Signed conversion to DImode.
  
! (define_expand "fix_truncxfdi2"
!   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
! 		   (fix:DI (match_operand:XF 1 "register_operand" "")))
! 	      (clobber (match_dup 2))
! 	      (clobber (match_dup 3))
! 	      (clobber (match_scratch:SI 4 ""))
! 	      (clobber (match_scratch:XF 5 ""))])]
!   "TARGET_80387"
!   "operands[2] = assign_386_stack_local (SImode, 0);
!    operands[3] = assign_386_stack_local (DImode, 1);")
! 
! (define_expand "fix_trunctfdi2"
    [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
! 		   (fix:DI (match_operand:TF 1 "register_operand" "")))
  	      (clobber (match_dup 2))
  	      (clobber (match_dup 3))
  	      (clobber (match_scratch:SI 4 ""))
! 	      (clobber (match_scratch:TF 5 ""))])]
    "TARGET_80387"
    "operands[2] = assign_386_stack_local (SImode, 0);
     operands[3] = assign_386_stack_local (DImode, 1);")
***************
*** 3453,3458 ****
--- 3922,3937 ----
    "operands[2] = assign_386_stack_local (SImode, 0);
     operands[3] = assign_386_stack_local (SImode, 1);")
  
+ (define_expand "fix_trunctfsi2"
+   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ 		   (fix:SI (match_operand:TF 1 "register_operand" "")))
+ 	      (clobber (match_dup 2))
+ 	      (clobber (match_dup 3))
+ 	      (clobber (match_scratch:SI 4 ""))])]
+   "TARGET_80387"
+   "operands[2] = assign_386_stack_local (SImode, 0);
+    operands[3] = assign_386_stack_local (SImode, 1);")
+ 
  (define_expand "fix_truncdfsi2"
    [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
  		   (fix:SI (match_operand:DF 1 "register_operand" "")))
***************
*** 3509,3514 ****
--- 3988,4003 ----
    "operands[2] = assign_386_stack_local (SImode, 0);
     operands[3] = assign_386_stack_local (HImode, 1);")
  
+ (define_expand "fix_trunctfhi2"
+   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ 		   (fix:HI (match_operand:TF 1 "register_operand" "")))
+ 	      (clobber (match_dup 2))
+ 	      (clobber (match_dup 3))
+ 	      (clobber (match_scratch:SI 4 ""))])]
+   "TARGET_80387"
+   "operands[2] = assign_386_stack_local (SImode, 0);
+    operands[3] = assign_386_stack_local (HImode, 1);")
+ 
  (define_expand "fix_truncdfhi2"
    [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
  		   (fix:HI (match_operand:DF 1 "register_operand" "")))
***************
*** 3657,3662 ****
--- 4146,4162 ----
     (set_attr "mode" "XF")
     (set_attr "fp_int_src" "true")])
  
+ (define_insn "floathitf2"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(float:TF (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
+   "TARGET_80387"
+   "@
+    fild%z1\\t%1
+    #"
+   [(set_attr "type" "fmov,multi")
+    (set_attr "mode" "XF")
+    (set_attr "fp_int_src" "true")])
+ 
  (define_insn "floatsixf2"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,r")))]
***************
*** 3668,3673 ****
--- 4168,4184 ----
     (set_attr "mode" "XF")
     (set_attr "fp_int_src" "true")])
  
+ (define_insn "floatsitf2"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(float:TF (match_operand:SI 1 "nonimmediate_operand" "m,r")))]
+   "TARGET_80387"
+   "@
+    fild%z1\\t%1
+    #"
+   [(set_attr "type" "fmov,multi")
+    (set_attr "mode" "XF")
+    (set_attr "fp_int_src" "true")])
+ 
  (define_insn "floatdixf2"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
***************
*** 3679,3684 ****
--- 4190,4206 ----
     (set_attr "mode" "XF")
     (set_attr "fp_int_src" "true")])
  
+ (define_insn "floatditf2"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(float:TF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+   "TARGET_80387"
+   "@
+    fild%z1\\t%1
+    #"
+   [(set_attr "type" "fmov,multi")
+    (set_attr "mode" "XF")
+    (set_attr "fp_int_src" "true")])
+ 
  ;; %%% Kill these when reload knows how to do it.
  (define_split
    [(set (match_operand 0 "register_operand" "")
***************
*** 4679,4684 ****
--- 5201,5213 ----
    "TARGET_80387"
    "")
  
+ (define_expand "addtf3"
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(plus:TF (match_operand:TF 1 "register_operand" "")
+ 		 (match_operand:TF 2 "register_operand" "")))]
+   "TARGET_80387"
+   "")
+ 
  (define_expand "adddf3"
    [(set (match_operand:DF 0 "register_operand" "")
  	(plus:DF (match_operand:DF 1 "register_operand" "")
***************
*** 4890,4895 ****
--- 5419,5431 ----
    "TARGET_80387"
    "")
  
+ (define_expand "subtf3"
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(minus:TF (match_operand:TF 1 "register_operand" "")
+ 		  (match_operand:TF 2 "register_operand" "")))]
+   "TARGET_80387"
+   "")
+ 
  (define_expand "subdf3"
    [(set (match_operand:DF 0 "register_operand" "")
  	(minus:DF (match_operand:DF 1 "register_operand" "")
***************
*** 5064,5069 ****
--- 5600,5612 ----
    "TARGET_80387"
    "")
  
+ (define_expand "multf3"
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(mult:TF (match_operand:TF 1 "register_operand" "")
+ 		 (match_operand:TF 2 "register_operand" "")))]
+   "TARGET_80387"
+   "")
+ 
  (define_expand "muldf3"
    [(set (match_operand:DF 0 "register_operand" "")
  	(mult:DF (match_operand:DF 1 "register_operand" "")
***************
*** 5111,5116 ****
--- 5654,5666 ----
    "TARGET_80387"
    "")
  
+ (define_expand "divtf3"
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(div:TF (match_operand:TF 1 "register_operand" "")
+ 		(match_operand:TF 2 "register_operand" "")))]
+   "TARGET_80387"
+   "")
+ 
  (define_expand "divdf3"
    [(set (match_operand:DF 0 "register_operand" "")
   	(div:DF (match_operand:DF 1 "register_operand" "")
***************
*** 6340,6345 ****
--- 6890,6902 ----
    "TARGET_80387"
    "ix86_expand_unary_operator (NEG, XFmode, operands); DONE;")
  
+ (define_expand "negtf2"
+   [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ 		   (neg:TF (match_operand:TF 1 "nonimmediate_operand" "")))
+ 	      (clobber (reg:CC 17))])]
+   "TARGET_80387"
+   "ix86_expand_unary_operator (NEG, TFmode, operands); DONE;")
+ 
  ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
  ;; because of secondary memory needed to reload from class FLOAT_INT_REGS
  ;; to itself.
***************
*** 6369,6374 ****
--- 6926,6960 ----
    "operands[1] = GEN_INT (0x8000);
     operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + 2);")
  
+ ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
+ ;; because of secondary memory needed to reload from class FLOAT_INT_REGS
+ ;; to itself.
+ (define_insn "*negtf2_if"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,rm#f")
+ 	(neg:TF (match_operand:TF 1 "nonimmediate_operand" "0,0")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && ix86_unary_operator_ok (NEG, TFmode, operands)"
+   "#")
+ 
+ (define_split
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(neg:TF (match_operand:TF 1 "register_operand" "")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+   [(set (match_dup 0)
+ 	(neg:TF (match_dup 1)))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(neg:TF (match_operand:TF 1 "register_operand" "")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+   [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
+ 	      (clobber (reg:CC 17))])]
+   "operands[1] = GEN_INT (0x8000);
+    operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + 2);")
+ 
  ;; Conditionize these after reload. If they matches before reload, we 
  ;; lose the clobber and ability to use integer instructions.
  
***************
*** 6428,6433 ****
--- 7014,7048 ----
    [(set_attr "type" "fsgn")
     (set_attr "mode" "XF")
     (set_attr "ppro_uops" "few")])
+ 
+ (define_insn "*negtf2_1"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(neg:TF (match_operand:TF 1 "register_operand" "0")))]
+   "TARGET_80387 && reload_completed"
+   "fchs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "XF")
+    (set_attr "ppro_uops" "few")])
+ 
+ (define_insn "*negextenddftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(neg:TF (float_extend:TF
+ 		  (match_operand:DF 1 "register_operand" "0"))))]
+   "TARGET_80387"
+   "fchs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "XF")
+    (set_attr "ppro_uops" "few")])
+ 
+ (define_insn "*negextendsftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(neg:TF (float_extend:TF
+ 		  (match_operand:SF 1 "register_operand" "0"))))]
+   "TARGET_80387"
+   "fchs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "XF")
+    (set_attr "ppro_uops" "few")])
  
  ;; Absolute value instructions
  
***************
*** 6529,6534 ****
--- 7144,7156 ----
    "TARGET_80387"
    "ix86_expand_unary_operator (ABS, XFmode, operands); DONE;")
  
+ (define_expand "abstf2"
+   [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ 		   (neg:TF (match_operand:TF 1 "nonimmediate_operand" "")))
+ 	      (clobber (reg:CC 17))])]
+   "TARGET_80387"
+   "ix86_expand_unary_operator (ABS, TFmode, operands); DONE;")
+ 
  ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems
  ;; because of secondary memory needed to reload from class FLOAT_INT_REGS
  ;; to itself.
***************
*** 6558,6563 ****
--- 7180,7211 ----
    "operands[1] = GEN_INT (~0x8000);
     operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + 2);")
  
+ (define_insn "*abstf2_if"
+   [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,rm#f")
+ 	(abs:TF (match_operand:TF 1 "nonimmediate_operand" "0,0")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && ix86_unary_operator_ok (ABS, TFmode, operands)"
+   "#")
+ 
+ (define_split
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(abs:TF (match_operand:TF 1 "register_operand" "")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+   [(set (match_dup 0)
+ 	(abs:TF (match_dup 1)))]
+   "")
+ 
+ (define_split
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(abs:TF (match_operand:TF 1 "register_operand" "")))
+    (clobber (reg:CC 17))]
+   "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+   [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
+ 	      (clobber (reg:CC 17))])]
+   "operands[1] = GEN_INT (~0x8000);
+    operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + 2);")
+ 
  (define_insn "*abssf2_1"
    [(set (match_operand:SF 0 "register_operand" "=f")
  	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
***************
*** 6608,6613 ****
--- 7256,7287 ----
    "fabs"
    [(set_attr "type" "fsgn")
     (set_attr "mode" "XF")])
+ 
+ (define_insn "*abstf2_1"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(abs:TF (match_operand:TF 1 "register_operand" "0")))]
+   "TARGET_80387 && reload_completed"
+   "fabs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "DF")])
+ 
+ (define_insn "*absextenddftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(abs:TF (float_extend:TF
+ 	  (match_operand:DF 1 "register_operand" "0"))))]
+   "TARGET_80387"
+   "fabs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "XF")])
+ 
+ (define_insn "*absextendsftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(abs:TF (float_extend:TF
+ 	  (match_operand:SF 1 "register_operand" "0"))))]
+   "TARGET_80387"
+   "fabs"
+   [(set_attr "type" "fsgn")
+    (set_attr "mode" "XF")])
  
  ;; One complement instructions
  
***************
*** 9309,9314 ****
--- 9983,10001 ----
             (const_string "fop")))
     (set_attr "mode" "XF")])
  
+ (define_insn "*fop_tf_comm"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 			[(match_operand:TF 1 "register_operand" "%0")
+ 			 (match_operand:TF 2 "register_operand" "f")]))]
+   "TARGET_80387 && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (if_then_else (match_operand:TF 3 "mult_operator" "") 
+            (const_string "fmul")
+            (const_string "fop")))
+    (set_attr "mode" "XF")])
+ 
  (define_insn "*fop_sf_1"
    [(set (match_operand:SF 0 "register_operand" "=f,f")
  	(match_operator:SF 3 "binary_fp_operator"
***************
*** 9468,9473 ****
--- 10155,10177 ----
                (const_string "fop")))
     (set_attr "mode" "XF")])
  
+ (define_insn "*fop_tf_1"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 			[(match_operand:TF 1 "register_operand" "0,f")
+ 			 (match_operand:TF 2 "register_operand" "f,0")]))]
+   "TARGET_80387
+    && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "mode" "XF")])
+ 
  (define_insn "*fop_xf_2"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9486,9491 ****
--- 10190,10213 ----
     (set_attr "mode" "SI")
     (set_attr "ppro_uops" "many")])
  
+ (define_insn "*fop_tf_2"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	   [(float:TF (match_operand:SI 1 "nonimmediate_operand" "m,?r"))
+ 	    (match_operand:TF 2 "register_operand" "0,0")]))]
+   "TARGET_80387 && TARGET_USE_FIOP"
+   "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "fp_int_src" "true")
+    (set_attr "mode" "SI")
+    (set_attr "ppro_uops" "many")])
+ 
  (define_insn "*fop_xf_3"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9504,9509 ****
--- 10226,10249 ----
     (set_attr "mode" "SI")
     (set_attr "ppro_uops" "many")])
  
+ (define_insn "*fop_tf_3"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	  [(match_operand:TF 1 "register_operand" "0,0")
+ 	   (float:TF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))]
+   "TARGET_80387 && TARGET_USE_FIOP"
+   "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "fp_int_src" "true")
+    (set_attr "mode" "SI")
+    (set_attr "ppro_uops" "many")])
+ 
  (define_insn "*fop_xf_4"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9520,9525 ****
--- 10260,10281 ----
                (const_string "fop")))
     (set_attr "mode" "SF")])
  
+ (define_insn "*fop_tf_4"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	   [(float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
+ 	    (match_operand:TF 2 "register_operand" "0,f")]))]
+   "TARGET_80387"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "mode" "SF")])
+ 
  (define_insn "*fop_xf_5"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9537,9542 ****
--- 10293,10315 ----
                (const_string "fop")))
     (set_attr "mode" "SF")])
  
+ (define_insn "*fop_tf_5"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	  [(match_operand:TF 1 "register_operand" "0,f")
+ 	   (float_extend:TF
+ 	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
+   "TARGET_80387"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "mode" "SF")])
+ 
  (define_insn "*fop_xf_6"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9553,9558 ****
--- 10326,10347 ----
                (const_string "fop")))
     (set_attr "mode" "DF")])
  
+ (define_insn "*fop_tf_6"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	   [(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "fm,0"))
+ 	    (match_operand:TF 2 "register_operand" "0,f")]))]
+   "TARGET_80387"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "mode" "DF")])
+ 
  (define_insn "*fop_xf_7"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(match_operator:XF 3 "binary_fp_operator"
***************
*** 9570,9575 ****
--- 10359,10381 ----
                (const_string "fop")))
     (set_attr "mode" "DF")])
  
+ (define_insn "*fop_tf_7"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(match_operator:TF 3 "binary_fp_operator"
+ 	  [(match_operand:TF 1 "register_operand" "0,f")
+ 	   (float_extend:TF
+ 	    (match_operand:DF 2 "nonimmediate_operand" "fm,0"))]))]
+   "TARGET_80387"
+   "* return output_387_binary_op (insn, operands);"
+   [(set (attr "type") 
+         (cond [(match_operand:TF 3 "mult_operator" "") 
+                  (const_string "fmul")
+                (match_operand:TF 3 "div_operator" "") 
+                  (const_string "fdiv")
+               ]
+               (const_string "fop")))
+    (set_attr "mode" "DF")])
+ 
  (define_split
    [(set (match_operand 0 "register_operand" "")
  	(match_operator 3 "binary_fp_operator"
***************
*** 9647,9652 ****
--- 10453,10468 ----
     (set_attr "mode" "XF")
     (set_attr "athlon_decode" "direct")])
  
+ (define_insn "sqrttf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(sqrt:TF (match_operand:TF 1 "register_operand" "0")))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+    && (TARGET_IEEE_FP || flag_fast_math) "
+   "fsqrt"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")
+    (set_attr "athlon_decode" "direct")])
+ 
  (define_insn "*sqrtextenddfxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(sqrt:XF (float_extend:XF
***************
*** 9657,9662 ****
--- 10473,10488 ----
     (set_attr "mode" "XF")
     (set_attr "athlon_decode" "direct")])
  
+ (define_insn "*sqrtextenddftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(sqrt:TF (float_extend:TF
+ 		  (match_operand:DF 1 "register_operand" "0"))))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
+   "fsqrt"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")
+    (set_attr "athlon_decode" "direct")])
+ 
  (define_insn "*sqrtextendsfxf2"
    [(set (match_operand:XF 0 "register_operand" "=f")
  	(sqrt:XF (float_extend:XF
***************
*** 9667,9672 ****
--- 10493,10508 ----
     (set_attr "mode" "XF")
     (set_attr "athlon_decode" "direct")])
  
+ (define_insn "*sqrtextendsftf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(sqrt:TF (float_extend:TF
+ 		  (match_operand:SF 1 "register_operand" "0"))))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
+   "fsqrt"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")
+    (set_attr "athlon_decode" "direct")])
+ 
  (define_insn "sindf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
***************
*** 9700,9705 ****
--- 10536,10549 ----
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
  
+ (define_insn "sintf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 1))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
+   "fsin"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")])
+ 
  (define_insn "cosdf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
***************
*** 9732,9737 ****
--- 10576,10589 ----
    "fcos"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])
+ 
+ (define_insn "costf2"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(unspec:TF [(match_operand:TF 1 "register_operand" "0")] 2))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
+   "fcos"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")])
  
  ;; Block operation instructions
  
***************
*** 10686,10697 ****
--- 11538,11570 ----
    "TARGET_CMOVE"
    "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
  
+ (define_expand "movtfcc"
+   [(set (match_operand:TF 0 "register_operand" "")
+ 	(if_then_else:TF (match_operand 1 "comparison_operator" "")
+ 			 (match_operand:TF 2 "register_operand" "")
+ 			 (match_operand:TF 3 "register_operand" "")))]
+   "TARGET_CMOVE"
+   "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;")
+ 
  (define_insn "*movxfcc_1"
    [(set (match_operand:XF 0 "register_operand" "=f,f")
  	(if_then_else:XF (match_operator 1 "fcmov_comparison_operator" 
  				[(reg 17) (const_int 0)])
  		      (match_operand:XF 2 "register_operand" "f,0")
  		      (match_operand:XF 3 "register_operand" "0,f")))]
+   "TARGET_CMOVE"
+   "@
+    fcmov%F1\\t{%2, %0|%0, %2}
+    fcmov%f1\\t{%3, %0|%0, %3}"
+   [(set_attr "type" "fcmov")
+    (set_attr "mode" "XF")])
+ 
+ (define_insn "*movtfcc_1"
+   [(set (match_operand:TF 0 "register_operand" "=f,f")
+ 	(if_then_else:TF (match_operator 1 "fcmov_comparison_operator" 
+ 				[(reg 17) (const_int 0)])
+ 		      (match_operand:TF 2 "register_operand" "f,0")
+ 		      (match_operand:TF 3 "register_operand" "0,f")))]
    "TARGET_CMOVE"
    "@
     fcmov%F1\\t{%2, %0|%0, %2}
*** invoke.texi.old	Tue Jul 18 02:38:17 2000
--- invoke.texi	Tue Jul 18 02:45:42 2000
*************** in the following sections.
*** 375,381 ****
  -malign-jumps=@var{num}  -malign-loops=@var{num}
  -malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
  -mthreads -mno-align-stringops -minline-all-stringops
! -mpush-args -maccumulate-outgoing-args
  
  @emph{HPPA Options}
  -march=@var{architecture type}
--- 375,382 ----
  -malign-jumps=@var{num}  -malign-loops=@var{num}
  -malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
  -mthreads -mno-align-stringops -minline-all-stringops
! -mpush-args -maccumulate-outgoing-args -m128bit-long-double
! -m96bit-long-double
  
  @emph{HPPA Options}
  -march=@var{architecture type}
*************** boundary.  Aligning @code{double} variab
*** 6189,6197 ****
  produce code that runs somewhat faster on a @samp{Pentium} at the
  expense of more memory.
  
! @strong{Warning:} if you use the @samp{-malign-double} switch,
! structures containing the above types will be aligned differently than
! the published application binary interface specifications for the 386.
  
  @item -msvr3-shlib
  @itemx -mno-svr3-shlib
--- 6190,6211 ----
  produce code that runs somewhat faster on a @samp{Pentium} at the
  expense of more memory.
  
! @item -m128bit-long-double
! @itemx -m128bit-long-double
! Control the size of @code{long double} type. i386 application binary interface
! specify the size to be 12 bytes, while modern architectures (Pentium and newer)
! preffer @code{long double} aligned to 8 or 16 byte boundary.  This is
! impossible to reach with 12 byte long doubles in the array accesses.
! 
! @strong{Warning:} if you use the @samp{-m128bit-long-double} switch, the
! structures and arrays containing @code{long double} will change their size as
! well as function calling convention for function taking @code{long double}
! will be modified. 
! 
! @item -m96bit-long-double
! @itemx -m96bit-long-double
! Set the size of @code{long double} to 96 bytes as requires by the i386
! application binary interface.  This is the default.
  
  @item -msvr3-shlib
  @itemx -mno-svr3-shlib
*** invoke.texi.old	Tue Jul 18 02:38:17 2000
--- invoke.texi	Tue Jul 18 02:56:24 2000
*************** in the following sections.
*** 375,381 ****
  -malign-jumps=@var{num}  -malign-loops=@var{num}
  -malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
  -mthreads -mno-align-stringops -minline-all-stringops
! -mpush-args -maccumulate-outgoing-args
  
  @emph{HPPA Options}
  -march=@var{architecture type}
--- 375,382 ----
  -malign-jumps=@var{num}  -malign-loops=@var{num}
  -malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
  -mthreads -mno-align-stringops -minline-all-stringops
! -mpush-args -maccumulate-outgoing-args -m128bit-long-double
! -m96bit-long-double
  
  @emph{HPPA Options}
  -march=@var{architecture type}
*************** expense of more memory.
*** 6192,6197 ****
--- 6193,6215 ----
  @strong{Warning:} if you use the @samp{-malign-double} switch,
  structures containing the above types will be aligned differently than
  the published application binary interface specifications for the 386.
+ 
+ @item -m128bit-long-double
+ @itemx -m128bit-long-double
+ Control the size of @code{long double} type. i386 application binary interface
+ specify the size to be 12 bytes, while modern architectures (Pentium and newer)
+ preffer @code{long double} aligned to 8 or 16 byte boundary.  This is
+ impossible to reach with 12 byte long doubles in the array accesses.
+ 
+ @strong{Warning:} if you use the @samp{-m128bit-long-double} switch, the
+ structures and arrays containing @code{long double} will change their size as
+ well as function calling convention for function taking @code{long double}
+ will be modified. 
+ 
+ @item -m96bit-long-double
+ @itemx -m96bit-long-double
+ Set the size of @code{long double} to 96 bytes as requires by the i386
+ application binary interface.  This is the default.
  
  @item -msvr3-shlib
  @itemx -mno-svr3-shlib

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]