aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChao-ying Fu <fu@mips.com>2007-09-11 01:04:08 +0000
committerChao-ying Fu <chaoyingfu@gcc.gnu.org>2007-09-11 01:04:08 +0000
commit9fc777ad2561e542ef0eec9d94ee8cb5edc68554 (patch)
tree90489292cc9aae88f88ecd159e05429ec37d914c
parent9ccaf0a6285b6b9d346cb0e3b8593ab89ef8fd46 (diff)
downloadgcc-9fc777ad2561e542ef0eec9d94ee8cb5edc68554.zip
gcc-9fc777ad2561e542ef0eec9d94ee8cb5edc68554.tar.gz
gcc-9fc777ad2561e542ef0eec9d94ee8cb5edc68554.tar.bz2
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
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/mips/mips-fixed.md138
-rw-r--r--gcc/config/mips/mips-modes.def5
-rw-r--r--gcc/config/mips/mips.c42
-rw-r--r--gcc/config/mips/mips.h13
-rw-r--r--gcc/config/mips/mips.md18
6 files changed, 235 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c02cd4b..223e8fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2007-09-10 Chao-ying Fu <fu@mips.com>
+
+ * 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 <bje@au.ibm.com>
* 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 0000000..3305be8
--- /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 "add<mode>3"
+ [(set (match_operand:FIXED 0 "register_operand" "=d")
+ (plus:FIXED (match_operand:FIXED 1 "register_operand" "d")
+ (match_operand:FIXED 2 "register_operand" "d")))]
+ ""
+ "<d>addu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "usadd<mode>3"
+ [(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.<uaddsubfmt>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "ssadd<mode>3"
+ [(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.<addsubfmt>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:FIXED 0 "register_operand" "=d")
+ (minus:FIXED (match_operand:FIXED 1 "register_operand" "d")
+ (match_operand:FIXED 2 "register_operand" "d")))]
+ ""
+ "<d>subu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "ussub<mode>3"
+ [(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.<uaddsubfmt>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "sssub<mode>3"
+ [(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.<addsubfmt>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<IMODE>")])
+
+(define_insn "ssmul<mode>3"
+ [(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.<mulqfmt>\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "<IMODE>")])
+
+(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 3d6e2a5..207f6da 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 4a180da..14f0de2 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 9fe11d0..a8957686 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 42f9b1e..a6a5ea4 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -497,7 +497,11 @@
;; In GPR templates, a string like "<d>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")