mips.c (mips_scalar_mode_supported_p): Declare.
authorChao-ying Fu <fu@mips.com>
Tue, 11 Sep 2007 01:04:08 +0000 (01:04 +0000)
committerChao-ying Fu <chaoyingfu@gcc.gnu.org>
Tue, 11 Sep 2007 01:04:08 +0000 (01:04 +0000)
* 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
gcc/config/mips/mips-fixed.md [new file with mode: 0644]
gcc/config/mips/mips-modes.def
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index c02cd4b02b04b6a15355a52e6b6cb5a6e3f25542..223e8fe90c3f73ec2d927be157e37cac147060f2 100644 (file)
@@ -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 (file)
index 0000000..3305be8
--- /dev/null
@@ -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")])
index 3d6e2a575816331ca42e4c50d57fd77f3fef6b86..207f6da060b770f8fd5f37c7e93c33cae7535eaa 100644 (file)
@@ -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);
index 4a180da7468c8ce4a0ee7534f056f5765148c4f4..14f0de2f9451db451659d7096802bcda7e3e1aee 100644 (file)
@@ -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);
+}
 \f
 /* If we can access small data directly (using gp-relative relocation
    operators) return the small data pointer, otherwise return null.
index 9fe11d0dce8fac98b2f77982539a1c087739267e..a8957686240dac9bd045563cc10fe74fe1ee19a9 100644 (file)
@@ -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
index 42f9b1ea323903d12d0be52036ff890e92987116..a6a5ea4a20f04ac89b413d34ff9b0e9f34da7561 100644 (file)
 
 ;; 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.
 ;; 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
 ; The MIPS DSP REV 2 Instructions.
 
 (include "mips-dspr2.md")
+
+; MIPS fixed-point instructions.
+(include "mips-fixed.md")