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]

[PATCH] Sparc _Qp_* support


Hi!

Sparc 64bit ABI requires different syntax of the quad floating point software
emulation (_Qp_* routines) than what is common in gcc.
128bit long doubles are passed by reference to these functions and if
it returns a long double, they take the first argument as a pointer to that
long double.
This patch adds support for this. It does not generate very efficient code
but at least works according to the ABI. Once reload will handle the case
where it sees a "m"-only patterns and is able to spill that pseudo into the
stack because of that, I can rewrite some of these patterns to make them
more efficient.

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jakub@redhat.com | http://sunsite.mff.cuni.cz/~jj
Linux version 2.3.18 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________
1999-12-07  Jakub Jelinek  <jakub@redhat.com>

	* config/sparc/sparc.c (sparc_emit_float_lib_cmp): New function.
	* config/sparc/sparc-protos.h (sparc_emit_float_lib_cmp): Prototype.
	* config/sparc/sparc.h (*_LIBCALL): Only use for _Q_*
	routines, _Qp_* cannot be handled like that now.
	(INIT_TARGET_OPTABS): Likewise.
	* config/sparc/sparc.md (cmptf): Accept soft float ARCH64.
	(seq, sne, sgt, sge, slt, sle, beq, bne, bgt, bge, blt, ble): Call
	sparc_emit_float_lib_cmp if ARCH64 and soft float.
	(extendsftf2, extenddftf2, trunctfsf2, trunctfdf2, floatsitf2,
	floatditf2, fix_trunctfsi2, fix_trunctfdi2, addtf3, subtf3, multf3,
	divtf3, sqrttf3): New expanders.
	(extendsftf2_hq, extenddftf2_hq, trunctfsf2_hq, trunctfdf2_hq,
	floatsitf2_hq, floatditf2_hq, fix_trunctfsi2_hq, fix_trunctfdi2_hq,
	addtf3_hq, subtf3_hq, multf3_hq, divtf3_hq, sqrttf3_hq): Rename from
	non-_hq patterns.
	
--- gcc/config/sparc/sparc.c.jj	Wed Dec  1 09:04:29 1999
+++ gcc/config/sparc/sparc.c	Wed Dec  1 09:17:50 1999
@@ -4680,6 +4687,77 @@ output_cbranch (op, label, reversed, ann
   return string;
 }
 
+/* Emit a library call comparison between floating point X and Y.
+   COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
+   TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode
+   values as arguments instead of the TFmode registers themselves,
+   that's why we cannot call emit_float_lib_cmp.  */
+void
+sparc_emit_float_lib_cmp (x, y, comparison)
+     rtx x, y;
+     enum rtx_code comparison;
+{
+  const char *qpfunc;
+  rtx slot0, slot1, result;
+
+  switch (comparison)
+    {
+    case EQ:
+      qpfunc = "_Qp_feq";
+      break;
+
+    case NE:
+      qpfunc = "_Qp_fne";
+      break;
+
+    case GT:
+      qpfunc = "_Qp_fgt";
+      break;
+
+    case GE:
+      qpfunc = "_Qp_fge";
+      break;
+
+    case LT:
+      qpfunc = "_Qp_flt";
+      break;
+
+    case LE:
+      qpfunc = "_Qp_fle";
+      break;
+
+    default:
+      abort();
+      break;
+    }
+
+  if (GET_CODE (x) != MEM)
+    {
+      slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+      emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
+    }
+
+  if (GET_CODE (y) != MEM)
+    {
+      slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+      emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+    }
+
+  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, qpfunc), 1,
+                     DImode, 2,
+                     XEXP (slot0, 0), Pmode,
+                     XEXP (slot1, 0), Pmode);
+
+  /* Immediately move the result of the libcall into a pseudo
+     register so reload doesn't clobber the value if it needs
+     the return register for a spill reg.  */
+  result = gen_reg_rtx (DImode);
+  emit_move_insn (result, hard_libcall_value (DImode));
+
+  emit_cmp_insn (result, const0_rtx, comparison,
+                 NULL_RTX, DImode, 0, 0);
+}
+          
 /* Return the string to output a conditional branch to LABEL, testing
    register REG.  LABEL is the operand number of the label; REG is the
    operand number of the reg.  OP is the conditional expression.  The mode
--- gcc/config/sparc/sparc-protos.h.jj	Wed Dec  1 19:21:51 1999
+++ gcc/config/sparc/sparc-protos.h	Tue Dec  7 15:10:43 1999
@@ -79,6 +79,7 @@ extern void sparc_flat_save_restore PARA
 #ifdef RTX_CODE
 /* Define the function that build the compare insn for scc and bcc.  */
 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));
 /* 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));
--- gcc/config/sparc/sparc.h.jj	Wed Dec  1 09:04:33 1999
+++ gcc/config/sparc/sparc.h	Wed Dec  1 09:17:50 1999
@@ -2658,26 +2681,25 @@ do {                                    
 #define MULSI3_LIBCALL "*.umul"
 
 /* Define library calls for quad FP operations.  These are all part of the
-   SPARC ABI.
-   ??? ARCH64 still does not work as the _Qp_* routines take pointers.  */
-#define ADDTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_add" : "_Q_add")
-#define SUBTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_sub" : "_Q_sub")
-#define NEGTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_neg" : "_Q_neg")
-#define MULTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_mul" : "_Q_mul")
-#define DIVTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_div" : "_Q_div")
-#define FLOATSITF2_LIBCALL (TARGET_ARCH64 ? "_Qp_itoq" : "_Q_itoq")
-#define FIX_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoi" : "_Q_qtoi")
-#define FIXUNS_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoui" : "_Q_qtou")
-#define EXTENDSFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_stoq" : "_Q_stoq")
-#define TRUNCTFSF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtos" :  "_Q_qtos")
-#define EXTENDDFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_dtoq" : "_Q_dtoq")
-#define TRUNCTFDF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtod" : "_Q_qtod")
-#define EQTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq")
-#define NETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne")
-#define GTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt")
-#define GETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge")
-#define LTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt")
-#define LETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle")
+   SPARC 32bit ABI.  */
+#define ADDTF3_LIBCALL "_Q_add"
+#define SUBTF3_LIBCALL "_Q_sub"
+#define NEGTF2_LIBCALL "_Q_neg"
+#define MULTF3_LIBCALL "_Q_mul"
+#define DIVTF3_LIBCALL "_Q_div"
+#define FLOATSITF2_LIBCALL "_Q_itoq"
+#define FIX_TRUNCTFSI2_LIBCALL "_Q_qtoi"
+#define FIXUNS_TRUNCTFSI2_LIBCALL "_Q_qtou"
+#define EXTENDSFTF2_LIBCALL "_Q_stoq"
+#define TRUNCTFSF2_LIBCALL "_Q_qtos"
+#define EXTENDDFTF2_LIBCALL "_Q_dtoq"
+#define TRUNCTFDF2_LIBCALL "_Q_qtod"
+#define EQTF2_LIBCALL "_Q_feq"
+#define NETF2_LIBCALL "_Q_fne"
+#define GTTF2_LIBCALL "_Q_fgt"
+#define GETF2_LIBCALL "_Q_fge"
+#define LTTF2_LIBCALL "_Q_flt"
+#define LETF2_LIBCALL "_Q_fle"
 
 /* We can define the TFmode sqrt optab only if TARGET_FPU.  This is because
    with soft-float, the SFmode and DFmode sqrt instructions will be absent,
@@ -2685,33 +2707,36 @@ do {                                    
    for calls to the builtin function sqrt, but this fails.  */
 #define INIT_TARGET_OPTABS						\
   do {									\
-    add_optab->handlers[(int) TFmode].libfunc				\
-      = init_one_libfunc (ADDTF3_LIBCALL);				\
-    sub_optab->handlers[(int) TFmode].libfunc				\
-      = init_one_libfunc (SUBTF3_LIBCALL);				\
-    neg_optab->handlers[(int) TFmode].libfunc				\
-      = init_one_libfunc (NEGTF2_LIBCALL);				\
-    smul_optab->handlers[(int) TFmode].libfunc				\
-      = init_one_libfunc (MULTF3_LIBCALL);				\
-    flodiv_optab->handlers[(int) TFmode].libfunc			\
-      = init_one_libfunc (DIVTF3_LIBCALL);				\
-    eqtf2_libfunc = init_one_libfunc (EQTF2_LIBCALL);			\
-    netf2_libfunc = init_one_libfunc (NETF2_LIBCALL);			\
-    gttf2_libfunc = init_one_libfunc (GTTF2_LIBCALL);			\
-    getf2_libfunc = init_one_libfunc (GETF2_LIBCALL);			\
-    lttf2_libfunc = init_one_libfunc (LTTF2_LIBCALL);			\
-    letf2_libfunc = init_one_libfunc (LETF2_LIBCALL);			\
-    trunctfsf2_libfunc = init_one_libfunc (TRUNCTFSF2_LIBCALL);		\
-    trunctfdf2_libfunc = init_one_libfunc (TRUNCTFDF2_LIBCALL);		\
-    extendsftf2_libfunc = init_one_libfunc (EXTENDSFTF2_LIBCALL);	\
-    extenddftf2_libfunc = init_one_libfunc (EXTENDDFTF2_LIBCALL);	\
-    floatsitf_libfunc = init_one_libfunc (FLOATSITF2_LIBCALL);		\
-    fixtfsi_libfunc = init_one_libfunc (FIX_TRUNCTFSI2_LIBCALL);	\
-    fixunstfsi_libfunc							\
-      = init_one_libfunc (FIXUNS_TRUNCTFSI2_LIBCALL);			\
-    if (TARGET_FPU)							\
-      sqrt_optab->handlers[(int) TFmode].libfunc			\
-	= init_one_libfunc ("_Q_sqrt");					\
+    if (TARGET_ARCH32)							\
+      {									\
+	add_optab->handlers[(int) TFmode].libfunc			\
+	  = init_one_libfunc (ADDTF3_LIBCALL);				\
+	sub_optab->handlers[(int) TFmode].libfunc			\
+	  = init_one_libfunc (SUBTF3_LIBCALL);				\
+	neg_optab->handlers[(int) TFmode].libfunc			\
+	  = init_one_libfunc (NEGTF2_LIBCALL);				\
+	smul_optab->handlers[(int) TFmode].libfunc			\
+	  = init_one_libfunc (MULTF3_LIBCALL);				\
+	flodiv_optab->handlers[(int) TFmode].libfunc			\
+	  = init_one_libfunc (DIVTF3_LIBCALL);				\
+	eqtf2_libfunc = init_one_libfunc (EQTF2_LIBCALL);		\
+	netf2_libfunc = init_one_libfunc (NETF2_LIBCALL);		\
+	gttf2_libfunc = init_one_libfunc (GTTF2_LIBCALL);		\
+	getf2_libfunc = init_one_libfunc (GETF2_LIBCALL);		\
+	lttf2_libfunc = init_one_libfunc (LTTF2_LIBCALL);		\
+	letf2_libfunc = init_one_libfunc (LETF2_LIBCALL);		\
+	trunctfsf2_libfunc = init_one_libfunc (TRUNCTFSF2_LIBCALL);	\
+	trunctfdf2_libfunc = init_one_libfunc (TRUNCTFDF2_LIBCALL);	\
+	extendsftf2_libfunc = init_one_libfunc (EXTENDSFTF2_LIBCALL);	\
+	extenddftf2_libfunc = init_one_libfunc (EXTENDDFTF2_LIBCALL);	\
+	floatsitf_libfunc = init_one_libfunc (FLOATSITF2_LIBCALL);	\
+	fixtfsi_libfunc = init_one_libfunc (FIX_TRUNCTFSI2_LIBCALL);	\
+	fixunstfsi_libfunc						\
+	  = init_one_libfunc (FIXUNS_TRUNCTFSI2_LIBCALL);		\
+	if (TARGET_FPU)							\
+	  sqrt_optab->handlers[(int) TFmode].libfunc			\
+	    = init_one_libfunc ("_Q_sqrt");				\
+      }									\
     INIT_SUBTARGET_OPTABS;						\
   } while (0)
 
--- gcc/config/sparc/sparc.md.jj	Wed Dec  1 09:04:37 1999
+++ gcc/config/sparc/sparc.md	Wed Dec  1 09:17:50 1999
@@ -629,7 +629,7 @@
   [(set (reg:CCFP 96)
 	(compare:CCFP (match_operand:TF 0 "register_operand" "")
 		      (match_operand:TF 1 "register_operand" "")))]
-  "TARGET_FPU && TARGET_HARD_QUAD"
+  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
   "
 {
   sparc_compare_op0 = operands[0];
@@ -857,6 +857,12 @@
       emit_insn (pat);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
   else if (TARGET_V9)
     {
       if (gen_v9_scc (EQ, operands))
@@ -904,6 +910,12 @@
       emit_insn (pat);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
   else if (TARGET_V9)
     {
       if (gen_v9_scc (NE, operands))
@@ -919,7 +931,13 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (TARGET_V9)
+  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
+  else if (TARGET_V9)
     {
       if (gen_v9_scc (GT, operands))
 	DONE;
@@ -934,7 +952,13 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (TARGET_V9)
+  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
+  else if (TARGET_V9)
     {
       if (gen_v9_scc (LT, operands))
 	DONE;
@@ -949,7 +973,13 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (TARGET_V9)
+  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
+  else if (TARGET_V9)
     {
       if (gen_v9_scc (GE, operands))
 	DONE;
@@ -964,7 +994,13 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (TARGET_V9)
+  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+      emit_jump_insn (gen_sne (operands[0]));
+      DONE;
+    }
+  else if (TARGET_V9)
     {
       if (gen_v9_scc (LE, operands))
 	DONE;
@@ -1592,6 +1628,12 @@
       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -1610,6 +1652,12 @@
       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -1628,6 +1676,12 @@
       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -1656,6 +1710,12 @@
       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -1684,6 +1744,12 @@
       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -1712,6 +1778,12 @@
       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
       DONE;
     }
+  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
 }")
 
@@ -4451,7 +4746,34 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "extendsftf2"
+(define_expand "extendsftf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(float_extend:TF
+	 (match_operand:SF 1 "register_operand" "f")))]
+  "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\"), 0,
+			 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;
+    }
+}")
+
+(define_insn "*extendsftf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(float_extend:TF
 	 (match_operand:SF 1 "register_operand" "f")))]
@@ -4460,7 +4782,34 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "extenddftf2"
+(define_expand "extenddftf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(float_extend:TF
+	 (match_operand:DF 1 "register_operand" "e")))]
+  "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\"), 0,
+			 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;
+    }
+}")
+
+(define_insn "*extenddftf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(float_extend:TF
 	 (match_operand:DF 1 "register_operand" "e")))]
@@ -4478,7 +4827,33 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "trunctfsf2"
+(define_expand "trunctfsf2"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+	(float_truncate:SF
+	 (match_operand:TF 1 "register_operand" "e")))]
+  "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], 0, SFmode, 1,
+			       XEXP (slot0, 0), Pmode);
+      DONE;
+    }
+}")
+
+(define_insn "*trunctfsf2_hq"
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(float_truncate:SF
 	 (match_operand:TF 1 "register_operand" "e")))]
@@ -4487,7 +4862,33 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "trunctfdf2"
+(define_expand "trunctfdf2"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+	(float_truncate:DF
+	 (match_operand:TF 1 "register_operand" "e")))]
+  "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], 0, DFmode, 1,
+			       XEXP (slot0, 0), Pmode);
+      DONE;
+    }
+}")
+
+(define_insn "*trunctfdf2_hq"
   [(set (match_operand:DF 0 "register_operand" "=e")
 	(float_truncate:DF
 	 (match_operand:TF 1 "register_operand" "e")))]
@@ -4514,7 +4915,33 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "floatsitf2"
+(define_expand "floatsitf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(float:TF (match_operand:SI 1 "register_operand" "f")))]
+  "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;
+    }
+}")
+
+(define_insn "*floatsitf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(float:TF (match_operand:SI 1 "register_operand" "f")))]
   "TARGET_FPU && TARGET_HARD_QUAD"
@@ -4522,6 +4949,29 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
+(define_expand "floatunssitf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
+  "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;
+}")
+
 ;; Now the same for 64 bit sources.
 
 (define_insn "floatdisf2"
@@ -4540,7 +4990,33 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "floatditf2"
+(define_expand "floatditf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(float:TF (match_operand:DI 1 "register_operand" "e")))]
+  "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;
+    }
+}")
+
+(define_insn "*floatditf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(float:TF (match_operand:DI 1 "register_operand" "e")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
@@ -4548,6 +5024,29 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
+(define_expand "floatunsditf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
+  "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;
+}")
+
 ;; Convert a float to an actual integer.
 ;; Truncation is performed as part of the conversion.
 
@@ -4567,7 +5066,32 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "fix_trunctfsi2"
+(define_expand "fix_trunctfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=f")
+	(fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  "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], 0, SImode, 1,
+			       XEXP (slot0, 0), Pmode);
+      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"))))]
   "TARGET_FPU && TARGET_HARD_QUAD"
@@ -4575,6 +5099,28 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
+(define_expand "fixuns_trunctfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=f")
+	(unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  "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], 0, SImode, 1,
+			   XEXP (slot0, 0), Pmode);
+  DONE;
+}")
+
 ;; Now the same, for V9 targets
 
 (define_insn "fix_truncsfdi2"
@@ -4593,13 +5139,61 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "fix_trunctfdi2"
+(define_expand "fix_trunctfdi2"
+  [(set (match_operand:DI 0 "register_operand" "=e")
+	(fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  "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], 0, DImode, 1,
+			       XEXP (slot0, 0), Pmode);
+      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"))))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
   "fqtox\\t%1, %0"
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
+
+(define_expand "fixuns_trunctfdi2"
+  [(set (match_operand:DI 0 "register_operand" "=f")
+	(unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+  "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], 0, DImode, 1,
+			   XEXP (slot0, 0), Pmode);
+  DONE;
+}")
+
 
 ;;- arithmetic instructions
 
@@ -6528,7 +7122,49 @@
 
 ;; Floating point arithmetic instructions.
 
-(define_insn "addtf3"
+(define_expand "addtf3"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+	(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;
+    }
+}")
+
+(define_insn "*addtf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(plus:TF (match_operand:TF 1 "register_operand" "e")
 		 (match_operand:TF 2 "register_operand" "e")))]
@@ -6555,7 +7191,49 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "subtf3"
+(define_expand "subtf3"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+	(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;
+    }
+}")
+
+(define_insn "*subtf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(minus:TF (match_operand:TF 1 "register_operand" "e")
 		  (match_operand:TF 2 "register_operand" "e")))]
@@ -6582,7 +7260,49 @@
   [(set_attr "type" "fp")
    (set_attr "length" "1")])
 
-(define_insn "multf3"
+(define_expand "multf3"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+	(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;
+    }
+}")
+
+(define_insn "*multf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(mult:TF (match_operand:TF 1 "register_operand" "e")
 		 (match_operand:TF 2 "register_operand" "e")))]
@@ -6627,8 +7347,50 @@
   [(set_attr "type" "fpmul")
    (set_attr "length" "1")])
 
+(define_expand "divtf3"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+	(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;
+    }
+}")
+
 ;; don't have timing for quad-prec. divide.
-(define_insn "divtf3"
+(define_insn "*divtf3_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(div:TF (match_operand:TF 1 "register_operand" "e")
 		(match_operand:TF 2 "register_operand" "e")))]
@@ -6899,7 +7661,40 @@
   [(set_attr "type" "fpmove")
    (set_attr "length" "1")])
 
-(define_insn "sqrttf2"
+(define_expand "sqrttf2"
+  [(set (match_operand:TF 0 "register_operand" "=e")
+	(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
+  "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;
+    }
+}")
+
+(define_insn "*sqrttf2_hq"
   [(set (match_operand:TF 0 "register_operand" "=e")
 	(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
   "TARGET_FPU && TARGET_HARD_QUAD"

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