Octeon2 includes the indexed load instructions from the DSP ASE and a
few extensions on top of those: lbx, lhux, and lwux.
This patch adds to GCC support for the DSP64 instruction ldx and also
all of the Octeon2 extensions.
I only added the builtin function for ldx to be the same as the other
l*x DSP ASE.

Ok? Bootstrapped and tested on mips64-linux-gnu (with
{-march=octeon,-march=octeon2}/{-march=n32,-march=64} ).

Thanks,
Andrew Pinski

gcc/ChangeLog:
* config/mips/mips.md (size): Add SI and DI.
(SIZE): New mode attribute.
(U): New code attribute.
* config/mips/mips-dsp.md (mips_lbux): Use gen_mips_lbux_extsi.
(mips_lbux_<mode>): Delete.
(mips_l<SHORT:size><u>x_ext<GPR:mode>_<P:mode>): New pattern.
(mips_lhx): Use gen_mips_lhx_extsi.
(mips_lhx_<mode>): Delete.
(mips_lwx_<mode>): Delete.
(mips_ldx): New expand.
(mips_l<GPR:size>x_<P:mode>): New pattern.
(*mips_lw<u>x_<P:mode>_ext): Likewise.
* config/mips/mips-ftypes.def: Add DI f(POINTER, SI) function type.
* config/mips/mips.c (mips_loadindexed_address_p): New function.
(mips_rtx_costs <case MEM>): Call mips_loadindexed_address_p.
(dsp64): New availability predicate.
(mips_builtins): Add an entry for __builtin_mips_ldx.
* config/mips/mips.h (ISA_HAS_LBX): New define.
(ISA_HAS_LBUX): Likewise.
(ISA_HAS_LHX): Likewise.
(ISA_HAS_LHUX): Likewise.
(ISA_HAS_LWX): Likewise.
(ISA_HAS_LWUX): Likewise.
(ISA_HAS_LDX): Likewise.

gcc/testsuite/ChangeLog:
* gcc.target/mips/mips64-dsp-ldx1.c: New test.
* gcc.target/mips/octeon2-lx-1.c: New test.
* gcc.target/mips/mips64-dsp-ldx.c: New test.
* gcc.target/mips/octeon2-lx-2.c: New test.
* gcc.target/mips/octeon2-lx-3.c: New test.
Index: testsuite/gcc.target/mips/mips64-dsp-ldx1.c
===================================================================
--- testsuite/gcc.target/mips/mips64-dsp-ldx1.c (revision 0)
+++ testsuite/gcc.target/mips/mips64-dsp-ldx1.c (revision 0)
@@ -0,0 +1,10 @@
+/* Test MIPS64 DSP instructions */
+/* { dg-do compile } */
+/* { dg-options "-mgp64 -mdsp" }  */
+
+/* { dg-final { scan-assembler "\tldx\t" } } */
+
+NOMIPS16 signed long long test (signed long long *a, int index)
+{
+  return __builtin_mips_ldx (a, index);
+}
Index: testsuite/gcc.target/mips/octeon2-lx-1.c
===================================================================
--- testsuite/gcc.target/mips/octeon2-lx-1.c    (revision 0)
+++ testsuite/gcc.target/mips/octeon2-lx-1.c    (revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=octeon2 -O -mgp64" } */
+
+#define TEST(N, R, T) \
+  T f##N (T j, R *b, long long i) { return j + b[i]; } \
+  T g##N (T j, unsigned R *b, long long i) { return j + b[i]; }
+
+TEST (1, char, int)
+TEST (2, char, long long)
+/* { dg-final { scan-assembler-times "\tlbx\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tlbux\t" 2 } } */
+TEST (3, short, int)
+TEST (4, short, long long)
+/* { dg-final { scan-assembler-times "\tlhx\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tlhux\t" 2 } } */
+TEST (5, int, long long)
+/* { dg-final { scan-assembler-times "\tlwx\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tlwux\t" 1 } } */
Index: testsuite/gcc.target/mips/mips64-dsp-ldx.c
===================================================================
--- testsuite/gcc.target/mips/mips64-dsp-ldx.c  (revision 0)
+++ testsuite/gcc.target/mips/mips64-dsp-ldx.c  (revision 0)
@@ -0,0 +1,10 @@
+/* Test MIPS64 DSP instructions */
+/* { dg-do compile } */
+/* { dg-options "-mgp64 -mdsp -O" } */
+
+/* { dg-final { scan-assembler "\tldx\t" } } */
+
+NOMIPS16 signed long long test (signed long long *a, int index)
+{
+  return a[index];
+}
Index: testsuite/gcc.target/mips/octeon2-lx-2.c
===================================================================
--- testsuite/gcc.target/mips/octeon2-lx-2.c    (revision 0)
+++ testsuite/gcc.target/mips/octeon2-lx-2.c    (revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=octeon2 -O -mgp64" } */
+
+#define TEST(N, T) \
+  T f##N (T *p, int i) { return p[i]; } \
+  unsigned T g##N (unsigned T *p, int i) { return p[i]; }
+
+TEST (1, char)
+/* { dg-final { scan-assembler-times "\tlbu?x\t" 2 } } */
+TEST (2, short)
+/* { dg-final { scan-assembler-times "\tlhu?x\t" 2 } } */
+TEST (3, int)
+/* { dg-final { scan-assembler-times "\tlwx\t" 2 } } */
+TEST (4, long long)
+/* { dg-final { scan-assembler-times "\tldx\t" 2 } } */
Index: testsuite/gcc.target/mips/octeon2-lx-3.c
===================================================================
--- testsuite/gcc.target/mips/octeon2-lx-3.c    (revision 0)
+++ testsuite/gcc.target/mips/octeon2-lx-3.c    (revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=octeon2 -O -mgp32" } */
+
+#define TEST(N, T) \
+  T f##N (T *p, int i) { return p[i]; } \
+  unsigned T g##N (unsigned T *p, int i) { return p[i]; }
+
+TEST (1, char)
+/* { dg-final { scan-assembler-times "\tlbu?x\t" 2 } } */
+TEST (2, short)
+/* { dg-final { scan-assembler-times "\tlhu?x\t" 2 } } */
+TEST (3, int)
+/* { dg-final { scan-assembler-times "\tlwx\t" 2 } } */
Index: config/mips/mips-dsp.md
===================================================================
--- config/mips/mips-dsp.md     (revision 182342)
+++ config/mips/mips-dsp.md     (working copy)
@@ -1105,20 +1105,21 @@ (define_expand "mips_lbux"
   "ISA_HAS_DSP"
 {
   operands[2] = convert_to_mode (Pmode, operands[2], false);
-  emit_insn (PMODE_INSN (gen_mips_lbux,
+  emit_insn (PMODE_INSN (gen_mips_lbux_extsi,
                         (operands[0], operands[1], operands[2])));
   DONE;
 })
 
-(define_insn "mips_lbux_<mode>"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (zero_extend:SI
-         (mem:QI (plus:P (match_operand:P 1 "register_operand" "d")
-                         (match_operand:P 2 "register_operand" "d")))))]
-  "ISA_HAS_DSP"
-  "lbux\t%0,%2(%1)"
+(define_insn "mips_l<SHORT:size><u>x_ext<GPR:mode>_<P:mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (any_extend:GPR
+         (mem:SHORT (plus:P (match_operand:P 1 "register_operand" "d")
+                            (match_operand:P 2 "register_operand" "d")))))]
+  "ISA_HAS_L<SHORT:SIZE><U>X"
+  "l<SHORT:size><u>x\t%0,%2(%1)"
   [(set_attr "type"    "load")
-   (set_attr "mode"    "SI")])
+   (set_attr "mode"    "<GPR:MODE>")
+   (set_attr "length"  "4")])
 
 (define_expand "mips_lhx"
   [(match_operand:SI 0 "register_operand")
@@ -1127,21 +1128,11 @@ (define_expand "mips_lhx"
   "ISA_HAS_DSP"
 {
   operands[2] = convert_to_mode (Pmode, operands[2], false);
-  emit_insn (PMODE_INSN (gen_mips_lhx,
+  emit_insn (PMODE_INSN (gen_mips_lhx_extsi,
                         (operands[0], operands[1], operands[2])));
   DONE;
 })
 
-(define_insn "mips_lhx_<mode>"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (sign_extend:SI
-         (mem:HI (plus:P (match_operand:P 1 "register_operand" "d")
-                         (match_operand:P 2 "register_operand" "d")))))]
-  "ISA_HAS_DSP"
-  "lhx\t%0,%2(%1)"
-  [(set_attr "type"    "load")
-   (set_attr "mode"    "SI")])
-
 (define_expand "mips_lwx"
   [(match_operand:SI 0 "register_operand")
    (match_operand 1 "pmode_register_operand")
@@ -1154,14 +1145,38 @@ (define_expand "mips_lwx"
   DONE;
 })
 
-(define_insn "mips_lwx_<mode>"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (mem:SI (plus:P (match_operand:P 1 "register_operand" "d")
-                       (match_operand:P 2 "register_operand" "d"))))]
-  "ISA_HAS_DSP"
-  "lwx\t%0,%2(%1)"
+(define_expand "mips_ldx"
+  [(match_operand:DI 0 "register_operand")
+   (match_operand 1 "pmode_register_operand")
+   (match_operand:SI 2 "register_operand")]
+  "ISA_HAS_DSP && TARGET_64BIT"
+{
+  operands[2] = convert_to_mode (Pmode, operands[2], false);
+  emit_insn (PMODE_INSN (gen_mips_ldx,
+                        (operands[0], operands[1], operands[2])));
+  DONE;
+})
+
+(define_insn "mips_l<GPR:size>x_<P:mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (mem:GPR (plus:P (match_operand:P 1 "register_operand" "d")
+                        (match_operand:P 2 "register_operand" "d"))))]
+  "ISA_HAS_L<GPR:SIZE>X"
+  "l<GPR:size>x\t%0,%2(%1)"
+  [(set_attr "type"    "load")
+   (set_attr "mode"    "<GPR:MODE>")
+   (set_attr "length"  "4")])
+
+(define_insn "*mips_lw<u>x_<P:mode>_ext"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+       (any_extend:DI
+         (mem:SI (plus:P (match_operand:P 1 "register_operand" "d")
+                            (match_operand:P 2 "register_operand" "d")))))]
+  "ISA_HAS_LW<U>X && TARGET_64BIT"
+  "lw<u>x\t%0,%2(%1)"
   [(set_attr "type"    "load")
-   (set_attr "mode"    "SI")])
+   (set_attr "mode"    "DI")
+   (set_attr "length"  "4")])
 
 ;; Table 2-8. MIPS DSP ASE Instructions: Branch
 ;; BPOSGE32
Index: config/mips/mips-ftypes.def
===================================================================
--- config/mips/mips-ftypes.def (revision 182342)
+++ config/mips/mips-ftypes.def (working copy)
@@ -53,6 +53,7 @@ DEF_MIPS_FTYPE (4, (INT, V2SF, V2SF, V2S
 
 DEF_MIPS_FTYPE (2, (SI, DI, SI))
 DEF_MIPS_FTYPE (2, (SI, POINTER, SI))
+DEF_MIPS_FTYPE (2, (DI, POINTER, SI))
 DEF_MIPS_FTYPE (1, (SI, SI))
 DEF_MIPS_FTYPE (2, (SI, SI, SI))
 DEF_MIPS_FTYPE (3, (SI, SI, SI, SI))
Index: config/mips/mips.md
===================================================================
--- config/mips/mips.md (revision 182342)
+++ config/mips/mips.md (working copy)
@@ -668,9 +668,10 @@ (define_mode_attr D [(SI "") (DI "D")
                     (HA "") (SA "") (DA "D")
                     (UHA "") (USA "") (UDA "D")])
 
-;; This attribute gives the length suffix for a sign- or zero-extension
-;; instruction.
-(define_mode_attr size [(QI "b") (HI "h")])
+;; This attribute gives the length suffix for a sign-, zero-extension
+;; load and store instruction.
+(define_mode_attr size [(QI "b") (HI "h") (SI "w") (DI "d")])
+(define_mode_attr SIZE [(QI "B") (HI "H") (SI "W") (DI "D")])
 
 ;; This attributes gives the mode mask of a SHORT.
 (define_mode_attr mask [(QI "0x00ff") (HI "0xffff")])
@@ -790,6 +791,9 @@ (define_code_attr u [(sign_extend "") (z
                     (lt "") (ltu "u")
                     (le "") (leu "u")])
 
+;; <U> is like <u> except uppercase.
+(define_code_attr U [(sign_extend "") (zero_extend "U")])
+
 ;; <su> is like <u>, but the signed form expands to "s" rather than "".
 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
 
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c  (revision 182342)
+++ config/mips/mips.c  (working copy)
@@ -2159,6 +2159,29 @@ mips_lwxs_address_p (rtx addr)
     }
   return false;
 }
+
+/* Return true if ADDR matches the pattern for the L{B,H,W,D}{,U}X load 
+   indexed address instruction.  Note that such addresses are
+   not considered legitimate in the TARGET_LEGITIMATE_ADDRESS_P
+   sense, because their use is so restricted.  */
+
+static bool
+mips_loadindexed_address_p (rtx addr, enum machine_mode mode)
+{
+  if (GET_CODE (addr) != PLUS
+      || !REG_P (XEXP (addr, 0))
+      || !REG_P (XEXP (addr, 1)))
+    return false;
+  if (ISA_HAS_LBX && mode == QImode)
+    return true;
+  if (ISA_HAS_LHX && mode == HImode)
+    return true;
+  if (ISA_HAS_LWX && mode == SImode)
+    return true;
+  if (ISA_HAS_LDX && mode == DImode)
+    return true;
+  return false;
+}
 
 /* Return true if a value at OFFSET bytes from base register BASE can be
    accessed using an unextended MIPS16 instruction.  MODE is the mode of
@@ -3552,6 +3575,11 @@ mips_rtx_costs (rtx x, int code, int out
          *total = COSTS_N_INSNS (2);
          return true;
        }
+      if (mips_loadindexed_address_p (addr, mode))
+       {
+         *total = COSTS_N_INSNS (2);
+         return true;
+       }
       /* Otherwise use the default handling.  */
       return false;
 
@@ -12627,6 +12655,7 @@ AVAIL_NON_MIPS16 (mips3d, TARGET_MIPS3D)
 AVAIL_NON_MIPS16 (dsp, TARGET_DSP)
 AVAIL_NON_MIPS16 (dspr2, TARGET_DSPR2)
 AVAIL_NON_MIPS16 (dsp_32, !TARGET_64BIT && TARGET_DSP)
+AVAIL_NON_MIPS16 (dsp_64, TARGET_64BIT && TARGET_DSP)
 AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2)
 AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_VECTORS)
 AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN)
@@ -12959,6 +12988,9 @@ static const struct mips_builtin_descrip
   DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dsp_32),
   DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dsp_32),
 
+  /* Built-in functions for the DSP ASE (64-bit only).  */
+  DIRECT_BUILTIN (ldx, MIPS_DI_FTYPE_POINTER_SI, dsp_64),
+
   /* The following are for the MIPS DSP ASE REV 2 (32-bit only).  */
   DIRECT_BUILTIN (dpa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
   DIRECT_BUILTIN (dps_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
Index: config/mips/mips.h
===================================================================
--- config/mips/mips.h  (revision 182342)
+++ config/mips/mips.h  (working copy)
@@ -996,6 +996,15 @@ struct mips_cpu_info {
 /* ISA has lwxs instruction (load w/scaled index address.  */
 #define ISA_HAS_LWXS           (TARGET_SMARTMIPS && !TARGET_MIPS16)
 
+/* ISA has lbx, lbux, lhx, lhx, lhux, lwx, lwux, or ldx instruction. */
+#define ISA_HAS_LBX            (TARGET_OCTEON2)
+#define ISA_HAS_LBUX           (ISA_HAS_DSP || TARGET_OCTEON2)
+#define ISA_HAS_LHX            (ISA_HAS_DSP || TARGET_OCTEON2)
+#define ISA_HAS_LHUX           (TARGET_OCTEON2)
+#define ISA_HAS_LWX            (ISA_HAS_DSP || TARGET_OCTEON2)
+#define ISA_HAS_LWUX           (TARGET_OCTEON2 && TARGET_64BIT)
+#define ISA_HAS_LDX            ((ISA_HAS_DSP || TARGET_OCTEON2) && 
TARGET_64BIT)
+
 /* The DSP ASE is available.  */
 #define ISA_HAS_DSP            (TARGET_DSP && !TARGET_MIPS16)
 

Reply via email to