diff options
author | claziss <claziss@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-16 14:11:24 +0000 |
---|---|---|
committer | claziss <claziss@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-16 14:11:24 +0000 |
commit | 74d6399477fcad989ca6493821fa32a9a5588b2f (patch) | |
tree | da942afd8cfd2f846b537d732131dfa2f973eb74 /gcc/config/arc | |
parent | e73a0c13a120374db2d874e1b789af300311cd97 (diff) | |
download | gcc-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.def | 4 | ||||
-rw-r--r-- | gcc/config/arc/arc-opts.h | 20 | ||||
-rw-r--r-- | gcc/config/arc/arc.c | 152 | ||||
-rw-r--r-- | gcc/config/arc/arc.h | 57 | ||||
-rw-r--r-- | gcc/config/arc/arc.md | 165 | ||||
-rw-r--r-- | gcc/config/arc/arc.opt | 43 | ||||
-rw-r--r-- | gcc/config/arc/fpu.md | 566 | ||||
-rw-r--r-- | gcc/config/arc/fpx.md | 64 | ||||
-rw-r--r-- | gcc/config/arc/predicates.md | 9 |
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)"))) |