summaryrefslogtreecommitdiff
path: root/gcc/config/arc
diff options
context:
space:
mode:
authorclaziss <claziss@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-16 14:11:24 +0000
committerclaziss <claziss@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-16 14:11:24 +0000
commit74d6399477fcad989ca6493821fa32a9a5588b2f (patch)
treeda942afd8cfd2f846b537d732131dfa2f973eb74 /gcc/config/arc
parente73a0c13a120374db2d874e1b789af300311cd97 (diff)
downloadgcc-74d6399477fcad989ca6493821fa32a9a5588b2f.tar.gz
[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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233451 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arc')
-rw-r--r--gcc/config/arc/arc-modes.def4
-rw-r--r--gcc/config/arc/arc-opts.h20
-rw-r--r--gcc/config/arc/arc.c152
-rw-r--r--gcc/config/arc/arc.h57
-rw-r--r--gcc/config/arc/arc.md165
-rw-r--r--gcc/config/arc/arc.opt43
-rw-r--r--gcc/config/arc/fpu.md566
-rw-r--r--gcc/config/arc/fpx.md64
-rw-r--r--gcc/config/arc/predicates.md9
9 files changed, 977 insertions, 103 deletions
diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def
index b64a596082e..921a59876a1 100644
--- a/gcc/config/arc/arc-modes.def
+++ b/gcc/config/arc/arc-modes.def
@@ -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);
diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
index 0f128850431..1e11ebc41ff 100644
--- a/gcc/config/arc/arc-opts.h
+++ b/gcc/config/arc/arc-opts.h
@@ -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
+
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index b9799a016cb..d60db502ef8 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -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. */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 27665b0caa7..21c049f9850 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -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 */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 6a8ec83b286..4193d2610f1 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -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
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index 00b98d58f54..2227b7554c3 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -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)
diff --git a/gcc/config/arc/fpu.md b/gcc/config/arc/fpu.md
new file mode 100644
index 00000000000..9b0a65d9386
--- /dev/null
+++ b/gcc/config/arc/fpu.md
@@ -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")]
+)
diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
index a4ecc4a9bf2..b7906003748 100644
--- a/gcc/config/arc/fpx.md
+++ b/gcc/config/arc/fpx.md
@@ -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*/
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
index d384d70f7d6..85bbf843558 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -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)")))