From 9fc777ad2561e542ef0eec9d94ee8cb5edc68554 Mon Sep 17 00:00:00 2001 From: Chao-ying Fu Date: Tue, 11 Sep 2007 01:04:08 +0000 Subject: [PATCH] mips.c (mips_scalar_mode_supported_p): Declare. * config/mips/mips.c (mips_scalar_mode_supported_p): Declare. (TARGET_SCALAR_MODE_SUPPORTED_P): Define. (mips_emit_compare): Process fixed-point modes. (mips_pad_arg_upward): Support fixed-point types. (override_options): Allow fixed-point modes in accumulators. (mips_pass_by_reference): Pass DQ, UDQ, DA, and UDA modes in registers. (mips_vector_mode_supported_p): Support V2HQmode, V2UHQmode, V2HAmode, V2UHAmode, V4QQmode, and V4UQQmode when TARGET_DSP. (mips_scalar_mode_supported_p): New function to accept fixed-point modes if the width is not greater than two BITS_PER_WORD. * config/mips/mips.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE, LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE, SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE, LONG_LONG_ACCUM_TYPE_SIZE): Define. * config/mips/mips.md ("d"): Update mode attribute for fixed-point modes. ("IMODE"): New mode attribute. (mips-fixed.md): Include. * config/mips/mips-modes.def: Create VECTOR_MODES for FRACT, UFRACT, ACCUM, UACCUM. * config/mips/mips-fixed.md: New file. From-SVN: r128360 --- gcc/ChangeLog | 24 ++++++ gcc/config/mips/mips-fixed.md | 138 +++++++++++++++++++++++++++++++++ gcc/config/mips/mips-modes.def | 5 ++ gcc/config/mips/mips.c | 42 +++++++++- gcc/config/mips/mips.h | 13 ++++ gcc/config/mips/mips.md | 18 ++++- 6 files changed, 235 insertions(+), 5 deletions(-) create mode 100644 gcc/config/mips/mips-fixed.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c02cd4b02b0..223e8fe90c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2007-09-10 Chao-ying Fu + + * config/mips/mips.c (mips_scalar_mode_supported_p): Declare. + (TARGET_SCALAR_MODE_SUPPORTED_P): Define. + (mips_emit_compare): Process fixed-point modes. + (mips_pad_arg_upward): Support fixed-point types. + (override_options): Allow fixed-point modes in accumulators. + (mips_pass_by_reference): Pass DQ, UDQ, DA, and UDA modes in registers. + (mips_vector_mode_supported_p): Support V2HQmode, V2UHQmode, V2HAmode, + V2UHAmode, V4QQmode, and V4UQQmode when TARGET_DSP. + (mips_scalar_mode_supported_p): New function to accept fixed-point + modes if the width is not greater than two BITS_PER_WORD. + * config/mips/mips.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE, + LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE, + SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE, + LONG_LONG_ACCUM_TYPE_SIZE): Define. + * config/mips/mips.md ("d"): Update mode attribute for fixed-point + modes. + ("IMODE"): New mode attribute. + (mips-fixed.md): Include. + * config/mips/mips-modes.def: Create VECTOR_MODES for FRACT, UFRACT, + ACCUM, UACCUM. + * config/mips/mips-fixed.md: New file. + 2007-09-11 Ben Elliston * config/spu/spu.md: Formatting fixes. diff --git a/gcc/config/mips/mips-fixed.md b/gcc/config/mips/mips-fixed.md new file mode 100644 index 00000000000..3305be8b35a --- /dev/null +++ b/gcc/config/mips/mips-fixed.md @@ -0,0 +1,138 @@ +;; This file contains MIPS instructions that support fixed-point operations. + +;; All supported fixed-point modes +(define_mode_iterator FIXED [(QQ "") (HQ "") (SQ "") (DQ "TARGET_64BIT") + (UQQ "") (UHQ "") (USQ "") (UDQ "TARGET_64BIT") + (HA "") (SA "") (DA "TARGET_64BIT") + (UHA "") (USA "") (UDA "TARGET_64BIT")]) + +;; For signed add/sub with saturation +(define_mode_iterator ADDSUB [(HQ "") (SQ "") (HA "") (SA "") (V2HQ "") + (V2HA "")]) +(define_mode_attr addsubfmt [(HQ "ph") (SQ "w") (HA "ph") (SA "w") + (V2HQ "ph") (V2HA "ph")]) + +;; For unsigned add/sub with saturation +(define_mode_iterator UADDSUB [(UQQ "TARGET_DSP") (UHQ "TARGET_DSPR2") + (UHA "TARGET_DSPR2") (V4UQQ "TARGET_DSP") + (V2UHQ "TARGET_DSPR2") (V2UHA "TARGET_DSPR2")]) +(define_mode_attr uaddsubfmt [(UQQ "qb") (UHQ "ph") (UHA "ph") + (V4UQQ "qb") (V2UHQ "ph") (V2UHA "ph")]) + +;; For signed multiplication with saturation +(define_mode_iterator MULQ [(V2HQ "TARGET_DSP") (HQ "TARGET_DSP") + (SQ "TARGET_DSPR2")]) +(define_mode_attr mulqfmt [(V2HQ "ph") (HQ "ph") (SQ "w")]) + +(define_insn "add3" + [(set (match_operand:FIXED 0 "register_operand" "=d") + (plus:FIXED (match_operand:FIXED 1 "register_operand" "d") + (match_operand:FIXED 2 "register_operand" "d")))] + "" + "addu\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "usadd3" + [(parallel + [(set (match_operand:UADDSUB 0 "register_operand" "=d") + (us_plus:UADDSUB (match_operand:UADDSUB 1 "register_operand" "d") + (match_operand:UADDSUB 2 "register_operand" "d"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])] + "" + "addu_s.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "ssadd3" + [(parallel + [(set (match_operand:ADDSUB 0 "register_operand" "=d") + (ss_plus:ADDSUB (match_operand:ADDSUB 1 "register_operand" "d") + (match_operand:ADDSUB 2 "register_operand" "d"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])] + "TARGET_DSP" + "addq_s.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "sub3" + [(set (match_operand:FIXED 0 "register_operand" "=d") + (minus:FIXED (match_operand:FIXED 1 "register_operand" "d") + (match_operand:FIXED 2 "register_operand" "d")))] + "" + "subu\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "ussub3" + [(parallel + [(set (match_operand:UADDSUB 0 "register_operand" "=d") + (us_minus:UADDSUB (match_operand:UADDSUB 1 "register_operand" "d") + (match_operand:UADDSUB 2 "register_operand" "d"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])] + "" + "subu_s.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "sssub3" + [(parallel + [(set (match_operand:ADDSUB 0 "register_operand" "=d") + (ss_minus:ADDSUB (match_operand:ADDSUB 1 "register_operand" "d") + (match_operand:ADDSUB 2 "register_operand" "d"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])] + "TARGET_DSP" + "subq_s.\t%0,%1,%2" + [(set_attr "type" "arith") + (set_attr "mode" "")]) + +(define_insn "ssmul3" + [(parallel + [(set (match_operand:MULQ 0 "register_operand" "=d") + (ss_mult:MULQ (match_operand:MULQ 1 "register_operand" "d") + (match_operand:MULQ 2 "register_operand" "d"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULQ_RS_PH)) + (clobber (match_scratch:DI 3 "=x"))])] + "" + "mulq_rs.\t%0,%1,%2" + [(set_attr "type" "imul3") + (set_attr "mode" "")]) + +(define_insn "ssmaddsqdq4" + [(parallel + [(set (match_operand:DQ 0 "register_operand" "=a") + (ss_plus:DQ + (ss_mult:DQ (sat_fract:DQ (match_operand:SQ 1 + "register_operand" "d")) + (sat_fract:DQ (match_operand:SQ 2 + "register_operand" "d"))) + (match_operand:DQ 3 "register_operand" "0"))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)] + UNSPEC_DPAQ_SA_L_W))])] + "TARGET_DSP && !TARGET_64BIT" + "dpaq_sa.l.w\t%q0,%1,%2" + [(set_attr "type" "imadd") + (set_attr "mode" "SI")]) + +(define_insn "ssmsubsqdq4" + [(parallel + [(set (match_operand:DQ 0 "register_operand" "=a") + (ss_minus:DQ + (match_operand:DQ 3 "register_operand" "0") + (ss_mult:DQ (sat_fract:DQ (match_operand:SQ 1 + "register_operand" "d")) + (sat_fract:DQ (match_operand:SQ 2 + "register_operand" "d"))))) + (set (reg:CCDSP CCDSP_OU_REGNUM) + (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)] + UNSPEC_DPSQ_SA_L_W))])] + "TARGET_DSP && !TARGET_64BIT" + "dpsq_sa.l.w\t%q0,%1,%2" + [(set_attr "type" "imadd") + (set_attr "mode" "SI")]) diff --git a/gcc/config/mips/mips-modes.def b/gcc/config/mips/mips-modes.def index 3d6e2a57581..207f6da060b 100644 --- a/gcc/config/mips/mips-modes.def +++ b/gcc/config/mips/mips-modes.def @@ -29,6 +29,11 @@ FLOAT_MODE (TF, 16, mips_quad_format); VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */ VECTOR_MODES (INT, 4); /* V4QI V2HI */ +VECTOR_MODES (FRACT, 4); /* V4QQ V2HQ */ +VECTOR_MODES (UFRACT, 4); /* V4UQQ V2UHQ */ +VECTOR_MODES (ACCUM, 4); /* V2HA */ +VECTOR_MODES (UACCUM, 4); /* V2UHA */ + /* Paired single comparison instructions use 2 or 4 CC. */ CC_MODE (CCV2); ADJUST_BYTESIZE (CCV2, 8); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 4a180da7468..14f0de2f945 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -408,6 +408,7 @@ static bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode, static int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode, tree, bool); static bool mips_valid_pointer_mode (enum machine_mode); +static bool mips_scalar_mode_supported_p (enum machine_mode); static bool mips_vector_mode_supported_p (enum machine_mode); static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree, unsigned int); static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx); @@ -1329,6 +1330,9 @@ static const unsigned char mips16e_save_restore_regs[] = { #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p +#undef TARGET_SCALAR_MODE_SUPPORTED_P +#define TARGET_SCALAR_MODE_SUPPORTED_P mips_scalar_mode_supported_p + #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS mips_init_builtins #undef TARGET_EXPAND_BUILTIN @@ -3626,6 +3630,13 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) *code = (invert ? EQ : NE); } } + else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_operands[0]))) + { + *op0 = gen_rtx_REG (CCDSPmode, CCDSP_CC_REGNUM); + mips_emit_binary (*code, *op0, cmp_operands[0], cmp_operands[1]); + *code = NE; + *op1 = const0_rtx; + } else { enum rtx_code cmp_code; @@ -4470,8 +4481,11 @@ mips_pad_arg_upward (enum machine_mode mode, const_tree type) /* Otherwise, integral types are padded downward: the last byte of a stack argument is passed in the last byte of the stack slot. */ if (type != 0 - ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type) - : GET_MODE_CLASS (mode) == MODE_INT) + ? (INTEGRAL_TYPE_P (type) + || POINTER_TYPE_P (type) + || FIXED_POINT_TYPE_P (type)) + : (GET_MODE_CLASS (mode) == MODE_INT + || ALL_SCALAR_FIXED_POINT_MODE_P (mode))) return false; /* Big-endian o64 pads floating-point arguments downward. */ @@ -5737,7 +5751,7 @@ override_options (void) || (ISA_HAS_8CC && mode == TFmode))); else if (ACC_REG_P (regno)) - temp = (INTEGRAL_MODE_P (mode) + temp = ((INTEGRAL_MODE_P (mode) || ALL_FIXED_POINT_MODE_P (mode)) && size <= UNITS_PER_WORD * 2 && (size <= UNITS_PER_WORD || regno == MD_REG_FIRST @@ -8749,7 +8763,9 @@ mips_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, int size; /* ??? How should SCmode be handled? */ - if (mode == DImode || mode == DFmode) + if (mode == DImode || mode == DFmode + || mode == DQmode || mode == UDQmode + || mode == DAmode || mode == UDAmode) return 0; size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); @@ -9011,12 +9027,30 @@ mips_vector_mode_supported_p (enum machine_mode mode) case V2HImode: case V4QImode: + case V2HQmode: + case V2UHQmode: + case V2HAmode: + case V2UHAmode: + case V4QQmode: + case V4UQQmode: return TARGET_DSP; default: return false; } } + +/* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ + +static bool +mips_scalar_mode_supported_p (enum machine_mode mode) +{ + if (ALL_FIXED_POINT_MODE_P (mode) + && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD) + return true; + + return default_scalar_mode_supported_p (mode); +} /* If we can access small data directly (using gp-relative relocation operators) return the small data pointer, otherwise return null. diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 9fe11d0dce8..a8957686240 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1189,6 +1189,19 @@ extern enum mips_code_readable_setting mips_code_readable; #define DOUBLE_TYPE_SIZE 64 #define LONG_DOUBLE_TYPE_SIZE (TARGET_NEWABI ? 128 : 64) +/* Define the sizes of fixed-point types. */ +#define SHORT_FRACT_TYPE_SIZE 8 +#define FRACT_TYPE_SIZE 16 +#define LONG_FRACT_TYPE_SIZE 32 +#define LONG_LONG_FRACT_TYPE_SIZE 64 + +#define SHORT_ACCUM_TYPE_SIZE 16 +#define ACCUM_TYPE_SIZE 32 +#define LONG_ACCUM_TYPE_SIZE 64 +/* FIXME. LONG_LONG_ACCUM_TYPE_SIZE should be 128 bits, but GCC + doesn't support 128-bit integers for MIPS32 currently. */ +#define LONG_LONG_ACCUM_TYPE_SIZE (TARGET_64BIT ? 128 : 64) + /* long double is not a fixed mode, but the idea is that, if we support long double, we also want a 128-bit integer type. */ #define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 42f9b1ea323..a6a5ea4a20f 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -497,7 +497,11 @@ ;; In GPR templates, a string like "subu" will expand to "subu" in the ;; 32-bit version and "dsubu" in the 64-bit version. -(define_mode_attr d [(SI "") (DI "d")]) +(define_mode_attr d [(SI "") (DI "d") + (QQ "") (HQ "") (SQ "") (DQ "d") + (UQQ "") (UHQ "") (USQ "") (UDQ "d") + (HA "") (SA "") (DA "d") + (UHA "") (USA "") (UDA "d")]) ;; This attribute gives the length suffix for a sign- or zero-extension ;; instruction. @@ -530,6 +534,15 @@ ;; floating-point mode. (define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")]) +;; This attribute gives the integer mode that has the same size as a +;; fixed-point mode. +(define_mode_attr IMODE [(QQ "QI") (HQ "HI") (SQ "SI") (DQ "DI") + (UQQ "QI") (UHQ "HI") (USQ "SI") (UDQ "DI") + (HA "HI") (SA "SI") (DA "DI") + (UHA "HI") (USA "SI") (UDA "DI") + (V4UQQ "SI") (V2UHQ "SI") (V2UHA "SI") + (V2HQ "SI") (V2HA "SI")]) + ;; This attribute works around the early SB-1 rev2 core "F2" erratum: ;; ;; In certain cases, div.s and div.ps may have a rounding error @@ -6009,3 +6022,6 @@ ; The MIPS DSP REV 2 Instructions. (include "mips-dspr2.md") + +; MIPS fixed-point instructions. +(include "mips-fixed.md") -- 2.30.2