Commit 47ac041c by Jakub Jelinek Committed by David S. Miller

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
parent 0f63333c
......@@ -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.
......
......@@ -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));
......
......@@ -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
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment