aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>1999-12-08 09:00:51 +0100
committerDavid S. Miller <davem@gcc.gnu.org>1999-12-08 00:00:51 -0800
commit47ac041c930f67cad6259c88b14907f376c748ba (patch)
tree03bb17e771e02fe076760cd6d33a5ffb5a9e49e4
parent0f63333cc92a1cf2c61f551e4bf987c0eeb1f3c3 (diff)
downloadgcc-47ac041c930f67cad6259c88b14907f376c748ba.zip
gcc-47ac041c930f67cad6259c88b14907f376c748ba.tar.gz
gcc-47ac041c930f67cad6259c88b14907f376c748ba.tar.bz2
sparc.c (sparc_emit_float_lib_cmp): New function.
* 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. From-SVN: r30824
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c71
-rw-r--r--gcc/config/sparc/sparc.h96
-rw-r--r--gcc/config/sparc/sparc.md608
5 files changed, 727 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c9d7794..da3a78b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -15,6 +15,22 @@
(clear_sf): Use const_double_operand.
(clear_sfp, clear_dfp, clear_tf, clear_tfp): New patterns.
+ * 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.
+
Tue Dec 7 19:22:06 1999 Richard Henderson <rth@cygnus.com>
* loop.h (struct induction): Add multi_insn_incr.
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 2e17339..c761669 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -79,6 +79,7 @@ extern void sparc_flat_save_restore PARAMS ((FILE *, const char *,
#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));
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index b2161ab..b2219cc 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -4689,6 +4689,77 @@ output_cbranch (op, label, reversed, annul, noop, insn)
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
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index cfb80ce..c051c78 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -2680,26 +2680,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,
@@ -2707,33 +2706,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)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index cf99546..25951f0 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -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);
}")
@@ -4515,7 +4587,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")))]
@@ -4524,7 +4623,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")))]
@@ -4542,7 +4668,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")))]
@@ -4551,7 +4703,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")))]
@@ -4578,7 +4756,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"
@@ -4586,6 +4790,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"
@@ -4604,7 +4831,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"
@@ -4612,6 +4865,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.
@@ -4631,7 +4907,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"
@@ -4639,6 +4940,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"
@@ -4657,13 +4980,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
@@ -6592,7 +6963,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")))]
@@ -6619,7 +7032,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")))]
@@ -6646,7 +7101,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")))]
@@ -6691,8 +7188,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")))]
@@ -6963,7 +7502,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"