diff options
author | Jakub Jelinek <jakub@redhat.com> | 1999-12-08 09:00:51 +0100 |
---|---|---|
committer | David S. Miller <davem@gcc.gnu.org> | 1999-12-08 00:00:51 -0800 |
commit | 47ac041c930f67cad6259c88b14907f376c748ba (patch) | |
tree | 03bb17e771e02fe076760cd6d33a5ffb5a9e49e4 /gcc | |
parent | 0f63333cc92a1cf2c61f551e4bf987c0eeb1f3c3 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/sparc/sparc-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 71 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 96 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 608 |
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" |