[ARC] Add single/double IEEE precission FPU support.

gcc/
2016-02-16  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc-modes.def (CC_FPU, CC_FPU_UNEQ): New modes.
	* config/arc/arc-opts.h (FPU_SP, FPU_SF, FPU_SC, FPU_SD, FPU_DP)
	(FPU_DF, FPU_DC, FPU_DD, FXP_DP): Define.
	* config/arc/arc.c (arc_init): Check FPU options.
	(get_arc_condition_code): Handle new CC_FPU* modes.
	(arc_select_cc_mode): Likewise.
	(arc_conditional_register_usage): Allow 64 bit datum into even-odd
	register pair only. Allow access for ARCv2 accumulator.
	(gen_compare_reg): Whenever we have FPU support use FPU compare
	instructions.
	(arc_reorg): Don't generate brcc insns when FPU compare
	instructions are involved.
	* config/arc/arc.h (TARGET_DPFP): Add TARGET_FP_DPAX condition.
	(TARGET_OPTFPE): Add condition when ARC EM can use optimized
	floating point emulation.
	(ACC_REG_FIRST, ACC_REG_LAST, ACCL_REGNO, ACCH_REGNO): Define.
	(REVERSE_CONDITION): Add new CC_FPU* modes.
	(TARGET_FP_SP_BASE): Define.
	(TARGET_FP_DP_BASE): Likewise.
	(TARGET_FP_SP_FUSED): Likewise.
	(TARGET_FP_DP_FUSED): Likewise.
	(TARGET_FP_SP_CONV): Likewise.
	(TARGET_FP_DP_CONV): Likewise.
	(TARGET_FP_SP_SQRT): Likewise.
	(TARGET_FP_DP_SQRT): Likewise.
	(TARGET_FP_DP_AX): Likewise.
	* config/arc/arc.md (ARCV2_ACC): New constant.
	(type): New fpu type attribute.
	(SDF): Conditional iterator.
	(cstore<mode>, cbranch<mode>): Change expand condition.
	(addsf3, subsf3, mulsf3, adddf3, subdf3, muldf3): New expands,
	handles FPU/FPX cases as well.
	* config/arc/arc.opt (mfpu): New option.
	* config/arc/fpx.md (addsf3_fpx, subsf3_fpx, mulsf3_fpx):
	Renamed.
	(adddf3, muldf3, subdf3): Removed.
	* config/arc/predicates.md (proper_comparison_operator): Recognize
	CC_FPU* modes.
	* config/arc/fpu.md: New file.
	* doc/invoke.texi (ARC Options): Document mfpu option.

From-SVN: r233451
This commit is contained in:
Claudiu Zissulescu 2016-02-16 15:11:24 +01:00 committed by Claudiu Zissulescu
parent d5b1a52eec
commit 8f3304d019
11 changed files with 1103 additions and 104 deletions

View File

@ -1,3 +1,46 @@
2016-02-16 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-modes.def (CC_FPU, CC_FPU_UNEQ): New modes.
* config/arc/arc-opts.h (FPU_SP, FPU_SF, FPU_SC, FPU_SD, FPU_DP)
(FPU_DF, FPU_DC, FPU_DD, FXP_DP): Define.
* config/arc/arc.c (arc_init): Check FPU options.
(get_arc_condition_code): Handle new CC_FPU* modes.
(arc_select_cc_mode): Likewise.
(arc_conditional_register_usage): Allow 64 bit datum into even-odd
register pair only. Allow access for ARCv2 accumulator.
(gen_compare_reg): Whenever we have FPU support use FPU compare
instructions.
(arc_reorg): Don't generate brcc insns when FPU compare
instructions are involved.
* config/arc/arc.h (TARGET_DPFP): Add TARGET_FP_DPAX condition.
(TARGET_OPTFPE): Add condition when ARC EM can use optimized
floating point emulation.
(ACC_REG_FIRST, ACC_REG_LAST, ACCL_REGNO, ACCH_REGNO): Define.
(REVERSE_CONDITION): Add new CC_FPU* modes.
(TARGET_FP_SP_BASE): Define.
(TARGET_FP_DP_BASE): Likewise.
(TARGET_FP_SP_FUSED): Likewise.
(TARGET_FP_DP_FUSED): Likewise.
(TARGET_FP_SP_CONV): Likewise.
(TARGET_FP_DP_CONV): Likewise.
(TARGET_FP_SP_SQRT): Likewise.
(TARGET_FP_DP_SQRT): Likewise.
(TARGET_FP_DP_AX): Likewise.
* config/arc/arc.md (ARCV2_ACC): New constant.
(type): New fpu type attribute.
(SDF): Conditional iterator.
(cstore<mode>, cbranch<mode>): Change expand condition.
(addsf3, subsf3, mulsf3, adddf3, subdf3, muldf3): New expands,
handles FPU/FPX cases as well.
* config/arc/arc.opt (mfpu): New option.
* config/arc/fpx.md (addsf3_fpx, subsf3_fpx, mulsf3_fpx):
Renamed.
(adddf3, muldf3, subdf3): Removed.
* config/arc/predicates.md (proper_comparison_operator): Recognize
CC_FPU* modes.
* config/arc/fpu.md: New file.
* doc/invoke.texi (ARC Options): Document mfpu option.
2016-02-16 Richard Biener <rguenther@suse.de>
PR rtl-optimization/69291

View File

@ -35,3 +35,7 @@ CC_MODE (CC_FPX);
VECTOR_MODES (INT, 4); /* V4QI V2HI */
VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
/* FPU condition flags. */
CC_MODE (CC_FPU);
CC_MODE (CC_FPU_UNEQ);

View File

@ -27,3 +27,23 @@ enum processor_type
PROCESSOR_ARCEM,
PROCESSOR_ARCHS
};
/* Single precision floating point. */
#define FPU_SP 0x0001
/* Single precision fused floating point operations. */
#define FPU_SF 0x0002
/* Single precision floating point format conversion operations. */
#define FPU_SC 0x0004
/* Single precision floating point sqrt and div operations. */
#define FPU_SD 0x0008
/* Double precision floating point. */
#define FPU_DP 0x0010
/* Double precision fused floating point operations. */
#define FPU_DF 0x0020
/* Double precision floating point format conversion operations. */
#define FPU_DC 0x0040
/* Double precision floating point sqrt and div operations. */
#define FPU_DD 0x0080
/* Double precision floating point assist operations. */
#define FPX_DP 0x0100

View File

@ -719,9 +719,16 @@ arc_init (void)
/* FPX-3. No FPX extensions on pre-ARC600 cores. */
if ((TARGET_DPFP || TARGET_SPFP)
&& !TARGET_ARCOMPACT_FAMILY)
&& (!TARGET_ARCOMPACT_FAMILY && !TARGET_EM))
error ("FPX extensions not available on pre-ARC600 cores");
/* FPX-4. No FPX extensions mixed with FPU extensions for ARC HS
cpus. */
if ((TARGET_DPFP || TARGET_SPFP)
&& TARGET_HARD_FLOAT
&& TARGET_HS)
error ("No FPX/FPU mixing allowed");
/* Only selected multiplier configurations are available for HS. */
if (TARGET_HS && ((arc_mpy_option > 2 && arc_mpy_option < 7)
|| (arc_mpy_option == 1)))
@ -743,6 +750,19 @@ arc_init (void)
if (TARGET_LL64 && !TARGET_HS)
error ("-mll64 is only supported for ARC HS cores");
/* FPU support only for V2. */
if (TARGET_HARD_FLOAT)
{
if (TARGET_EM
&& (arc_fpu_build & ~(FPU_SP | FPU_SF | FPU_SC | FPU_SD | FPX_DP)))
error ("FPU double precision options are available for ARC HS only");
if (TARGET_HS && (arc_fpu_build & FPX_DP))
error ("FPU double precision assist "
"options are not available for ARC HS");
if (!TARGET_HS && !TARGET_EM)
error ("FPU options are available for ARCv2 architecture only");
}
arc_init_reg_tables ();
/* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
@ -926,6 +946,33 @@ get_arc_condition_code (rtx comparison)
case UNEQ : return ARC_CC_LS;
default : gcc_unreachable ();
}
case CC_FPUmode:
switch (GET_CODE (comparison))
{
case EQ : return ARC_CC_EQ;
case NE : return ARC_CC_NE;
case GT : return ARC_CC_GT;
case GE : return ARC_CC_GE;
case LT : return ARC_CC_C;
case LE : return ARC_CC_LS;
case UNORDERED : return ARC_CC_V;
case ORDERED : return ARC_CC_NV;
case UNGT : return ARC_CC_HI;
case UNGE : return ARC_CC_HS;
case UNLT : return ARC_CC_LT;
case UNLE : return ARC_CC_LE;
/* UNEQ and LTGT do not have representation. */
case LTGT : /* Fall through. */
case UNEQ : /* Fall through. */
default : gcc_unreachable ();
}
case CC_FPU_UNEQmode:
switch (GET_CODE (comparison))
{
case LTGT : return ARC_CC_NE;
case UNEQ : return ARC_CC_EQ;
default : gcc_unreachable ();
}
default : gcc_unreachable ();
}
/*NOTREACHED*/
@ -1009,19 +1056,46 @@ arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
return CC_FP_GEmode;
default: gcc_unreachable ();
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
else if (TARGET_HARD_FLOAT
&& ((mode == SFmode && TARGET_FP_SP_BASE)
|| (mode == DFmode && TARGET_FP_DP_BASE)))
switch (op)
{
case EQ: case NE: return CC_Zmode;
case LT: case UNGE:
case GT: case UNLE: return CC_FP_GTmode;
case LE: case UNGT:
case GE: case UNLT: return CC_FP_GEmode;
case UNEQ: case LTGT: return CC_FP_UNEQmode;
case ORDERED: case UNORDERED: return CC_FP_ORDmode;
default: gcc_unreachable ();
}
case EQ:
case NE:
case UNORDERED:
case ORDERED:
case UNLT:
case UNLE:
case UNGT:
case UNGE:
case LT:
case LE:
case GT:
case GE:
return CC_FPUmode;
case LTGT:
case UNEQ:
return CC_FPU_UNEQmode;
default:
gcc_unreachable ();
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
{
switch (op)
{
case EQ: case NE: return CC_Zmode;
case LT: case UNGE:
case GT: case UNLE: return CC_FP_GTmode;
case LE: case UNGT:
case GE: case UNLT: return CC_FP_GEmode;
case UNEQ: case LTGT: return CC_FP_UNEQmode;
case ORDERED: case UNORDERED: return CC_FP_ORDmode;
default: gcc_unreachable ();
}
}
return CCmode;
}
@ -1148,7 +1222,8 @@ arc_init_reg_tables (void)
we must explicitly check for them here. */
if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
|| i == (int) CC_Cmode
|| i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
|| i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode
|| i == CC_FPUmode || i == CC_FPU_UNEQmode)
arc_mode_class[i] = 1 << (int) C_MODE;
else
arc_mode_class[i] = 0;
@ -1282,6 +1357,16 @@ arc_conditional_register_usage (void)
arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
}
/* ARCHS has 64-bit data-path which makes use of the even-odd paired
registers. */
if (TARGET_HS)
{
for (regno = 1; regno < 32; regno +=2)
{
arc_hard_regno_mode_ok[regno] = S_MODES;
}
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if (i < 29)
@ -1376,6 +1461,19 @@ arc_conditional_register_usage (void)
/* pc : r63 */
arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
/*ARCV2 Accumulator. */
if (TARGET_V2
&& (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED))
{
arc_regno_reg_class[ACCL_REGNO] = WRITABLE_CORE_REGS;
arc_regno_reg_class[ACCH_REGNO] = WRITABLE_CORE_REGS;
SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCL_REGNO);
SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCH_REGNO);
SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCL_REGNO);
SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCH_REGNO);
arc_hard_regno_mode_ok[ACC_REG_FIRST] = D_MODES;
}
}
/* Handle an "interrupt" attribute; arguments as in
@ -1545,6 +1643,10 @@ gen_compare_reg (rtx comparison, machine_mode omode)
gen_rtx_REG (CC_FPXmode, 61),
const0_rtx)));
}
else if (TARGET_HARD_FLOAT
&& ((cmode == SFmode && TARGET_FP_SP_BASE)
|| (cmode == DFmode && TARGET_FP_DP_BASE)))
emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (mode, x, y)));
else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
{
rtx op0 = gen_rtx_REG (cmode, 0);
@ -1638,10 +1740,11 @@ arc_setup_incoming_varargs (cumulative_args_t args_so_far,
/* We must treat `__builtin_va_alist' as an anonymous arg. */
next_cum = *get_cumulative_args (args_so_far);
arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
arc_function_arg_advance (pack_cumulative_args (&next_cum),
mode, type, true);
first_anon_arg = next_cum;
if (first_anon_arg < MAX_ARC_PARM_REGS)
if (FUNCTION_ARG_REGNO_P (first_anon_arg))
{
/* First anonymous (unnamed) argument is in a reg. */
@ -4856,8 +4959,6 @@ arc_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
return ret;
}
/* This function is used to control a function argument is passed in a
register, and which register.
@ -4895,8 +4996,10 @@ arc_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
and the rest are pushed. */
static rtx
arc_function_arg (cumulative_args_t cum_v, machine_mode mode,
const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
arc_function_arg (cumulative_args_t cum_v,
machine_mode mode,
const_tree type ATTRIBUTE_UNUSED,
bool named ATTRIBUTE_UNUSED)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int arg_num = *cum;
@ -4942,8 +5045,10 @@ arc_function_arg (cumulative_args_t cum_v, machine_mode mode,
course function_arg_partial_nregs will come into play. */
static void
arc_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
const_tree type, bool named ATTRIBUTE_UNUSED)
arc_function_arg_advance (cumulative_args_t cum_v,
machine_mode mode,
const_tree type,
bool named ATTRIBUTE_UNUSED)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int bytes = (mode == BLKmode
@ -6398,6 +6503,11 @@ arc_reorg (void)
pc_target = SET_SRC (pattern);
/* Avoid FPU instructions. */
if ((GET_MODE (XEXP (XEXP (pc_target, 0), 0)) == CC_FPUmode)
|| (GET_MODE (XEXP (XEXP (pc_target, 0), 0)) == CC_FPU_UNEQmode))
continue;
/* Now go back and search for the set cc insn. */
label = XEXP (pc_target, 1);
@ -6420,7 +6530,7 @@ arc_reorg (void)
break;
}
}
if (! link_insn)
if (!link_insn)
continue;
else
/* Check if this is a data dependency. */

View File

@ -255,7 +255,8 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_MIXED_CODE (TARGET_MIXED_CODE_SET)
#define TARGET_SPFP (TARGET_SPFP_FAST_SET || TARGET_SPFP_COMPACT_SET)
#define TARGET_DPFP (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET)
#define TARGET_DPFP (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET \
|| TARGET_FP_DP_AX)
#define SUBTARGET_SWITCHES
@ -266,11 +267,12 @@ along with GCC; see the file COPYING3. If not see
default for A7, and only for pre A7 cores when -mnorm is given. */
#define TARGET_NORM (TARGET_ARC700 || TARGET_NORM_SET || TARGET_HS)
/* Indicate if an optimized floating point emulation library is available. */
#define TARGET_OPTFPE \
(TARGET_ARC700 \
/* We need a barrel shifter and NORM. */ \
|| (TARGET_ARC600 && TARGET_NORM_SET) \
|| TARGET_HS)
#define TARGET_OPTFPE \
(TARGET_ARC700 \
/* We need a barrel shifter and NORM. */ \
|| (TARGET_ARC600 && TARGET_NORM_SET) \
|| TARGET_HS \
|| (TARGET_EM && TARGET_NORM_SET && TARGET_BARREL_SHIFTER))
/* Non-zero means the cpu supports swap instruction. This flag is set by
default for A7, and only for pre A7 cores when -mswap is given. */
@ -713,6 +715,12 @@ enum reg_class
#define ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG 136
#define ARC_LAST_SIMD_DMA_CONFIG_REG 143
/* ARCv2 double-register accumulator. */
#define ACC_REG_FIRST 58
#define ACC_REG_LAST 59
#define ACCL_REGNO (TARGET_BIG_ENDIAN ? ACC_REG_FIRST + 1 : ACC_REG_FIRST)
#define ACCH_REGNO (TARGET_BIG_ENDIAN ? ACC_REG_FIRST : ACC_REG_FIRST + 1)
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
@ -864,7 +872,7 @@ arc_return_addr_rtx(COUNT,FRAME)
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT,N_NAMED_ARGS) \
((CUM) = 0)
((CUM) = 0)
/* The number of registers used for parameter passing. Local to this file. */
#define MAX_ARC_PARM_REGS 8
@ -1656,12 +1664,13 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
&& GET_CODE (PATTERN (X)) != CLOBBER \
&& get_attr_is_##NAME (X) == IS_##NAME##_YES) \
#define REVERSE_CONDITION(CODE,MODE) \
(((MODE) == CC_FP_GTmode || (MODE) == CC_FP_GEmode \
|| (MODE) == CC_FP_UNEQmode || (MODE) == CC_FP_ORDmode \
|| (MODE) == CC_FPXmode) \
? reverse_condition_maybe_unordered ((CODE)) \
: reverse_condition ((CODE)))
#define REVERSE_CONDITION(CODE,MODE) \
(((MODE) == CC_FP_GTmode || (MODE) == CC_FP_GEmode \
|| (MODE) == CC_FP_UNEQmode || (MODE) == CC_FP_ORDmode \
|| (MODE) == CC_FPXmode || (MODE) == CC_FPU_UNEQmode \
|| (MODE) == CC_FPUmode) \
? reverse_condition_maybe_unordered ((CODE)) \
: reverse_condition ((CODE)))
#define ADJUST_INSN_LENGTH(X, LENGTH) \
((LENGTH) \
@ -1724,4 +1733,26 @@ enum
been written to by an ordinary instruction. */
#define TARGET_LP_WR_INTERLOCK (!TARGET_ARC600_FAMILY)
/* FPU defines. */
/* Any FPU support. */
#define TARGET_HARD_FLOAT (arc_fpu_build != 0)
/* Single precision floating point support. */
#define TARGET_FP_SP_BASE ((arc_fpu_build & FPU_SP) != 0)
/* Double precision floating point support. */
#define TARGET_FP_DP_BASE ((arc_fpu_build & FPU_DP) != 0)
/* Single precision floating point support with fused operation. */
#define TARGET_FP_SP_FUSED ((arc_fpu_build & FPU_SF) != 0)
/* Double precision floating point support with fused operation. */
#define TARGET_FP_DP_FUSED ((arc_fpu_build & FPU_DF) != 0)
/* Single precision floating point conversion instruction support. */
#define TARGET_FP_SP_CONV ((arc_fpu_build & FPU_SC) != 0)
/* Double precision floating point conversion instruction support. */
#define TARGET_FP_DP_CONV ((arc_fpu_build & FPU_DC) != 0)
/* Single precision floating point SQRT/DIV instruction support. */
#define TARGET_FP_SP_SQRT ((arc_fpu_build & FPU_SD) != 0)
/* Double precision floating point SQRT/DIV instruction support. */
#define TARGET_FP_DP_SQRT ((arc_fpu_build & FPU_DD) != 0)
/* Double precision floating point assist instruction support. */
#define TARGET_FP_DP_AX ((arc_fpu_build & FPX_DP) != 0)
#endif /* GCC_ARC_H */

View File

@ -175,6 +175,7 @@
(ILINK2_REGNUM 30)
(RETURN_ADDR_REGNUM 31)
(MUL64_OUT_REG 58)
(ARCV2_ACC 58)
(LP_COUNT 60)
(CC_REG 61)
@ -201,7 +202,8 @@
simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
simd_valign, simd_valign_with_acc, simd_vcontrol,
simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem"
simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem,
fpu"
(cond [(eq_attr "is_sfunc" "yes")
(cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
(match_test "flag_pic") (const_string "sfunc")]
@ -3364,7 +3366,8 @@
})
(define_mode_iterator SDF [SF DF])
(define_mode_iterator SDF [(SF "TARGET_FP_SP_BASE || TARGET_OPTFPE")
(DF "TARGET_OPTFPE")])
(define_expand "cstore<mode>4"
[(set (reg:CC CC_REG)
@ -3374,7 +3377,7 @@
(match_operator:SI 1 "comparison_operator" [(reg CC_REG)
(const_int 0)]))]
"TARGET_OPTFPE"
"TARGET_FP_SP_BASE || TARGET_OPTFPE"
{
gcc_assert (XEXP (operands[1], 0) == operands[2]);
gcc_assert (XEXP (operands[1], 1) == operands[3]);
@ -5167,12 +5170,12 @@
(match_operand:SDF 2 "register_operand" "")))
(set (pc)
(if_then_else
(match_operator 0 "comparison_operator" [(reg CC_REG)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))]
(match_operator 0 "comparison_operator" [(reg CC_REG)
(const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_OPTFPE"
"TARGET_FP_SP_BASE || TARGET_OPTFPE"
{
gcc_assert (XEXP (operands[0], 0) == operands[1]);
gcc_assert (XEXP (operands[0], 1) == operands[2]);
@ -5624,9 +5627,155 @@
[(set_attr "length" "4")
(set_attr "type" "misc")])
;; FPU/FPX expands
;;add
(define_expand "addsf3"
[(set (match_operand:SF 0 "register_operand" "")
(plus:SF (match_operand:SF 1 "nonmemory_operand" "")
(match_operand:SF 2 "nonmemory_operand" "")))]
"TARGET_FP_SP_BASE || TARGET_SPFP"
"
if (!register_operand (operands[1], SFmode)
&& !register_operand (operands[2], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
")
;;sub
(define_expand "subsf3"
[(set (match_operand:SF 0 "register_operand" "")
(minus:SF (match_operand:SF 1 "nonmemory_operand" "")
(match_operand:SF 2 "nonmemory_operand" "")))]
"TARGET_FP_SP_BASE || TARGET_SPFP"
"
if (!register_operand (operands[1], SFmode)
&& !register_operand (operands[2], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
")
;;mul
(define_expand "mulsf3"
[(set (match_operand:SF 0 "register_operand" "")
(mult:SF (match_operand:SF 1 "nonmemory_operand" "")
(match_operand:SF 2 "nonmemory_operand" "")))]
"TARGET_FP_SP_BASE || TARGET_SPFP"
"
if (!register_operand (operands[1], SFmode)
&& !register_operand (operands[2], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
")
;;add
(define_expand "adddf3"
[(set (match_operand:DF 0 "double_register_operand" "")
(plus:DF (match_operand:DF 1 "double_register_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))]
"TARGET_FP_DP_BASE || TARGET_DPFP"
"
if (TARGET_DPFP)
{
if (GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
split_double (operands[2], &low, &high);
tmp = force_reg (SImode, high);
emit_insn (gen_adddf3_insn (operands[0], operands[1],
operands[2], tmp, const0_rtx));
}
else
emit_insn (gen_adddf3_insn (operands[0], operands[1],
operands[2], const1_rtx, const1_rtx));
DONE;
}
else if (TARGET_FP_DP_BASE)
{
if (!even_register_operand (operands[2], DFmode))
operands[2] = force_reg (DFmode, operands[2]);
if (!even_register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
}
else
gcc_unreachable ();
")
;;sub
(define_expand "subdf3"
[(set (match_operand:DF 0 "double_register_operand" "")
(minus:DF (match_operand:DF 1 "nonmemory_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))]
"TARGET_FP_DP_BASE || TARGET_DPFP"
"
if (TARGET_DPFP)
{
if ((GET_CODE (operands[1]) == CONST_DOUBLE)
|| GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1 : 2);
split_double (operands[const_index], &low, &high);
tmp = force_reg (SImode, high);
emit_insn (gen_subdf3_insn (operands[0], operands[1],
operands[2], tmp, const0_rtx));
}
else
emit_insn (gen_subdf3_insn (operands[0], operands[1],
operands[2], const1_rtx, const1_rtx));
DONE;
}
else if (TARGET_FP_DP_BASE)
{
if (!even_register_operand (operands[2], DFmode))
operands[2] = force_reg (DFmode, operands[2]);
if (!even_register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
}
else
gcc_unreachable ();
")
;;mul
(define_expand "muldf3"
[(set (match_operand:DF 0 "double_register_operand" "")
(mult:DF (match_operand:DF 1 "double_register_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))]
"TARGET_FP_DP_BASE || TARGET_DPFP"
"
if (TARGET_DPFP)
{
if (GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
split_double (operands[2], &low, &high);
tmp = force_reg (SImode, high);
emit_insn (gen_muldf3_insn (operands[0], operands[1],
operands[2], tmp, const0_rtx));
}
else
emit_insn (gen_muldf3_insn (operands[0], operands[1],
operands[2], const1_rtx, const1_rtx));
DONE;
}
else if (TARGET_FP_DP_BASE)
{
if (!even_register_operand (operands[2], DFmode))
operands[2] = force_reg (DFmode, operands[2]);
if (!even_register_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
}
else
gcc_unreachable ();
")
;; include the arc-FPX instructions
(include "fpx.md")
;; include the arc-FPU instructions
(include "fpu.md")
(include "simdext.md")
;; include atomic extensions

View File

@ -413,3 +413,46 @@ Enable atomic instructions.
mll64
Target Report Mask(LL64)
Enable double load/store instructions for ARC HS.
mfpu=
Target RejectNegative Joined Enum(arc_fpu) Var(arc_fpu_build) Init(0)
Specify the name of the target floating point configuration.
Enum
Name(arc_fpu) Type(int)
EnumValue
Enum(arc_fpu) String(fpus) Value(FPU_SP | FPU_SC)
EnumValue
Enum(arc_fpu) String(fpud) Value(FPU_SP | FPU_SC | FPU_DP | FPU_DC)
EnumValue
Enum(arc_fpu) String(fpuda) Value(FPU_SP | FPU_SC | FPX_DP)
EnumValue
Enum(arc_fpu) String(fpuda_div) Value(FPU_SP | FPU_SC | FPU_SD | FPX_DP)
EnumValue
Enum(arc_fpu) String(fpuda_fma) Value(FPU_SP | FPU_SC | FPU_SF | FPX_DP)
EnumValue
Enum(arc_fpu) String(fpuda_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPX_DP)
EnumValue
Enum(arc_fpu) String(fpus_div) Value(FPU_SP | FPU_SC | FPU_SD)
EnumValue
Enum(arc_fpu) String(fpud_div) Value(FPU_SP | FPU_SC | FPU_SD | FPU_DP | FPU_DC | FPU_DD)
EnumValue
Enum(arc_fpu) String(fpus_fma) Value(FPU_SP | FPU_SC | FPU_SF)
EnumValue
Enum(arc_fpu) String(fpud_fma) Value(FPU_SP | FPU_SC | FPU_SF | FPU_DP | FPU_DC | FPU_DF)
EnumValue
Enum(arc_fpu) String(fpus_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD)
EnumValue
Enum(arc_fpu) String(fpud_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPU_DP | FPU_DC | FPU_DF | FPU_DD)

566
gcc/config/arc/fpu.md Normal file
View File

@ -0,0 +1,566 @@
;; ::::::::::::::::::::
;; ::
;; :: 32-bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
;; Addition
(define_insn "*addsf3_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(plus:SF (match_operand:SF 1 "nonmemory_operand" "%0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
"TARGET_FP_SP_BASE
&& (register_operand (operands[1], SFmode)
|| register_operand (operands[2], SFmode))"
"fsadd%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
])
;; Subtraction
(define_insn "*subsf3_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(minus:SF (match_operand:SF 1 "nonmemory_operand" "0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
"TARGET_FP_SP_BASE
&& (register_operand (operands[1], SFmode)
|| register_operand (operands[2], SFmode))"
"fssub%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
])
;; Multiplication
(define_insn "*mulsf3_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(mult:SF (match_operand:SF 1 "nonmemory_operand" "%0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
"TARGET_FP_SP_BASE
&& (register_operand (operands[1], SFmode)
|| register_operand (operands[2], SFmode))"
"fsmul%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
])
;; Multiplication with addition/subtraction
(define_expand "fmasf4"
[(set (match_operand:SF 0 "register_operand" "")
(fma:SF (match_operand:SF 1 "nonmemory_operand" "")
(match_operand:SF 2 "nonmemory_operand" "")
(match_operand:SF 3 "nonmemory_operand" "")))]
"TARGET_FP_SP_FUSED"
"{
rtx tmp;
tmp = gen_rtx_REG (SFmode, ACCL_REGNO);
emit_move_insn (tmp, operands[3]);
operands[3] = tmp;
}")
(define_expand "fnmasf4"
[(set (match_operand:SF 0 "register_operand" "")
(fma:SF (neg:SF (match_operand:SF 1 "nonmemory_operand" ""))
(match_operand:SF 2 "nonmemory_operand" "")
(match_operand:SF 3 "nonmemory_operand" "")))]
"TARGET_FP_SP_FUSED"
"{
rtx tmp;
tmp = gen_rtx_REG (SFmode, ACCL_REGNO);
emit_move_insn (tmp, operands[3]);
operands[3] = tmp;
}")
(define_insn "fmasf4_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(fma:SF (match_operand:SF 1 "nonmemory_operand" "%0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")
(match_operand:SF 3 "mlo_operand" "")))]
"TARGET_FP_SP_FUSED
&& (register_operand (operands[1], SFmode)
|| register_operand (operands[2], SFmode))"
"fsmadd%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")])
(define_insn "fnmasf4_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(fma:SF (neg:SF (match_operand:SF 1 "nonmemory_operand" "%0,r,0,r,F"))
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")
(match_operand:SF 3 "mlo_operand" "")))]
"TARGET_FP_SP_FUSED
&& (register_operand (operands[1], SFmode)
|| register_operand (operands[2], SFmode))"
"fsmsub%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")])
(define_expand "fmadf4"
[(match_operand:DF 0 "even_register_operand" "")
(match_operand:DF 1 "even_register_operand" "")
(match_operand:DF 2 "even_register_operand" "")
(match_operand:DF 3 "even_register_operand" "")]
"TARGET_FP_DP_FUSED"
"{
emit_insn (gen_fmadf4_split (operands[0], operands[1], operands[2], operands[3]));
DONE;
}")
(define_insn_and_split "fmadf4_split"
[(set (match_operand:DF 0 "even_register_operand" "")
(fma:DF (match_operand:DF 1 "even_register_operand" "")
(match_operand:DF 2 "even_register_operand" "")
(match_operand:DF 3 "even_register_operand" "")))
(clobber (reg:DF ARCV2_ACC))]
"TARGET_FP_DP_FUSED"
"#"
"TARGET_FP_DP_FUSED"
[(const_int 0)]
"{
rtx acc_reg = gen_rtx_REG (DFmode, ACC_REG_FIRST);
emit_move_insn (acc_reg, operands[3]);
emit_insn (gen_fmadf4_fpu (operands[0], operands[1], operands[2]));
DONE;
}"
)
(define_expand "fnmadf4"
[(match_operand:DF 0 "even_register_operand" "")
(match_operand:DF 1 "even_register_operand" "")
(match_operand:DF 2 "even_register_operand" "")
(match_operand:DF 3 "even_register_operand" "")]
"TARGET_FP_DP_FUSED"
"{
emit_insn (gen_fnmadf4_split (operands[0], operands[1], operands[2], operands[3]));
DONE;
}")
(define_insn_and_split "fnmadf4_split"
[(set (match_operand:DF 0 "even_register_operand" "")
(fma:DF (neg:DF (match_operand:DF 1 "even_register_operand" ""))
(match_operand:DF 2 "even_register_operand" "")
(match_operand:DF 3 "even_register_operand" "")))
(clobber (reg:DF ARCV2_ACC))]
"TARGET_FP_DP_FUSED"
"#"
"TARGET_FP_DP_FUSED"
[(const_int 0)]
"{
rtx acc_reg = gen_rtx_REG (DFmode, ACC_REG_FIRST);
emit_move_insn (acc_reg, operands[3]);
emit_insn (gen_fnmadf4_fpu (operands[0], operands[1], operands[2]));
DONE;
}")
(define_insn "fmadf4_fpu"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(fma:DF (match_operand:DF 1 "even_register_operand" "%0,r")
(match_operand:DF 2 "even_register_operand" "r,r")
(reg:DF ARCV2_ACC)))]
"TARGET_FP_DP_FUSED"
"fdmadd%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")])
(define_insn "fnmadf4_fpu"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(fma:DF (neg:DF (match_operand:DF 1 "even_register_operand" "%0,r"))
(match_operand:DF 2 "even_register_operand" "r,r")
(reg:DF ARCV2_ACC)))]
"TARGET_FP_DP_FUSED"
"fdmsub%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")])
;; Division
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(div:SF (match_operand:SF 1 "nonmemory_operand" "0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
"TARGET_FP_SP_SQRT"
"fsdiv%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no,yes,no,no")
(set_attr "cond" "canuse,nocond,canuse_limm,nocond,nocond")
])
;; Negation
;; see pattern in arc.md
;; Absolute value
;; see pattern in arc.md
;; Square root
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(sqrt:SF (match_operand:SF 1 "nonmemory_operand" "r,F")))]
"TARGET_FP_SP_SQRT"
"fssqrt %0,%1"
[(set_attr "length" "4,8")
(set_attr "type" "fpu")])
;; Comparison
(define_insn "*cmpsf_fpu"
[(set (reg:CC_FPU CC_REG)
(compare:CC_FPU (match_operand:SF 0 "register_operand" "r,r")
(match_operand:SF 1 "nonmemory_operand" "r,F")))]
"TARGET_FP_SP_BASE"
"fscmp%? %0, %1"
[(set_attr "length" "4,8")
(set_attr "iscompact" "false")
(set_attr "cond" "set")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,yes")])
(define_insn "*cmpsf_fpu_uneq"
[(set (reg:CC_FPU_UNEQ CC_REG)
(compare:CC_FPU_UNEQ
(match_operand:SF 0 "register_operand" "r,r")
(match_operand:SF 1 "nonmemory_operand" "r,F")))]
"TARGET_FP_SP_BASE"
"fscmp %0, %1\\n\\tmov.v.f 0,0\\t;set Z flag"
[(set_attr "length" "8,12")
(set_attr "iscompact" "false")
(set_attr "cond" "set")
(set_attr "type" "fpu")])
;; ::::::::::::::::::::
;; ::
;; :: 64-bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
;; Addition
(define_insn "*adddf3_fpu"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(plus:DF (match_operand:DF 1 "even_register_operand" "%0,r")
(match_operand:DF 2 "even_register_operand" "r,r")))]
"TARGET_FP_DP_BASE"
"fdadd%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
])
;; Subtraction
(define_insn "*subdf3_fpu"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(minus:DF (match_operand:DF 1 "even_register_operand" "0,r")
(match_operand:DF 2 "even_register_operand" "r,r")))]
"TARGET_FP_DP_BASE"
"fdsub%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
])
;; Multiplication
(define_insn "*muldf3_fpu"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(mult:DF (match_operand:DF 1 "even_register_operand" "%0,r")
(match_operand:DF 2 "even_register_operand" "r,r")))]
"TARGET_FP_DP_BASE"
"fdmul%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
])
;; Division
(define_insn "divdf3"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(div:DF (match_operand:DF 1 "even_register_operand" "0,r")
(match_operand:DF 2 "even_register_operand" "r,r")))]
"TARGET_FP_DP_SQRT"
"fddiv%? %0,%1,%2"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")
(set_attr "cond" "canuse,nocond")
])
;; Square root
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "even_register_operand" "=r")
(sqrt:DF (match_operand:DF 1 "even_register_operand" "r")))]
"TARGET_FP_DP_SQRT"
"fdsqrt %0,%1"
[(set_attr "length" "4")
(set_attr "type" "fpu")])
;; Comparison
(define_insn "*cmpdf_fpu"
[(set (reg:CC_FPU CC_REG)
(compare:CC_FPU (match_operand:DF 0 "even_register_operand" "r")
(match_operand:DF 1 "even_register_operand" "r")))]
"TARGET_FP_DP_BASE"
"fdcmp%? %0, %1"
[(set_attr "length" "4")
(set_attr "iscompact" "false")
(set_attr "cond" "set")
(set_attr "type" "fpu")
(set_attr "predicable" "yes")])
(define_insn "*cmpdf_fpu_uneq"
[(set (reg:CC_FPU_UNEQ CC_REG)
(compare:CC_FPU_UNEQ
(match_operand:DF 0 "even_register_operand" "r")
(match_operand:DF 1 "even_register_operand" "r")))]
"TARGET_FP_DP_BASE"
"fdcmp %0, %1\\n\\tmov.v.f 0,0\\t;set Z flag"
[(set_attr "length" "8")
(set_attr "iscompact" "false")
(set_attr "cond" "set")
(set_attr "type" "fpu")])
;; ::::::::::::::::::::
;; ::
;; :: Conversion routines
;; ::
;; ::::::::::::::::::::
;; SF->DF
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(float_extend:DF (match_operand:SF 1 "register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt32_64%? %0,%1,0x04\\t;fs2d %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SI->DF
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(float:DF (match_operand:SI 1 "register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt32_64%? %0,%1,0x02\\t;fint2d %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; uSI->DF
(define_insn "floatunssidf2"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(unsigned_float:DF (match_operand:SI 1 "register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt32_64%? %0,%1,0x00\\t;fuint2d %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SF->uDI (using rounding towards zero)
(define_insn "fixuns_truncsfdi2"
[(set (match_operand:DI 0 "even_register_operand" "=r,r")
(unsigned_fix:DI (fix:SF (match_operand:SF 1 "register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt32_64%? %0,%1,0x09\\t;fs2ul_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SF->DI (using rounding towards zero)
(define_insn "fix_truncsfdi2"
[(set (match_operand:DI 0 "even_register_operand" "=r,r")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt32_64%? %0,%1,0x0B\\t;fs2l_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SI->SF
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(float:SF (match_operand:SI 1 "register_operand" "0,r")))]
"TARGET_FP_SP_CONV"
"fcvt32%? %0,%1,0x02\\t;fint2s %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; uSI->SF
(define_insn "floatunssisf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(unsigned_float:SF (match_operand:SI 1 "register_operand" "0,r")))]
"TARGET_FP_SP_CONV"
"fcvt32%? %0,%1,0x00\\t;fuint2s %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SF->uSI (using rounding towards zero)
(define_insn "fixuns_truncsfsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unsigned_fix:SI (fix:SF (match_operand:SF 1 "register_operand" "0,r"))))]
"TARGET_FP_SP_CONV"
"fcvt32%? %0,%1,0x09\\t;fs2uint_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; SF->SI (using rounding towards zero)
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "0,r"))))]
"TARGET_FP_SP_CONV"
"fcvt32%? %0,%1,0x0B\\t;fs2int_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DI->DF
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(float:DF (match_operand:DI 1 "even_register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt64%? %0,%1,0x02\\t;fl2d %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; uDI->DF
(define_insn "floatunsdidf2"
[(set (match_operand:DF 0 "even_register_operand" "=r,r")
(unsigned_float:DF (match_operand:DI 1 "even_register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt64%? %0,%1,0x00\\t;ful2d %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DF->uDI (using rounding towards zero)
(define_insn "fixuns_truncdfdi2"
[(set (match_operand:DI 0 "even_register_operand" "=r,r")
(unsigned_fix:DI (fix:DF (match_operand:DF 1 "even_register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt64%? %0,%1,0x09\\t;fd2ul_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DF->DI (using rounding towards zero)
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "even_register_operand" "=r,r")
(fix:DI (fix:DF (match_operand:DF 1 "even_register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt64%? %0,%1,0x0B\\t;fd2l_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DF->SF
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(float_truncate:SF (match_operand:DF 1 "even_register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt64_32%? %0,%1,0x04\\t;fd2s %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DI->SF
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(float:SF (match_operand:DI 1 "even_register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt64_32%? %0,%1,0x02\\t;fl2s %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; uDI->SF
(define_insn "floatunsdisf2"
[(set (match_operand:SF 0 "register_operand" "=r,r")
(unsigned_float:SF (match_operand:DI 1 "even_register_operand" "0,r")))]
"TARGET_FP_DP_CONV"
"fcvt64_32%? %0,%1,0x00\\t;ful2s %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DF->uSI (using rounding towards zero)
(define_insn "fixuns_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unsigned_fix:SI (fix:DF (match_operand:DF 1 "even_register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt64_32%? %0,%1,0x09\\t;fd2uint_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)
;; DF->SI (using rounding towards zero)
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI (fix:DF (match_operand:DF 1 "even_register_operand" "0,r"))))]
"TARGET_FP_DP_CONV"
"fcvt64_32%? %0,%1,0x0B\\t;fd2int_rz %0,%1"
[(set_attr "length" "4,4")
(set_attr "iscompact" "false")
(set_attr "type" "fpu")
(set_attr "predicable" "yes,no")]
)

View File

@ -50,7 +50,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "addsf3"
(define_insn "*addsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(plus:SF (match_operand:SF 1 "nonmemory_operand" "0,r,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "I,rL,r,GCal,LrCal")))]
@ -65,7 +65,7 @@
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
(define_insn "subsf3"
(define_insn "*subsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(minus:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
@ -80,7 +80,7 @@
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
(define_insn "mulsf3"
(define_insn "*mulsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(mult:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
@ -226,25 +226,6 @@
;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
;; OR
;; daddh{0}{1} 0, reg3, limm2.lo
(define_expand "adddf3"
[(set (match_operand:DF 0 "arc_double_register_operand" "")
(plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))
]
"TARGET_DPFP"
" if (GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
split_double (operands[2], &low, &high);
tmp = force_reg (SImode, high);
emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
}
else
emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
DONE;
"
)
;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
;; OR
;; daddh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0 */
@ -270,25 +251,6 @@
;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
;; OR
;; dmulh{0}{1} 0, reg3, limm2.lo
(define_expand "muldf3"
[(set (match_operand:DF 0 "arc_double_register_operand" "")
(mult:DF (match_operand:DF 1 "arc_double_register_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))]
"TARGET_DPFP"
" if (GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
split_double (operands[2], &low, &high);
tmp = force_reg (SImode, high);
emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
}
else
emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
DONE;
")
;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
;; OR
;; dmulh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
@ -317,26 +279,6 @@
;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo
;; OR
;; drsubh{0}{2} 0, reg3, limm1.lo
(define_expand "subdf3"
[(set (match_operand:DF 0 "arc_double_register_operand" "")
(minus:DF (match_operand:DF 1 "nonmemory_operand" "")
(match_operand:DF 2 "nonmemory_operand" "")))]
"TARGET_DPFP"
" if (GET_CODE (operands[1]) == CONST_DOUBLE || GET_CODE (operands[2]) == CONST_DOUBLE)
{
rtx high, low, tmp;
int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1: 2);
split_double (operands[const_index], &low, &high);
tmp = force_reg (SImode, high);
emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
}
else
emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
DONE;
"
)
;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1 */
;; OR
;; dsubh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/

View File

@ -504,6 +504,11 @@
return (code == EQ || code == NE || code == UNEQ || code == LTGT
|| code == ORDERED || code == UNORDERED);
case CC_FPUmode:
return 1;
case CC_FPU_UNEQmode:
return 1;
case CCmode:
case SImode: /* Used for BRcc. */
return 1;
@ -797,3 +802,7 @@
return (REG_P (op) && ((REGNO (op) >= FIRST_PSEUDO_REGISTER)
|| ((REGNO (op) & 1) == 0)));
})
(define_predicate "double_register_operand"
(ior (match_test "even_register_operand (op, mode)")
(match_test "arc_double_register_operand (op, mode)")))

View File

@ -599,7 +599,7 @@ Objective-C and Objective-C++ Dialects}.
-mmixed-code -mq-class -mRcq -mRcw -msize-level=@var{level} @gol
-mtune=@var{cpu} -mmultcost=@var{num} @gol
-munalign-prob-threshold=@var{probability} -mmpy-option=@var{multo} @gol
-mdiv-rem -mcode-density -mll64}
-mdiv-rem -mcode-density -mll64 -mfpu=@var{fpu}}
@emph{ARM Options}
@gccoptlist{-mapcs-frame -mno-apcs-frame @gol
@ -13325,6 +13325,88 @@ MPYU, MPYM, MPYMU, and MPY_S.
This option is only available for ARCv2 cores@.
@item -mfpu=@var{fpu}
@opindex mfpu
Enables specific floating-point hardware extension for ARCv2
core. Supported values for @var{fpu} are:
@table @samp
@item fpus
@opindex fpus
Enables support for single precision floating point hardware
extensions@.
@item fpud
@opindex fpud
Enables support for double precision floating point hardware
extensions. The single precision floating point extension is also
enabled. Not available for ARC EM@.
@item fpuda
@opindex fpuda
Enables support for double precision floating point hardware
extensions using double precision assist instructions. The single
precision floating point extension is also enabled. This option is
only available for ARC EM@.
@item fpuda_div
@opindex fpuda_div
Enables support for double precision floating point hardware
extensions using double precision assist instructions, and simple
precision square-root and divide hardware extensions. The single
precision floating point extension is also enabled. This option is
only available for ARC EM@.
@item fpuda_fma
@opindex fpuda_fma
Enables support for double precision floating point hardware
extensions using double precision assist instructions, and simple
precision fused multiple and add hardware extension. The single
precision floating point extension is also enabled. This option is
only available for ARC EM@.
@item fpuda_all
@opindex fpuda_all
Enables support for double precision floating point hardware
extensions using double precision assist instructions, and all simple
precision hardware extensions. The single precision floating point
extension is also enabled. This option is only available for ARC EM@.
@item fpus_div
@opindex fpus_div
Enables support for single precision floating point, and single
precision square-root and divide hardware extensions@.
@item fpud_div
@opindex fpud_div
Enables support for double precision floating point, and double
precision square-root and divide hardware extensions. This option
includes option @samp{fpus_div}. Not available for ARC EM@.
@item fpus_fma
@opindex fpus_fma
Enables support for single precision floating point, and single
precision fused multiple and add hardware extensions@.
@item fpud_fma
@opindex fpud_fma
Enables support for double precision floating point, and double
precision fused multiple and add hardware extensions. This option
includes option @samp{fpus_fma}. Not available for ARC EM@.
@item fpus_all
@opindex fpus_all
Enables support for all single precision floating point hardware
extensions@.
@item fpud_all
@opindex fpud_all
Enables support for all single and double precision floating point
hardware extensions. Not available for ARC EM@.
@end table
@end table
The following options are passed through to the assembler, and also