ext_ins.c: New test for testing the generation of MIPS32/64 rev 2 ext/ins instructions.
authorDavid Ung <davidu@mips.com>
Thu, 26 May 2005 17:23:35 +0000 (17:23 +0000)
committerDavid Ung <davidu@gcc.gnu.org>
Thu, 26 May 2005 17:23:35 +0000 (17:23 +0000)
* gcc.target/mips/ext_ins.c: New test for testing the generation
of MIPS32/64 rev 2 ext/ins instructions.

* config/mips/mips.c (mips_use_ins_ext_p): New helper function
that determines whether the MIPS32/64 R2 ext/ins should be used.
* config/mips/mips.h (ISA_HAS_EXT_INS): New macro.
* config/mips/mips.md (extzv): Changed predicate for operand to
nonimmediate_operand. Add code to generate insn patterns for
extzvsi and extzvdi.
(extzv<mode>): New pattern to match mips32/64 r2 ext insn.
(insv): Similarly for insertion.
(insv<mode>): Similarly.

From-SVN: r100212

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/ext_ins.c [new file with mode: 0644]

index ffd7b7f0bed912c24e50e94b5022999e2134711a..696cd17f6c5060d56785c2e2a976332e02eac855 100644 (file)
@@ -1,3 +1,15 @@
+2005-05-26  David Ung  <davidu@mips.com>
+
+       * config/mips/mips.c (mips_use_ins_ext_p): New helper function
+       that determines whether the MIPS32/64 R2 ext/ins should be used.
+       * config/mips/mips.h (ISA_HAS_EXT_INS): New macro.
+       * config/mips/mips.md (extzv): Changed predicate for operand to
+       nonimmediate_operand. Add code to generate insn patterns for
+       extzvsi and extzvdi.
+       (extzv<mode>): New pattern to match mips32/64 r2 ext insn.
+       (insv): Similarly for insertion.
+       (insv<mode>): Similarly.
+
 2005-05-26  Paolo Bonzini  <bonzini@gnu.org>
 
        * simplify-rtx.c (avoid_constant_pool_reference): Support
index 9ddcf4d72a04b756de328773d3b5edabffd8a213..76f681fb86a4cbbb105637a26581818e2ac18803 100644 (file)
@@ -4158,7 +4158,39 @@ mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos)
     }
   return true;
 }
-\f
+
+/* Return true if (zero_extract OP SIZE POSITION) can be used as the
+   source of an "ext" instruction or the destination of an "ins"
+   instruction.  OP must be a register operand and the following
+   conditions must hold:
+
+     0 <= POSITION < GET_MODE_BITSIZE (GET_MODE (op))
+     0 < SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+     0 < POSITION + SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+
+   Also reject lengths equal to a word as they are better handled
+   by the move patterns.  */
+
+bool
+mips_use_ins_ext_p (rtx op, rtx size, rtx position)
+{
+  HOST_WIDE_INT len, pos;
+
+  if (!ISA_HAS_EXT_INS
+      || !register_operand (op, VOIDmode)
+      || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
+    return false;
+
+  len = INTVAL (size);
+  pos = INTVAL (position);
+  
+  if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op)) 
+      || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op)))
+    return false;
+
+  return true;
+}
+
 /* Set up globals to generate code for the ISA or processor
    described by INFO.  */
 
index 9de422d95d11298981387e81a870f37b8459cf17..ef293bec8b6d26441d569a0c654f1eaab6f1f5b4 100644 (file)
@@ -670,6 +670,11 @@ extern const struct mips_cpu_info *mips_tune_info;
                                  && (ISA_MIPS32R2                      \
                                      ))
 
+/* ISA includes the MIPS32/64 rev 2 ext and ins instructions.  */
+#define ISA_HAS_EXT_INS         (!TARGET_MIPS16                        \
+                                 && (ISA_MIPS32R2                      \
+                                     ))
+
 /* True if the result of a load is not available to the next instruction.
    A nop will then be needed between instructions like "lw $4,..."
    and "addiu $4,$4,1".  */
index 5d58b735503f5024cd0bf6ffaee9ed310db48df4..804d50ad864a350437dcc083afb98bfc5be44f95 100644 (file)
@@ -2818,7 +2818,7 @@ beq\t%2,%.,1b\;\
 
 (define_expand "extzv"
   [(set (match_operand 0 "register_operand")
-       (zero_extract (match_operand:QI 1 "memory_operand")
+       (zero_extract (match_operand 1 "nonimmediate_operand")
                      (match_operand 2 "immediate_operand")
                      (match_operand 3 "immediate_operand")))]
   "!TARGET_MIPS16"
@@ -2827,12 +2827,33 @@ beq\t%2,%.,1b\;\
                                  INTVAL (operands[2]),
                                  INTVAL (operands[3])))
     DONE;
+  else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
+    {
+      if (GET_MODE (operands[0]) == DImode)
+        emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
+                               operands[3]));
+      else
+        emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
+                               operands[3]));
+      DONE;
+    }
   else
     FAIL;
 })
 
+(define_insn "extzv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+                         (match_operand:SI 2 "immediate_operand" "I")
+                         (match_operand:SI 3 "immediate_operand" "I")))]
+  "mips_use_ins_ext_p (operands[1], operands[2], operands[3])"
+  "<d>ext\t%0,%1,%3,%2"
+  [(set_attr "type"    "arith")
+   (set_attr "mode"    "<MODE>")])
+
+
 (define_expand "insv"
-  [(set (zero_extract (match_operand:QI 0 "memory_operand")
+  [(set (zero_extract (match_operand 0 "nonimmediate_operand")
                      (match_operand 1 "immediate_operand")
                      (match_operand 2 "immediate_operand"))
        (match_operand 3 "reg_or_0_operand"))]
@@ -2842,10 +2863,30 @@ beq\t%2,%.,1b\;\
                                   INTVAL (operands[1]),
                                   INTVAL (operands[2])))
     DONE;
-  else
-    FAIL;
+  else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2]))
+    {
+      if (GET_MODE (operands[0]) == DImode)
+        emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
+                              operands[3]));
+      else
+        emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
+                              operands[3]));
+      DONE;
+   }
+   else
+     FAIL;
 })
 
+(define_insn "insv<mode>"
+  [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
+                         (match_operand:SI 1 "immediate_operand" "I")
+                         (match_operand:SI 2 "immediate_operand" "I"))
+       (match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
+  "mips_use_ins_ext_p (operands[0], operands[1], operands[2])"
+  "<d>ins\t%0,%z3,%2,%1"
+  [(set_attr "type"    "arith")
+   (set_attr "mode"    "<MODE>")])
+
 ;; Unaligned word moves generated by the bit field patterns.
 ;;
 ;; As far as the rtl is concerned, both the left-part and right-part
index 9c7db6067b6e81be23a0b9475c9b8152249c0cd4..545b1b1658f3f39225e3f164c182ea23d95953bd 100644 (file)
@@ -1,3 +1,8 @@
+2005-05-26  David Ung  <davidu@mips.com>
+
+       * gcc.target/mips/ext_ins.c: New test for testing the generation
+       of MIPS32/64 rev 2 ext/ins instructions.
+       
 2005-05-26  Andreas Jaeger  <aj@suse.de>
 
        * treelang/compile/unsigned.tree: Use gimple instead of
diff --git a/gcc/testsuite/gcc.target/mips/ext_ins.c b/gcc/testsuite/gcc.target/mips/ext_ins.c
new file mode 100644 (file)
index 0000000..77df1d2
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-march=mips32r2" } */
+/* { dg-final { scan-assembler "ext" } } */
+/* { dg-final { scan-assembler "ins" } } */
+
+struct A 
+{
+  unsigned int i : 2;
+  unsigned int j : 3;
+  unsigned int k : 4;
+  unsigned int l : 5;
+};
+
+void func (struct A);
+
+unsigned int f1 (struct A a)
+{
+  return a.j;
+}
+
+void f2 (int i)
+{
+  struct A c;
+  c.j = i;
+  func (c);
+}