OSDN Git Service

* config/sparc/sparc.c (emit_soft_tfmode_libcall,
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Apr 2002 19:17:07 +0000 (19:17 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Apr 2002 19:17:07 +0000 (19:17 +0000)
        emit_soft_tfmode_binop, emit_soft_tfmode_unop, emit_soft_tfmode_cvt,
        emit_hard_tfmode_operation, emit_tfmode_binop, emit_tfmode_unop,
        emit_tfmode_cvt): New.
        * config/sparc/sparc.md (extendsftf2, extenddftf2, trunctfsf2,
        trunctfdf2, floatsitf2, floatunssitf2, floatditf2, floatunsditf2,
        fix_trunctfsi2, fixuns_trunctfsi2, fix_trunctfdi2, fixuns_trunctfdi2,
        addtf3, subtf3, multf3, divtf3, sqrttf2): Use them.
        * config/sparc/sparc-protos.h: Update.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52965 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md

index 981185e..174a7ee 100644 (file)
@@ -1,3 +1,15 @@
+2002-04-30  Richard Henderson  <rth@redhat.com>
+
+       * config/sparc/sparc.c (emit_soft_tfmode_libcall,
+       emit_soft_tfmode_binop, emit_soft_tfmode_unop, emit_soft_tfmode_cvt,
+       emit_hard_tfmode_operation, emit_tfmode_binop, emit_tfmode_unop,
+       emit_tfmode_cvt): New.
+       * config/sparc/sparc.md (extendsftf2, extenddftf2, trunctfsf2,
+       trunctfdf2, floatsitf2, floatunssitf2, floatditf2, floatunsditf2,
+       fix_trunctfsi2, fixuns_trunctfsi2, fix_trunctfdi2, fixuns_trunctfdi2,
+       addtf3, subtf3, multf3, divtf3, sqrttf2): Use them.
+       * config/sparc/sparc-protos.h: Update.
+
 2002-04-30  Janis Johnson  <janis187@us.ibm.com>
 
        * install.texi (Final install): Add to the list of info to include
index fef6ecb..5f6343b 100644 (file)
@@ -74,6 +74,9 @@ extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
 extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
 extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
 extern void sparc_emit_floatunsdi PARAMS ((rtx [2]));
+extern void emit_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+extern void emit_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+extern void emit_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
 /* This function handles all v9 scc insns */
 extern int gen_v9_scc PARAMS ((enum rtx_code, rtx *));
 extern void sparc_initialize_trampoline PARAMS ((rtx, rtx, rtx));
index e564e46..0bac7c9 100644 (file)
@@ -168,6 +168,12 @@ static void sparc_sched_init PARAMS ((FILE *, int, int));
 static int sparc_use_dfa_pipeline_interface PARAMS ((void));
 static int sparc_use_sched_lookahead PARAMS ((void));
 static rtx sparc_cycle_display PARAMS ((int, rtx));
+
+static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));
+static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
+static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
 \f
 /* Option handling.  */
 
@@ -2456,6 +2462,304 @@ gen_df_reg (reg, low)
   return gen_rtx_REG (DFmode, regno);
 }
 \f
+/* Generate a call to FUNC with OPERANDS.  Operand 0 is the return value.
+   Unlike normal calls, TFmode operands are passed by reference.  It is
+   assumed that no more than 3 operands are required.  */
+
+static void
+emit_soft_tfmode_libcall (func_name, nargs, operands)
+     const char *func_name;
+     int nargs;
+     rtx *operands;
+{
+  rtx ret_slot = NULL, arg[3], func_sym;
+  int i;
+
+  /* We only expect to be called for conversions, unary, and binary ops.  */
+  if (nargs < 2 || nargs > 3)
+    abort ();
+
+  for (i = 0; i < nargs; ++i)
+    {
+      rtx this_arg = operands[i];
+      rtx this_slot;
+
+      /* TFmode arguments and return values are passed by reference.  */
+      if (GET_MODE (this_arg) == TFmode)
+       {
+         if (GET_CODE (this_arg) == MEM)
+           this_arg = XEXP (this_arg, 0);
+         else if (CONSTANT_P (this_arg))
+           {
+             this_slot = force_const_mem (TFmode, this_arg);
+             this_arg = XEXP (this_slot, 0);
+           }
+         else
+           {
+             this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode), 0);
+
+             /* Operand 0 is the return value.  We'll copy it out later.  */
+             if (i > 0)
+               emit_move_insn (this_slot, this_arg);
+             else
+               ret_slot = this_slot;
+
+             this_arg = XEXP (this_slot, 0);
+           }
+       }
+
+      arg[i] = this_arg;
+    }
+
+  func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
+
+  if (GET_MODE (operands[0]) == TFmode)
+    {
+      if (nargs == 2)
+       emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 2,
+                          arg[0], GET_MODE (arg[0]),
+                          arg[1], GET_MODE (arg[1]));
+      else
+       emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 3,
+                          arg[0], GET_MODE (arg[0]),
+                          arg[1], GET_MODE (arg[1]),
+                          arg[2], GET_MODE (arg[2]));
+
+      if (ret_slot)
+       emit_move_insn (operands[0], ret_slot);
+    }
+  else
+    {
+      rtx ret;
+
+      if (nargs != 2)
+       abort ();
+
+      ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
+                                    GET_MODE (operands[0]), 1,
+                                    arg[1], GET_MODE (arg[1]));
+
+      if (ret != operands[0])
+       emit_move_insn (operands[0], ret);
+    }
+}
+
+/* Expand soft-float TFmode calls to sparc abi routines.  */
+
+static void
+emit_soft_tfmode_binop (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  const char *func;
+
+  switch (code)
+    {
+    case PLUS:
+      func = "_Qp_add";
+      break;
+    case MINUS:
+      func = "_Qp_sub";
+      break;
+    case MULT:
+      func = "_Qp_mul";
+      break;
+    case DIV:
+      func = "_Qp_div";
+      break;
+    default:
+      abort ();
+    }
+
+  emit_soft_tfmode_libcall (func, 3, operands);
+}
+
+static void
+emit_soft_tfmode_unop (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  const char *func;
+
+  switch (code)
+    {
+    case SQRT:
+      func = "_Qp_sqrt";
+      break;
+    default:
+      abort ();
+    }
+
+  emit_soft_tfmode_libcall (func, 2, operands);
+}
+
+static void
+emit_soft_tfmode_cvt (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  const char *func;
+
+  switch (code)
+    {
+    case FLOAT_EXTEND:
+      switch (GET_MODE (operands[1]))
+       {
+       case SFmode:
+         func = "_Qp_stoq";
+         break;
+       case DFmode:
+         func = "_Qp_dtoq";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case FLOAT_TRUNCATE:
+      switch (GET_MODE (operands[0]))
+       {
+       case SFmode:
+         func = "_Qp_qtos";
+         break;
+       case DFmode:
+         func = "_Qp_qtod";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case FLOAT:
+      switch (GET_MODE (operands[1]))
+       {
+       case SImode:
+         func = "_Qp_itoq";
+         break;
+       case DImode:
+         func = "_Qp_xtoq";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case UNSIGNED_FLOAT:
+      switch (GET_MODE (operands[1]))
+       {
+       case SImode:
+         func = "_Qp_uitoq";
+         break;
+       case DImode:
+         func = "_Qp_uxtoq";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case FIX:
+      switch (GET_MODE (operands[0]))
+       {
+       case SImode:
+         func = "_Qp_qtoi";
+         break;
+       case DImode:
+         func = "_Qp_qtox";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case UNSIGNED_FIX:
+      switch (GET_MODE (operands[0]))
+       {
+       case SImode:
+         func = "_Qp_qtoui";
+         break;
+       case DImode:
+         func = "_Qp_qtoux";
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    default:
+      abort ();
+    }
+
+  emit_soft_tfmode_libcall (func, 2, operands);
+}
+
+/* Expand a hard-float tfmode operation.  All arguments must be in
+   registers.  */
+
+static void
+emit_hard_tfmode_operation (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  rtx op, dest;
+
+  if (GET_RTX_CLASS (code) == '1')
+    {
+      operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+      op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
+    }
+  else
+    {
+      operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+      operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+      op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
+                          operands[1], operands[2]);
+    }
+
+  if (register_operand (operands[0], VOIDmode))
+    dest = operands[0];
+  else
+    dest = gen_reg_rtx (GET_MODE (operands[0]));
+
+  emit_insn (gen_rtx_SET (VOIDmode, dest, op));
+
+  if (dest != operands[0])
+    emit_move_insn (operands[0], dest);
+}
+
+void
+emit_tfmode_binop (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  if (TARGET_HARD_QUAD)
+    emit_hard_tfmode_operation (code, operands);
+  else
+    emit_soft_tfmode_binop (code, operands);
+}
+
+void
+emit_tfmode_unop (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  if (TARGET_HARD_QUAD)
+    emit_hard_tfmode_operation (code, operands);
+  else
+    emit_soft_tfmode_unop (code, operands);
+}
+
+void
+emit_tfmode_cvt (code, operands)
+     enum rtx_code code;
+     rtx *operands;
+{
+  if (TARGET_HARD_QUAD)
+    emit_hard_tfmode_operation (code, operands);
+  else
+    emit_soft_tfmode_cvt (code, operands);
+}
+\f
 /* Return nonzero if a return peephole merging return with
    setting of output register is ok.  */
 int
index 0932c84..db12cfe 100644 (file)
    (set_attr "fptype" "double")])
 
 (define_expand "extendsftf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
        (float_extend:TF
-        (match_operand:SF 1 "register_operand" "f")))]
+        (match_operand:SF 1 "register_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_stoq\"), LCT_NORMAL,
-                        VOIDmode, 2,
-                        XEXP (slot0, 0), Pmode,
-                        operands[1], SFmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
 
 (define_insn "*extendsftf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
   [(set_attr "type" "fp")])
 
 (define_expand "extenddftf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
        (float_extend:TF
-        (match_operand:DF 1 "register_operand" "e")))]
+        (match_operand:DF 1 "register_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_dtoq\"), LCT_NORMAL,
-                        VOIDmode, 2,
-                        XEXP (slot0, 0), Pmode,
-                        operands[1], DFmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
 
 (define_insn "*extenddftf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
    (set_attr "fptype" "double")])
 
 (define_expand "trunctfsf2"
-  [(set (match_operand:SF 0 "register_operand" "=f")
+  [(set (match_operand:SF 0 "register_operand" "")
        (float_truncate:SF
-        (match_operand:TF 1 "register_operand" "e")))]
+        (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-       }
-      else
-       slot0 = operands[1];
-
-      emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtos\"),
-                              operands[0], LCT_NORMAL, SFmode, 1,
-                              XEXP (slot0, 0), Pmode);
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
 
 (define_insn "*trunctfsf2_hq"
   [(set (match_operand:SF 0 "register_operand" "=f")
   [(set_attr "type" "fp")])
 
 (define_expand "trunctfdf2"
-  [(set (match_operand:DF 0 "register_operand" "=f")
+  [(set (match_operand:DF 0 "register_operand" "")
        (float_truncate:DF
-        (match_operand:TF 1 "register_operand" "e")))]
+        (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-       }
-      else
-       slot0 = operands[1];
-
-      emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtod\"),
-                              operands[0], LCT_NORMAL, DFmode, 1,
-                              XEXP (slot0, 0), Pmode);
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
 
 (define_insn "*trunctfdf2_hq"
   [(set (match_operand:DF 0 "register_operand" "=e")
    (set_attr "fptype" "double")])
 
 (define_expand "floatsitf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-       (float:TF (match_operand:SI 1 "register_operand" "f")))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (float:TF (match_operand:SI 1 "register_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[1];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_itoq\"), 0,
-                        VOIDmode, 2,
-                        XEXP (slot0, 0), Pmode,
-                        operands[1], SImode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT, operands); DONE;")
 
 (define_insn "*floatsitf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
   [(set_attr "type" "fp")])
 
 (define_expand "floatunssitf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-       (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
-  "
-{
-  rtx slot0;
-
-  if (GET_CODE (operands[1]) != MEM)
-    slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-  else
-    slot0 = operands[1];
-
-  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uitoq\"), 0,
-                    VOIDmode, 2,
-                    XEXP (slot0, 0), Pmode,
-                    operands[1], SImode);
-
-  if (GET_CODE (operands[0]) != MEM)
-    emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-  DONE;
-}")
+  "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
 
 ;; Now the same for 64 bit sources.
 
   "sparc_emit_floatunsdi (operands); DONE;")
 
 (define_expand "floatditf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-       (float:TF (match_operand:DI 1 "register_operand" "e")))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (float:TF (match_operand:DI 1 "register_operand" "")))]
   "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[1];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_xtoq\"), 0,
-                        VOIDmode, 2,
-                        XEXP (slot0, 0), Pmode,
-                        operands[1], DImode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FLOAT, operands); DONE;")
 
 (define_insn "*floatditf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
   [(set_attr "type" "fp")])
 
 (define_expand "floatunsditf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-       (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
-  "
-{
-  rtx slot0;
-
-  if (GET_CODE (operands[1]) != MEM)
-    slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-  else
-    slot0 = operands[1];
-
-  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uxtoq\"), 0,
-                    VOIDmode, 2,
-                    XEXP (slot0, 0), Pmode,
-                    operands[1], DImode);
-
-  if (GET_CODE (operands[0]) != MEM)
-    emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-  DONE;
-}")
+  "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
 
 ;; Convert a float to an actual integer.
 ;; Truncation is performed as part of the conversion.
    (set_attr "fptype" "double")])
 
 (define_expand "fix_trunctfsi2"
-  [(set (match_operand:SI 0 "register_operand" "=f")
-       (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (fix:SI (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-       }
-      else
-       slot0 = operands[1];
-
-      emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
-                              operands[0], LCT_NORMAL, SImode, 1,
-                              XEXP (slot0, 0), Pmode);
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FIX, operands); DONE;")
 
 (define_insn "*fix_trunctfsi2_hq"
   [(set (match_operand:SI 0 "register_operand" "=f")
-       (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+       (fix:SI (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
   "fqtoi\\t%1, %0"
   [(set_attr "type" "fp")])
 
 (define_expand "fixuns_trunctfsi2"
-  [(set (match_operand:SI 0 "register_operand" "=f")
-       (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
-  "
-{
-  rtx slot0;
-
-  if (GET_CODE (operands[1]) != MEM)
-    {
-      slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-    }
-  else
-    slot0 = operands[1];
-
-  emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
-                          operands[0], LCT_NORMAL, SImode, 1,
-                          XEXP (slot0, 0), Pmode);
-  DONE;
-}")
+  "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
 
 ;; Now the same, for V9 targets
 
    (set_attr "fptype" "double")])
 
 (define_expand "fix_trunctfdi2"
-  [(set (match_operand:DI 0 "register_operand" "=e")
-       (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  [(set (match_operand:DI 0 "register_operand" "")
+       (fix:DI (match_operand:TF 1 "general_operand" "")))]
   "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0;
-
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-       }
-      else
-       slot0 = operands[1];
-
-      emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
-                              operands[0], LCT_NORMAL, DImode, 1,
-                              XEXP (slot0, 0), Pmode);
-      DONE;
-    }
-}")
+  "emit_tfmode_cvt (FIX, operands); DONE;")
 
 (define_insn "*fix_trunctfdi2_hq"
   [(set (match_operand:DI 0 "register_operand" "=e")
-       (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+       (fix:DI (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
   "fqtox\\t%1, %0"
   [(set_attr "type" "fp")])
 
 (define_expand "fixuns_trunctfdi2"
-  [(set (match_operand:DI 0 "register_operand" "=f")
-       (unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  [(set (match_operand:DI 0 "register_operand" "")
+       (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
-  "
-{
-  rtx slot0;
-
-  if (GET_CODE (operands[1]) != MEM)
-    {
-      slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
-    }
-  else
-    slot0 = operands[1];
-
-  emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoux\"),
-                          operands[0], LCT_NORMAL, DImode, 1,
-                          XEXP (slot0, 0), Pmode);
-  DONE;
-}")
-
+  "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
 \f
 ;;- arithmetic instructions
 
        (plus:TF (match_operand:TF 1 "general_operand" "")
                 (match_operand:TF 2 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0, slot1, slot2;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
-       }
-      else
-       slot1 = operands[1];
-      if (GET_CODE (operands[2]) != MEM)
-       {
-         slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
-       }
-      else
-       slot2 = operands[2];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_add\"), 0,
-                        VOIDmode, 3,
-                        XEXP (slot0, 0), Pmode,
-                        XEXP (slot1, 0), Pmode,
-                        XEXP (slot2, 0), Pmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_binop (PLUS, operands); DONE;")
 
 (define_insn "*addtf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (minus:TF (match_operand:TF 1 "general_operand" "")
                  (match_operand:TF 2 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0, slot1, slot2;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
-       }
-      else
-       slot1 = operands[1];
-      if (GET_CODE (operands[2]) != MEM)
-       {
-         slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
-       }
-      else
-       slot2 = operands[2];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sub\"), 0,
-                        VOIDmode, 3,
-                        XEXP (slot0, 0), Pmode,
-                        XEXP (slot1, 0), Pmode,
-                        XEXP (slot2, 0), Pmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_binop (MINUS, operands); DONE;")
 
 (define_insn "*subtf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (mult:TF (match_operand:TF 1 "general_operand" "")
                 (match_operand:TF 2 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0, slot1, slot2;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
-       }
-      else
-       slot1 = operands[1];
-      if (GET_CODE (operands[2]) != MEM)
-       {
-         slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
-       }
-      else
-       slot2 = operands[2];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_mul\"), 0,
-                        VOIDmode, 3,
-                        XEXP (slot0, 0), Pmode,
-                        XEXP (slot1, 0), Pmode,
-                        XEXP (slot2, 0), Pmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_binop (MULT, operands); DONE;")
 
 (define_insn "*multf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
        (div:TF (match_operand:TF 1 "general_operand" "")
                (match_operand:TF 2 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0, slot1, slot2;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
-       }
-      else
-       slot1 = operands[1];
-      if (GET_CODE (operands[2]) != MEM)
-       {
-         slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
-       }
-      else
-       slot2 = operands[2];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_div\"), 0,
-                        VOIDmode, 3,
-                        XEXP (slot0, 0), Pmode,
-                        XEXP (slot1, 0), Pmode,
-                        XEXP (slot2, 0), Pmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_binop (DIV, operands); DONE;")
 
 ;; don't have timing for quad-prec. divide.
 (define_insn "*divtf3_hq"
   [(set_attr "type" "fpmove")])
 
 (define_expand "sqrttf2"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-       (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+       (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
   "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-  "
-{
-  if (! TARGET_HARD_QUAD)
-    {
-      rtx slot0, slot1;
-
-      if (GET_CODE (operands[0]) != MEM)
-       slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      else
-       slot0 = operands[0];
-      if (GET_CODE (operands[1]) != MEM)
-       {
-         slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-         emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
-       }
-      else
-       slot1 = operands[1];
-
-      emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sqrt\"), 0,
-                        VOIDmode, 2,
-                        XEXP (slot0, 0), Pmode,
-                        XEXP (slot1, 0), Pmode);
-
-      if (GET_CODE (operands[0]) != MEM)
-       emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
-      DONE;
-    }
-}")
+  "emit_tfmode_unop (SQRT, operands); DONE;")
 
 (define_insn "*sqrttf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")