OSDN Git Service

2005-10-19 Adrian Straetling <straetling@de.ibm.com>
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2005 16:37:10 +0000 (16:37 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2005 16:37:10 +0000 (16:37 +0000)
* config/s390/s390.c (s390_expand_insv): New.
* config/s390/s390-protos.h (s390_expand_insv): Declare.
* config/s390/s390.md ("UNSPEC_SETHIGH"): Rename to "UNSPEC_ICM".
("icm_hi"): Remove mode attribute.
("*sethigh<mode><mode>"): Rewrite to "sethighpart<mode>".
Adjust all uses.
("*extracthi", "*extractqi"): Remove.
(extv<mode>", "*extzv<mode>"): New.
("insv", "*insv<mode>_mem_reg", "*insvdi_mem_reghigh",
"*insv<mode>_reg_imm", "*insv<mode>_reg_extimm"): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105625 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 139c617..feb6a71 100644 (file)
@@ -1,3 +1,16 @@
+2005-10-19  Adrian Straetling  <straetling@de.ibm.com>
+
+       * config/s390/s390.c (s390_expand_insv): New.
+       * config/s390/s390-protos.h (s390_expand_insv): Declare.
+       * config/s390/s390.md ("UNSPEC_SETHIGH"): Rename to "UNSPEC_ICM".
+       ("icm_hi"): Remove mode attribute.
+       ("*sethigh<mode><mode>"): Rewrite to "sethighpart<mode>".
+       Adjust all uses.
+       ("*extracthi", "*extractqi"): Remove.
+       (extv<mode>", "*extzv<mode>"): New.
+       ("insv", "*insv<mode>_mem_reg", "*insvdi_mem_reghigh",
+       "*insv<mode>_reg_imm", "*insv<mode>_reg_extimm"): New.
+
 2005-10-19  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
        * cfgexpand.c (discover_nonconstant_array_refs_r,
index b18e1d1..3ae43ea 100644 (file)
@@ -74,6 +74,7 @@ extern void s390_expand_movmem (rtx, rtx, rtx);
 extern void s390_expand_setmem (rtx, rtx, rtx);
 extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
 extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
 extern rtx s390_return_addr_rtx (int, rtx);
 extern rtx s390_back_chain_rtx (void);
 extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
index 445f4e1..009c178 100644 (file)
@@ -3815,6 +3815,101 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
   return false;
 }
 
+/* Expand code for the insv template. Return true if successful, false else.  */
+
+bool 
+s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
+{
+  int bitsize = INTVAL (op1);
+  int bitpos = INTVAL (op2);
+
+  /* We need byte alignement.  */
+  if (bitsize % BITS_PER_UNIT)
+    return false;
+
+  if (bitpos == 0
+      && memory_operand (dest, VOIDmode)
+      && (register_operand (src, word_mode)
+         || const_int_operand (src, VOIDmode)))
+    {
+      /* Emit standard pattern if possible.  */
+      enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
+      if (GET_MODE_BITSIZE (mode) == bitsize)
+       emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
+
+      /* (set (ze (mem)) (const_int)).  */
+      else if (const_int_operand (src, VOIDmode))
+       {
+         int size = bitsize / BITS_PER_UNIT;
+         rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
+                                       GET_MODE_SIZE (word_mode) - size);
+
+         dest = adjust_address (dest, BLKmode, 0);
+         set_mem_size (dest, GEN_INT (size));
+         s390_expand_movmem (dest, src_mem, GEN_INT (size));
+       }
+         
+      /* (set (ze (mem)) (reg)).  */
+      else if (register_operand (src, word_mode))
+       {
+         if (bitsize <= GET_MODE_BITSIZE (SImode))
+           emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
+                                                 const0_rtx), src);
+         else
+           {
+             /* Emit st,stcmh sequence.  */
+             int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
+             int size = stcmh_width / BITS_PER_UNIT;
+
+             emit_move_insn (adjust_address (dest, SImode, size), 
+                             gen_lowpart (SImode, src));
+             set_mem_size (dest, GEN_INT (size));
+             emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
+                                                   (stcmh_width), const0_rtx),
+                             gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
+                                               (GET_MODE_BITSIZE (SImode))));
+           }
+       }
+      else
+       return false;
+
+      return true;
+    }
+
+  /* (set (ze (reg)) (const_int)).  */
+  if (TARGET_ZARCH
+      && register_operand (dest, word_mode) 
+      && (bitpos % 16) == 0
+      && (bitsize % 16) == 0
+      && const_int_operand (src, VOIDmode))
+    {
+      HOST_WIDE_INT val = INTVAL (src);
+      int regpos = bitpos + bitsize;
+
+      while (regpos > bitpos)
+       {
+         enum machine_mode putmode;
+         int putsize;
+
+         if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
+           putmode = SImode;
+         else
+           putmode = HImode;
+
+         putsize = GET_MODE_BITSIZE (putmode);
+         regpos -= putsize;
+         emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, 
+                                               GEN_INT (putsize),
+                                               GEN_INT (regpos)), 
+                         gen_int_mode (val, putmode));
+         val >>= putsize;
+       }
+      gcc_assert (regpos == bitpos);
+      return true;
+    }
+
+  return false;
+}
 
 /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
    We need to emit DTP-relative relocations.  */
index baea3ff..bc9e4c3 100644 (file)
   [; Miscellaneous
    (UNSPEC_ROUND               1)
    (UNSPEC_CMPINT              2)
-   (UNSPEC_SETHIGH             10)
+   (UNSPEC_ICM                 10)
 
    ; GOT/PLT and lt-relative accesses
    (UNSPEC_LTREL_OFFSET                100)
 ;; and "cfdbr" in SImode.
 (define_mode_attr gf [(DI "g") (SI "f")])
 
-;; ICM mask required to load MODE value into the highest subreg
-;; of a SImode register.
-(define_mode_attr icm_hi [(HI "12") (QI "8")])
-
 ;; ICM mask required to load MODE value into the lowest subreg
 ;; of a SImode register.
 (define_mode_attr icm_lo [(HI "3") (QI "1")])
 ;;- Conversion instructions.
 ;;
 
-
-(define_insn "*sethigh<mode>si"
+(define_insn "*sethighpartsi"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (unspec:SI [(match_operand:HQI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
+       (unspec:SI [(match_operand:BLK 1 "s_operand" "Q,S")
+                   (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "@
-   icm\t%0,<icm_hi>,%S1
-   icmy\t%0,<icm_hi>,%S1"
+   icm\t%0,%2,%S1
+   icmy\t%0,%2,%S1"
   [(set_attr "op_type" "RS,RSY")])
 
-(define_insn "*sethighqidi_64"
+(define_insn "*sethighpartdi_64"
   [(set (match_operand:DI 0 "register_operand" "=d")
-        (unspec:DI [(match_operand:QI 1 "s_operand" "QS")] UNSPEC_SETHIGH))
+       (unspec:DI [(match_operand:BLK 1 "s_operand" "QS")
+                   (match_operand 2 "const_int_operand" "n")] UNSPEC_ICM))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_64BIT"
-  "icmh\t%0,8,%S1"
+  "icmh\t%0,%2,%S1"
   [(set_attr "op_type" "RSY")])
 
-(define_insn "*sethighqidi_31"
+(define_insn "*sethighpartdi_31"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (unspec:DI [(match_operand:QI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
+       (unspec:DI [(match_operand:BLK 1 "s_operand" "Q,S")
+                   (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
    (clobber (reg:CC CC_REGNUM))]
   "!TARGET_64BIT"
   "@
-   icm\t%0,8,%S1
-   icmy\t%0,8,%S1"
+   icm\t%0,%2,%S1
+   icmy\t%0,%2,%S1"
   [(set_attr "op_type" "RS,RSY")])
 
-(define_insn_and_split "*extractqi"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
-                         (match_operand 2 "const_int_operand" "n")
-                         (const_int 0)))
+(define_insn_and_split "*extzv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
+                         (match_operand 2 "const_int_operand" "n")
+                         (const_int 0)))
    (clobber (reg:CC CC_REGNUM))]
-  "!TARGET_64BIT
-   && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
+  "INTVAL (operands[2]) > 0
+   && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
   "#"
   "&& reload_completed"
   [(parallel
-    [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
+    [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
      (clobber (reg:CC CC_REGNUM))])
-    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+   (set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
 {
-  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-  operands[1] = change_address (operands[1], QImode, 0);
+  int bitsize = INTVAL (operands[2]);
+  int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
+  int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
+
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+  set_mem_size (operands[1], GEN_INT (size));
+  operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
+  operands[3] = GEN_INT (mask);
 })
 
-(define_insn_and_split "*extracthi"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
-                         (match_operand 2 "const_int_operand" "n")
-                         (const_int 0)))
+(define_insn_and_split "*extv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
+                         (match_operand 2 "const_int_operand" "n")
+                         (const_int 0)))
    (clobber (reg:CC CC_REGNUM))]
-  "!TARGET_64BIT
-   && INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
+  "INTVAL (operands[2]) > 0
+   && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
   "#"
   "&& reload_completed"
   [(parallel
-    [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
+    [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
      (clobber (reg:CC CC_REGNUM))])
-    (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+   (parallel
+    [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
+     (clobber (reg:CC CC_REGNUM))])]
 {
-  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-  operands[1] = change_address (operands[1], HImode, 0);
+  int bitsize = INTVAL (operands[2]);
+  int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
+  int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
+
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+  set_mem_size (operands[1], GEN_INT (size));
+  operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
+  operands[3] = GEN_INT (mask);
+})
+
+;
+; insv instruction patterns
+;
+
+(define_expand "insv"
+  [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
+                     (match_operand 1 "const_int_operand" "")
+                     (match_operand 2 "const_int_operand" ""))
+       (match_operand 3 "general_operand" ""))]
+  ""
+{
+  if (s390_expand_insv (operands[0], operands[1], operands[2], operands[3]))
+    DONE;
+  FAIL;
 })
 
+(define_insn "*insv<mode>_mem_reg"
+  [(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
+                       (match_operand 1 "const_int_operand" "n,n")
+                       (const_int 0))
+       (match_operand:P 2 "register_operand" "d,d"))]
+  "INTVAL (operands[1]) > 0
+   && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+   && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+{
+    int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+
+    operands[1] = GEN_INT ((1ul << size) - 1);
+    return (which_alternative == 0) ? "stcm\t%2,%1,%S0" 
+                                   : "stcmy\t%2,%1,%S0";
+}
+  [(set_attr "op_type" "RS,RSY")])
+
+(define_insn "*insvdi_mem_reghigh"
+  [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "+QS")
+                        (match_operand 1 "const_int_operand" "n")
+                        (const_int 0))
+       (lshiftrt:DI (match_operand:DI 2 "register_operand" "d")
+                    (const_int 32)))]
+  "TARGET_64BIT
+   && INTVAL (operands[1]) > 0
+   && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+   && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+{
+    int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+
+    operands[1] = GEN_INT ((1ul << size) - 1);
+    return "stcmh\t%2,%1,%S0";
+}
+[(set_attr "op_type" "RSY")])
+
+(define_insn "*insv<mode>_reg_imm"
+  [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+                       (const_int 16)
+                       (match_operand 1 "const_int_operand" "n"))
+       (match_operand:P 2 "const_int_operand" "K"))]
+  "TARGET_ZARCH
+   && INTVAL (operands[1]) >= 0
+   && INTVAL (operands[1]) < BITS_PER_WORD
+   && INTVAL (operands[1]) % 16 == 0"
+{
+  switch (BITS_PER_WORD - INTVAL (operands[1]))
+    {
+      case 64: return "iihh\t%0,%x2"; break;
+      case 48: return "iihl\t%0,%x2"; break;
+      case 32: return "iilh\t%0,%x2"; break;
+      case 16: return "iill\t%0,%x2"; break;
+      default: gcc_unreachable();
+    }
+}
+  [(set_attr "op_type" "RI")])
+
+(define_insn "*insv<mode>_reg_extimm"
+  [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+                       (const_int 32)
+                       (match_operand 1 "const_int_operand" "n"))
+       (match_operand:P 2 "const_int_operand" "Os"))]
+  "TARGET_EXTIMM
+   && INTVAL (operands[1]) >= 0
+   && INTVAL (operands[1]) < BITS_PER_WORD
+   && INTVAL (operands[1]) % 32 == 0"
+{
+  switch (BITS_PER_WORD - INTVAL (operands[1]))
+    {
+      case 64: return "iihf\t%0,%o2"; break;
+      case 32: return "iilf\t%0,%o2"; break;
+      default: gcc_unreachable();
+    }
+}
+  [(set_attr "op_type" "RIL")])
+
 ;
 ; extendsidi2 instruction pattern(s).
 ;
   "#"
   "&& reload_completed"
   [(parallel
-    [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_SETHIGH))
+    [(set (match_dup 0) (unspec:DI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
      (clobber (reg:CC CC_REGNUM))])
    (parallel
     [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
      (clobber (reg:CC CC_REGNUM))])]
-  "")
+{
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+  set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
+})
 
 ;
 ; extend(hi|qi)si2 instruction pattern(s).
   "#"
   "&& reload_completed"
   [(parallel
-    [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
+    [(set (match_dup 0) (unspec:SI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
      (clobber (reg:CC CC_REGNUM))])
    (parallel
     [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
      (clobber (reg:CC CC_REGNUM))])]
-  "")
+{
+  operands[1] = adjust_address (operands[1], BLKmode, 0);
+  set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
+})
 
 ;
 ; extendqihi2 instruction pattern(s).