This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix sparc -mhard-quad-float (c/4331)
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, mark at codesourcery dot com
- Date: Mon, 29 Apr 2002 13:50:26 -0700
- Subject: fix sparc -mhard-quad-float (c/4331)
The code expanders for -mhard-quad-float are completely broken.
Particularly at -O0, they quite regularly generate invalid code
which is then not recognized, followed directly by an ice.
This is probably not a regression as such, in that it has probably
never worked, but I'm given to understand that e.g. freebsd does
not implement the software routines, and so must use hard-quad.
Ok for 3.1?
r~
* config/sparc/sparc.c (emit_soft_tfmode_libcall,
emit_soft_tfmode_binop, emit_soft_tfmode_unop, emit_soft_tfmode_cvt,
emit_hard_tfmode_operation, emit_tfmode_binop, emit_tfmode_unop,
emit_tfmode_cvt): New.
* config/sparc/sparc.md (extendsftf2, extenddftf2, trunctfsf2,
trunctfdf2, floatsitf2, floatunssitf2, floatditf2, floatunsditf2,
fix_trunctfsi2, fixuns_trunctfsi2, fix_trunctfdi2, fixuns_trunctfdi2,
addtf3, subtf3, multf3, divtf3, sqrttf2): Use them.
* config/sparc/sparc-protos.h: Update.
Index: sparc-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc-protos.h,v
retrieving revision 1.17.8.7
diff -c -p -d -r1.17.8.7 sparc-protos.h
*** sparc-protos.h 15 Apr 2002 10:08:51 -0000 1.17.8.7
--- sparc-protos.h 29 Apr 2002 20:25:44 -0000
*************** extern enum machine_mode select_cc_mode
*** 74,79 ****
--- 74,82 ----
extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
extern void sparc_emit_floatunsdi PARAMS ((rtx [2]));
+ extern void emit_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+ extern void emit_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+ extern void emit_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
/* This function handles all v9 scc insns */
extern int gen_v9_scc PARAMS ((enum rtx_code, rtx *));
extern void sparc_initialize_trampoline PARAMS ((rtx, rtx, rtx));
Index: sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.185.2.19
diff -c -p -d -r1.185.2.19 sparc.c
*** sparc.c 17 Apr 2002 08:16:48 -0000 1.185.2.19
--- sparc.c 29 Apr 2002 20:25:45 -0000
*************** static int sparc_issue_rate PARAMS ((voi
*** 178,183 ****
--- 178,189 ----
static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
static void sparc_sched_init PARAMS ((FILE *, int, int));
static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
+
+ static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));
+ static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+ static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+ static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
+ static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
/* Option handling. */
*************** gen_df_reg (reg, low)
*** 2456,2461 ****
--- 2462,2765 ----
if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
regno += (TARGET_ARCH64 && regno < 32) ? 1 : 2;
return gen_rtx_REG (DFmode, regno);
+ }
+
+ /* Generate a call to FUNC with OPERANDS. Operand 0 is the return value.
+ Unlike normal calls, TFmode operands are passed by reference. It is
+ assumed that no more than 3 operands are required. */
+
+ static void
+ emit_soft_tfmode_libcall (func_name, nargs, operands)
+ const char *func_name;
+ int nargs;
+ rtx *operands;
+ {
+ rtx ret_slot = NULL, arg[3], func_sym;
+ int i;
+
+ /* We only expect to be called for conversions, unary, and binary ops. */
+ if (nargs < 2 || nargs > 3)
+ abort ();
+
+ for (i = 0; i < nargs; ++i)
+ {
+ rtx this_arg = operands[i];
+ rtx this_slot;
+
+ /* TFmode arguments and return values are passed by reference. */
+ if (GET_MODE (this_arg) == TFmode)
+ {
+ if (GET_CODE (this_arg) == MEM)
+ this_arg = XEXP (this_arg, 0);
+ else if (CONSTANT_P (arg[i]))
+ {
+ this_slot = force_const_mem (TFmode, this_arg);
+ this_arg = XEXP (this_slot, 0);
+ }
+ else
+ {
+ this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode), 0);
+
+ /* Operand 0 is the return value. We'll copy it out later. */
+ if (i > 0)
+ emit_move_insn (this_slot, this_arg);
+ else
+ ret_slot = this_slot;
+
+ this_arg = XEXP (this_slot, 0);
+ }
+ }
+
+ arg[i] = this_arg;
+ }
+
+ func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
+
+ if (GET_MODE (operands[0]) == TFmode)
+ {
+ if (nargs == 2)
+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 2,
+ arg[0], GET_MODE (arg[0]),
+ arg[1], GET_MODE (arg[1]));
+ else
+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 3,
+ arg[0], GET_MODE (arg[0]),
+ arg[1], GET_MODE (arg[1]),
+ arg[2], GET_MODE (arg[2]));
+
+ if (ret_slot)
+ emit_move_insn (operands[0], ret_slot);
+ }
+ else
+ {
+ rtx ret;
+
+ if (nargs != 2)
+ abort ();
+
+ ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
+ GET_MODE (operands[0]), 1,
+ arg[1], GET_MODE (arg[1]));
+
+ if (ret != operands[0])
+ emit_move_insn (operands[0], ret);
+ }
+ }
+
+ /* Expand soft-float TFmode calls to sparc abi routines. */
+
+ static void
+ emit_soft_tfmode_binop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ const char *func;
+
+ switch (code)
+ {
+ case PLUS:
+ func = "_Qp_add";
+ break;
+ case MINUS:
+ func = "_Qp_sub";
+ break;
+ case MULT:
+ func = "_Qp_mul";
+ break;
+ case DIV:
+ func = "_Qp_div";
+ break;
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 3, operands);
+ }
+
+ static void
+ emit_soft_tfmode_unop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ const char *func;
+
+ switch (code)
+ {
+ case SQRT:
+ func = "_Qp_sqrt";
+ break;
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 2, operands);
+ }
+
+ static void
+ emit_soft_tfmode_cvt (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ const char *func;
+
+ switch (code)
+ {
+ case FLOAT_EXTEND:
+ switch (GET_MODE (operands[1]))
+ {
+ case SFmode:
+ func = "_Qp_stoq";
+ break;
+ case DFmode:
+ func = "_Qp_dtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FLOAT_TRUNCATE:
+ switch (GET_MODE (operands[0]))
+ {
+ case SFmode:
+ func = "_Qp_qtos";
+ break;
+ case DFmode:
+ func = "_Qp_qtod";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FLOAT:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_itoq";
+ break;
+ case DImode:
+ func = "_Qp_xtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case UNSIGNED_FLOAT:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_uitoq";
+ break;
+ case DImode:
+ func = "_Qp_uxtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FIX:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_qtoi";
+ break;
+ case DImode:
+ func = "_Qp_qtox";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case UNSIGNED_FIX:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_qtoui";
+ break;
+ case DImode:
+ func = "_Qp_qtoux";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 2, operands);
+ }
+
+ /* Expand a hard-float tfmode operation. All arguments must be in
+ registers. */
+
+ static void
+ emit_hard_tfmode_operation (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ rtx op, dest;
+
+ if (GET_RTX_CLASS (code) == '1')
+ {
+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+ op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
+ }
+ else
+ {
+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+ operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+ op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
+ operands[1], operands[2]);
+ }
+
+ if (register_operand (operands[0], VOIDmode))
+ dest = operands[0];
+ else
+ dest = gen_reg_rtx (GET_MODE (operands[0]));
+
+ emit_insn (gen_rtx_SET (VOIDmode, dest, op));
+
+ if (dest != operands[0])
+ emit_move_insn (operands[0], dest);
+ }
+
+ void
+ emit_tfmode_binop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_binop (code, operands);
+ }
+
+ void
+ emit_tfmode_unop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_unop (code, operands);
+ }
+
+ void
+ emit_tfmode_cvt (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+ {
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_cvt (code, operands);
}
/* Return nonzero if a return peephole merging return with
Index: sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.148.2.12
diff -c -p -d -r1.148.2.12 sparc.md
*** sparc.md 29 Apr 2002 05:26:07 -0000 1.148.2.12
--- sparc.md 29 Apr 2002 20:25:45 -0000
***************
*** 5023,5053 ****
(set_attr "fptype" "double")])
(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\"), LCT_NORMAL,
! VOIDmode, 2,
! XEXP (slot0, 0), Pmode,
! operands[1], SFmode);
!
! if (GET_CODE (operands[0]) != MEM)
! emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
! DONE;
! }
! }")
(define_insn "*extendsftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
--- 5023,5033 ----
(set_attr "fptype" "double")])
(define_expand "extendsftf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
! (match_operand:SF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extendsftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 5058,5088 ****
[(set_attr "type" "fp")])
(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\"), LCT_NORMAL,
! VOIDmode, 2,
! XEXP (slot0, 0), Pmode,
! operands[1], DFmode);
!
! if (GET_CODE (operands[0]) != MEM)
! emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
! DONE;
! }
! }")
(define_insn "*extenddftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
--- 5038,5048 ----
[(set_attr "type" "fp")])
(define_expand "extenddftf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
! (match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extenddftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 5102,5131 ****
(set_attr "fptype" "double")])
(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], LCT_NORMAL, SFmode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }
! }")
(define_insn "*trunctfsf2_hq"
[(set (match_operand:SF 0 "register_operand" "=f")
--- 5062,5072 ----
(set_attr "fptype" "double")])
(define_expand "trunctfsf2"
! [(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
! (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfsf2_hq"
[(set (match_operand:SF 0 "register_operand" "=f")
***************
*** 5136,5165 ****
[(set_attr "type" "fp")])
(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], LCT_NORMAL, DFmode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }
! }")
(define_insn "*trunctfdf2_hq"
[(set (match_operand:DF 0 "register_operand" "=e")
--- 5077,5087 ----
[(set_attr "type" "fp")])
(define_expand "trunctfdf2"
! [(set (match_operand:DF 0 "register_operand" "")
(float_truncate:DF
! (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfdf2_hq"
[(set (match_operand:DF 0 "register_operand" "=e")
***************
*** 5188,5217 ****
(set_attr "fptype" "double")])
(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")
--- 5110,5119 ----
(set_attr "fptype" "double")])
(define_expand "floatsitf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
! (float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatsitf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 5221,5247 ****
[(set_attr "type" "fp")])
(define_expand "floatunssitf2"
! [(set (match_operand:TF 0 "register_operand" "=e")
! (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
"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.
--- 5123,5132 ----
[(set_attr "type" "fp")])
(define_expand "floatunssitf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
! (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
! "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Now the same for 64 bit sources.
***************
*** 5274,5303 ****
"sparc_emit_floatunsdi (operands); DONE;")
(define_expand "floatditf2"
! [(set (match_operand:TF 0 "register_operand" "=e")
! (float:TF (match_operand:DI 1 "register_operand" "e")))]
"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")
--- 5159,5168 ----
"sparc_emit_floatunsdi (operands); DONE;")
(define_expand "floatditf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
! (float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatditf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 5307,5333 ****
[(set_attr "type" "fp")])
(define_expand "floatunsditf2"
! [(set (match_operand:TF 0 "register_operand" "=e")
! (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
"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.
--- 5172,5181 ----
[(set_attr "type" "fp")])
(define_expand "floatunsditf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
! (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
! "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.
***************
*** 5349,5406 ****
(set_attr "fptype" "double")])
(define_expand "fix_trunctfsi2"
! [(set (match_operand:SI 0 "register_operand" "=f")
! (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "
! {
! if (! TARGET_HARD_QUAD)
! {
! rtx slot0;
!
! if (GET_CODE (operands[1]) != MEM)
! {
! slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
! emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
! }
! else
! slot0 = operands[1];
!
! emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
! operands[0], LCT_NORMAL, SImode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }
! }")
(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"
"fqtoi\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfsi2"
! [(set (match_operand:SI 0 "register_operand" "=f")
! (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
! "
! {
! rtx slot0;
!
! if (GET_CODE (operands[1]) != MEM)
! {
! slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
! emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
! }
! else
! slot0 = operands[1];
!
! emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
! operands[0], LCT_NORMAL, SImode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }")
;; Now the same, for V9 targets
--- 5197,5219 ----
(set_attr "fptype" "double")])
(define_expand "fix_trunctfsi2"
! [(set (match_operand:SI 0 "register_operand" "")
! (fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfsi2_hq"
[(set (match_operand:SI 0 "register_operand" "=f")
! (fix:SI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtoi\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfsi2"
! [(set (match_operand:SI 0 "register_operand" "")
! (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
! "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;; Now the same, for V9 targets
***************
*** 5421,5479 ****
(set_attr "fptype" "double")])
(define_expand "fix_trunctfdi2"
! [(set (match_operand:DI 0 "register_operand" "=e")
! (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "
! {
! if (! TARGET_HARD_QUAD)
! {
! rtx slot0;
!
! if (GET_CODE (operands[1]) != MEM)
! {
! slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
! emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
! }
! else
! slot0 = operands[1];
!
! emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
! operands[0], LCT_NORMAL, DImode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }
! }")
(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")])
(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], LCT_NORMAL, DImode, 1,
! XEXP (slot0, 0), Pmode);
! DONE;
! }")
!
;;- arithmetic instructions
--- 5234,5256 ----
(set_attr "fptype" "double")])
(define_expand "fix_trunctfdi2"
! [(set (match_operand:DI 0 "register_operand" "")
! (fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfdi2_hq"
[(set (match_operand:DI 0 "register_operand" "=e")
! (fix:DI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"fqtox\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfdi2"
! [(set (match_operand:DI 0 "register_operand" "")
! (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
! "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;;- arithmetic instructions
***************
*** 7373,7414 ****
(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")
--- 7150,7156 ----
(plus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_binop (PLUS, operands); DONE;")
(define_insn "*addtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 7440,7481 ****
(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")
--- 7182,7188 ----
(minus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_binop (MINUS, operands); DONE;")
(define_insn "*subtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 7507,7548 ****
(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")
--- 7214,7220 ----
(mult:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_binop (MULT, operands); DONE;")
(define_insn "*multf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
***************
*** 7591,7632 ****
(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_hq"
--- 7263,7269 ----
(div:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_binop (DIV, operands); DONE;")
;; don't have timing for quad-prec. divide.
(define_insn "*divtf3_hq"
***************
*** 7875,7911 ****
[(set_attr "type" "fpmove")])
(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")
--- 7512,7521 ----
[(set_attr "type" "fpmove")])
(define_expand "sqrttf2"
! [(set (match_operand:TF 0 "nonimmediate_operand" "")
! (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
! "emit_tfmode_unop (SQRT, operands); DONE;")
(define_insn "*sqrttf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")