OSDN Git Service

* config/s390/s390.c (s390_dump_pool): Remove return value.
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 2004 14:06:25 +0000 (14:06 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 2004 14:06:25 +0000 (14:06 +0000)
Use gen_pool_align, gen_pool_section_start/end instead of
gen_pool_start/end_31/64.
* config/s390/s390.md (UNSPECV_POOL_START, UNSPECV_POOL_END): Remove.
(UNSPECV_POOL_SECTION, UNSPECV_POOL_ALIGN): New constants.
("pool_start_31", "pool_end_31"): Remove.
("pool_start_64", "pool_end_64"): Likewise.
("pool_align", "pool_section_start", "pool_section_end": New insns.

* config/s390/s390.c (s390_cannot_copy_insn_p): New function.
(TARGET_CANNOT_COPY_INSN_P): Define.
(s390_cannot_force_const_mem): Handle UNSPEC_INSN.
(struct constant_pool): New member 'execute'.
(s390_add_execute, s390_find_execute): New functions.
(s390_execute_label, s390_execute_target): Likewise.
(s390_dump_pool): Output in-pool execute target templates.
(s390_dump_execute): New function.
(s390_alloc_pool, s390_free_pool): Handle execute templates.
(s390_mainpool_start, s390_mainpool_finish): Likewise.
(s390_chunkify_start, s390_chunkify_finish): Likewise.
* config/s390/s390.md (UNSPEC_INSN, UNSPEC_EXECUTE): New constants.
("*execute"): New insn pattern.
("movmem_short", "*movmem_short"): Use splitters to generate
explicit execute pattern, remove embedded execute.
("clrmem_short", "*clrmem_short"): Likewise.
("cmpmem_short", "*cmpmem_short"): Likewise.

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

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 63c93ce..82a9ad6 100644 (file)
@@ -1,3 +1,32 @@
+2004-10-05  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.c (s390_dump_pool): Remove return value.
+       Use gen_pool_align, gen_pool_section_start/end instead of
+       gen_pool_start/end_31/64.
+       * config/s390/s390.md (UNSPECV_POOL_START, UNSPECV_POOL_END): Remove.
+       (UNSPECV_POOL_SECTION, UNSPECV_POOL_ALIGN): New constants.
+       ("pool_start_31", "pool_end_31"): Remove.
+       ("pool_start_64", "pool_end_64"): Likewise.
+       ("pool_align", "pool_section_start", "pool_section_end": New insns.
+
+       * config/s390/s390.c (s390_cannot_copy_insn_p): New function.
+       (TARGET_CANNOT_COPY_INSN_P): Define.
+       (s390_cannot_force_const_mem): Handle UNSPEC_INSN.
+       (struct constant_pool): New member 'execute'.
+       (s390_add_execute, s390_find_execute): New functions.
+       (s390_execute_label, s390_execute_target): Likewise.
+       (s390_dump_pool): Output in-pool execute target templates.
+       (s390_dump_execute): New function.
+       (s390_alloc_pool, s390_free_pool): Handle execute templates.
+       (s390_mainpool_start, s390_mainpool_finish): Likewise.
+       (s390_chunkify_start, s390_chunkify_finish): Likewise.
+       * config/s390/s390.md (UNSPEC_INSN, UNSPEC_EXECUTE): New constants.
+       ("*execute"): New insn pattern.
+       ("movmem_short", "*movmem_short"): Use splitters to generate
+       explicit execute pattern, remove embedded execute.
+       ("clrmem_short", "*clrmem_short"): Likewise.
+       ("cmpmem_short", "*cmpmem_short"): Likewise.
+
 2004-10-05  Daniel Berlin  <dberlin@dberlin.org>
 
        * tree-ssa.c (verify_ssa): Verify phi arguments only
index 21679c3..c1414cf 100644 (file)
@@ -70,6 +70,7 @@ static enum attr_type s390_safe_attr_type (rtx);
 static int s390_adjust_priority (rtx, int);
 static int s390_issue_rate (void);
 static int s390_first_cycle_multipass_dfa_lookahead (void);
+static bool s390_cannot_copy_insn_p (rtx);
 static bool s390_rtx_costs (rtx, int, int, int *);
 static int s390_address_cost (rtx);
 static void s390_reorg (void);
@@ -127,6 +128,8 @@ static bool s390_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
 
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P s390_cannot_copy_insn_p
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS s390_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -2123,6 +2126,11 @@ s390_cannot_force_const_mem (rtx x)
        case UNSPEC_INDNTPOFF:
          return false;
 
+       /* If the literal pool shares the code section, be put
+          execute template placeholders into the pool as well.  */
+       case UNSPEC_INSN:
+         return TARGET_CPU_ZARCH;
+
        default:
          return true;
        }
@@ -4720,6 +4728,7 @@ struct constant_pool
   bitmap insns;
 
   struct constant *constants[NR_C_MODES];
+  struct constant *execute;
   rtx label;
   int size;
 };
@@ -4738,7 +4747,12 @@ static void s390_add_pool_insn (struct constant_pool *, rtx);
 static struct constant_pool *s390_find_pool (struct constant_pool *, rtx);
 static void s390_add_constant (struct constant_pool *, rtx, enum machine_mode);
 static rtx s390_find_constant (struct constant_pool *, rtx, enum machine_mode);
-static rtx s390_dump_pool (struct constant_pool *, bool);
+static void s390_add_execute (struct constant_pool *, rtx);
+static rtx s390_find_execute (struct constant_pool *, rtx);
+static rtx s390_execute_label (rtx);
+static rtx s390_execute_target (rtx);
+static void s390_dump_pool (struct constant_pool *, bool);
+static void s390_dump_execute (struct constant_pool *);
 static struct constant_pool *s390_alloc_pool (void);
 static void s390_free_pool (struct constant_pool *);
 
@@ -4857,24 +4871,130 @@ s390_find_constant (struct constant_pool *pool, rtx val,
   return offset;
 }
 
+/* Add execute target for INSN to the constant pool POOL.  */
+
+static void
+s390_add_execute (struct constant_pool *pool, rtx insn)
+{
+  struct constant *c;
+
+  for (c = pool->execute; c != NULL; c = c->next)
+    if (INSN_UID (insn) == INSN_UID (c->value))
+      break;
+
+  if (c == NULL)
+    {
+      rtx label = s390_execute_label (insn);
+      gcc_assert (label);
+
+      c = (struct constant *) xmalloc (sizeof *c);
+      c->value = insn;
+      c->label = label == const0_rtx ? gen_label_rtx () : XEXP (label, 0);
+      c->next = pool->execute;
+      pool->execute = c;
+      pool->size += label == const0_rtx ? 6 : 0;
+    }
+}
+
+/* Find execute target for INSN in the constant pool POOL.
+   Return an RTX describing the distance from the start of
+   the pool to the location of the execute target.  */
+
+static rtx
+s390_find_execute (struct constant_pool *pool, rtx insn)
+{
+  struct constant *c;
+  rtx offset;
+
+  for (c = pool->execute; c != NULL; c = c->next)
+    if (INSN_UID (insn) == INSN_UID (c->value))
+      break;
+
+  if (c == NULL)
+    abort ();
+
+  offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
+                                gen_rtx_LABEL_REF (Pmode, pool->label));
+  offset = gen_rtx_CONST (Pmode, offset);
+  return offset;
+}
+
+/* Check whether INSN is an execute.  Return the label_ref to its
+   execute target template if so, NULL_RTX otherwise.  */
+
+static rtx
+s390_execute_label (rtx insn)
+{
+  if (GET_CODE (insn) == INSN
+      && GET_CODE (PATTERN (insn)) == PARALLEL
+      && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
+      && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
+    return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
+
+  return NULL_RTX;
+}
+
+/* For an execute INSN, extract the execute target template.  */
+
+static rtx
+s390_execute_target (rtx insn)
+{
+  rtx pattern = PATTERN (insn);
+  gcc_assert (s390_execute_label (insn));
+
+  if (XVECLEN (pattern, 0) == 2)
+    {
+      pattern = copy_rtx (XVECEXP (pattern, 0, 1));
+    }
+  else
+    {
+      rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1);
+      int i;
+
+      for (i = 0; i < XVECLEN (pattern, 0) - 1; i++)
+       RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1));
+
+      pattern = gen_rtx_PARALLEL (VOIDmode, vec);
+    }
+
+  return pattern;
+}
+
+/* Indicate that INSN cannot be duplicated.  This is the case for
+   execute insns that carry a unique label.  */
+
+static bool
+s390_cannot_copy_insn_p (rtx insn)
+{
+  rtx label = s390_execute_label (insn);
+  return label && label != const0_rtx;
+}
+
 /* Dump out the constants in POOL.  If REMOTE_LABEL is true,
    do not emit the pool base label.  */
 
-static rtx
+static void
 s390_dump_pool (struct constant_pool *pool, bool remote_label)
 {
   struct constant *c;
-  rtx insn;
+  rtx insn = pool->pool_insn;
   int i;
 
-  /* Pool start insn switches to proper section
-     and guarantees necessary alignment.  */
+  /* Switch to rodata section.  */
   if (TARGET_CPU_ZARCH)
-    insn = emit_insn_after (gen_pool_start_64 (), pool->pool_insn);
+    {
+      insn = emit_insn_after (gen_pool_section_start (), insn);
+      INSN_ADDRESSES_NEW (insn, -1);
+    }
+
+  /* Ensure minimum pool alignment.  */
+  if (TARGET_CPU_ZARCH)
+    insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
   else
-    insn = emit_insn_after (gen_pool_start_31 (), pool->pool_insn);
+    insn = emit_insn_after (gen_pool_align (GEN_INT (4)), insn);
   INSN_ADDRESSES_NEW (insn, -1);
 
+  /* Emit pool base label.  */
   if (!remote_label)
     {
       insn = emit_label_after (pool->label, insn);
@@ -4908,21 +5028,60 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
        INSN_ADDRESSES_NEW (insn, -1);
       }
 
-  /* Pool end insn switches back to previous section
-     and guarantees necessary alignment.  */
-  if (TARGET_CPU_ZARCH)
-    insn = emit_insn_after (gen_pool_end_64 (), insn);
-  else
-    insn = emit_insn_after (gen_pool_end_31 (), insn);
+  /* Ensure minimum alignment for instructions.  */
+  insn = emit_insn_after (gen_pool_align (GEN_INT (2)), insn);
   INSN_ADDRESSES_NEW (insn, -1);
 
+  /* Output in-pool execute template insns.  */
+  for (c = pool->execute; c; c = c->next)
+    {
+      if (s390_execute_label (c->value) != const0_rtx)
+       continue;
+
+      insn = emit_label_after (c->label, insn);
+      INSN_ADDRESSES_NEW (insn, -1);
+
+      insn = emit_insn_after (s390_execute_target (c->value), insn);
+      INSN_ADDRESSES_NEW (insn, -1);
+    }
+
+  /* Switch back to previous section.  */
+  if (TARGET_CPU_ZARCH)
+    {
+      insn = emit_insn_after (gen_pool_section_end (), insn);
+      INSN_ADDRESSES_NEW (insn, -1);
+    }
+
   insn = emit_barrier_after (insn);
   INSN_ADDRESSES_NEW (insn, -1);
 
   /* Remove placeholder insn.  */
   remove_insn (pool->pool_insn);
 
-  return insn;
+  /* Output out-of-pool execute template isns.  */
+  s390_dump_execute (pool);
+}
+
+/* Dump out the out-of-pool execute template insns in POOL
+   at the end of the instruction stream.  */
+
+static void
+s390_dump_execute (struct constant_pool *pool)
+{
+  struct constant *c;
+  rtx insn;
+
+  for (c = pool->execute; c; c = c->next)
+    {
+      if (s390_execute_label (c->value) == const0_rtx)
+       continue;
+
+      insn = emit_label (c->label);
+      INSN_ADDRESSES_NEW (insn, -1);
+
+      insn = emit_insn (s390_execute_target (c->value));
+      INSN_ADDRESSES_NEW (insn, -1);
+    }
 }
 
 /* Allocate new constant_pool structure.  */
@@ -4938,6 +5097,7 @@ s390_alloc_pool (void)
   for (i = 0; i < NR_C_MODES; i++)
     pool->constants[i] = NULL;
 
+  pool->execute = NULL;
   pool->label = gen_label_rtx ();
   pool->first_insn = NULL_RTX;
   pool->pool_insn = NULL_RTX;
@@ -4952,17 +5112,20 @@ s390_alloc_pool (void)
 static void
 s390_free_pool (struct constant_pool *pool)
 {
+  struct constant *c, *next;
   int i;
 
   for (i = 0; i < NR_C_MODES; i++)
+    for (c = pool->constants[i]; c; c = next)
+      {
+       next = c->next;
+       free (c);
+      }
+
+  for (c = pool->execute; c; c = next)
     {
-      struct constant *c = pool->constants[i];
-      while (c != NULL)
-       {
-         struct constant *next = c->next;
-         free (c);
-         c = next;
-       }
+      next = c->next;
+      free (c);
     }
 
   BITMAP_XFREE (pool->insns);
@@ -4992,7 +5155,11 @@ s390_mainpool_start (void)
          pool->pool_insn = insn;
        }
 
-      if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+      if (s390_execute_label (insn))
+       {
+         s390_add_execute (pool, insn);
+       }
+      else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
        {
          rtx pool_ref = NULL_RTX;
          find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -5034,6 +5201,9 @@ s390_mainpool_finish (struct constant_pool *pool)
   /* If the pool is empty, we're done.  */
   if (pool->size == 0)
     {
+      /* However, we may have out-of-pool execute templates.  */
+      s390_dump_execute (pool);
+
       /* We don't actually need a base register after all.  */
       cfun->machine->base_reg = NULL_RTX;
 
@@ -5120,8 +5290,12 @@ s390_mainpool_finish (struct constant_pool *pool)
           find_constant_pool_ref (PATTERN (insn), &pool_ref);
           if (pool_ref)
             {
-              addr = s390_find_constant (pool, get_pool_constant (pool_ref),
-                                               get_pool_mode (pool_ref));
+             if (s390_execute_label (insn))
+               addr = s390_find_execute (pool, insn);
+             else
+               addr = s390_find_constant (pool, get_pool_constant (pool_ref),
+                                                get_pool_mode (pool_ref));
+
               replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
               INSN_CODE (insn) = -1;
             }
@@ -5184,7 +5358,15 @@ s390_chunkify_start (void)
            }
        }
 
-      if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+      if (s390_execute_label (insn))
+       {
+         if (!curr_pool)
+           curr_pool = s390_start_pool (&pool_list, insn);
+
+         s390_add_execute (curr_pool, insn);
+         s390_add_pool_insn (curr_pool, insn);
+       }
+      else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
        {
          rtx pool_ref = NULL_RTX;
          find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -5439,8 +5621,13 @@ s390_chunkify_finish (struct constant_pool *pool_list)
           find_constant_pool_ref (PATTERN (insn), &pool_ref);
           if (pool_ref)
             {
-              addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
-                                                    get_pool_mode (pool_ref));
+             if (s390_execute_label (insn))
+               addr = s390_find_execute (curr_pool, insn);
+             else
+               addr = s390_find_constant (curr_pool,
+                                          get_pool_constant (pool_ref),
+                                          get_pool_mode (pool_ref));
+
               replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
               INSN_CODE (insn) = -1;
             }
index a2408d7..5a64993 100644 (file)
@@ -94,6 +94,8 @@
    (UNSPEC_RELOAD_BASE         210)
    (UNSPEC_MAIN_BASE           211)
    (UNSPEC_LTREF               212)
+   (UNSPEC_INSN                        213)
+   (UNSPEC_EXECUTE             214)
 
    ; TLS relocation specifiers
    (UNSPEC_TLSGD               500)
 
    ; Literal pool
    (UNSPECV_POOL               200)
-   (UNSPECV_POOL_START         201)
-   (UNSPECV_POOL_END           202)
+   (UNSPECV_POOL_SECTION       201)
+   (UNSPECV_POOL_ALIGN         202)
    (UNSPECV_POOL_ENTRY         203)
    (UNSPECV_MAIN_POOL          300)
 
 ;; String instructions.
 ;;
 
+(define_insn "*execute"
+  [(match_parallel 0 ""
+    [(unspec [(match_operand 1 "register_operand" "a")
+              (match_operand:BLK 2 "memory_operand" "R")
+              (match_operand 3 "" "")] UNSPEC_EXECUTE)])]
+  "GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
+   && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
+  "ex\t%1,%2"
+  [(set_attr "op_type" "RX")])
+
+
 ;
 ; strlenM instruction pattern(s).
 ;
     [(set (match_operand:BLK 0 "memory_operand" "")
           (match_operand:BLK 1 "memory_operand" ""))
      (use (match_operand 2 "nonmemory_operand" ""))
+     (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
      (clobber (match_dup 3))])]
   ""
   "operands[3] = gen_rtx_SCRATCH (Pmode);")
 
 (define_insn "*movmem_short"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
-        (match_operand:BLK 1 "memory_operand" "Q,Q"))
-   (use (match_operand 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch 3 "=X,&a"))]
+  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+        (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))
+   (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+   (use (match_operand 3 "immediate_operand" "X,R,X"))
+   (clobber (match_scratch 4 "=X,X,&a"))]
   "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
-   && GET_MODE (operands[3]) == Pmode"
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return "mvc\t%O0(%b2+1,%R0),%1";
+   && GET_MODE (operands[4]) == Pmode"
+  "#"
+  [(set_attr "op_type" "SS,RX,RX")
+   (set_attr "type"    "cs")])
 
-      case 1:
-       output_asm_insn ("bras\t%3,.+10", operands);
-       output_asm_insn ("mvc\t%O0(1,%R0),%1", operands);
-       return "ex\t%2,0(%3)";
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (match_operand:BLK 1 "memory_operand" ""))
+   (use (match_operand 2 "const_int_operand" ""))
+   (use (match_operand 3 "immediate_operand" ""))
+   (clobber (scratch))]
+  "reload_completed"
+  [(parallel
+    [(set (match_dup 0) (match_dup 1))
+     (use (match_dup 2))])]
+  "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
 
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (match_operand:BLK 1 "memory_operand" ""))
+   (use (match_operand 2 "register_operand" ""))
+   (use (match_operand 3 "memory_operand" ""))
+   (clobber (scratch))]
+  "reload_completed"
+  [(parallel
+    [(unspec [(match_dup 2) (match_dup 3)
+              (const_int 0)] UNSPEC_EXECUTE)
+     (set (match_dup 0) (match_dup 1))
+     (use (const_int 1))])]
+  "")
+
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (match_operand:BLK 1 "memory_operand" ""))
+   (use (match_operand 2 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (match_operand 3 "register_operand" ""))]
+  "reload_completed && TARGET_CPU_ZARCH"
+  [(set (match_dup 3) (label_ref (match_dup 4)))
+   (parallel
+    [(unspec [(match_dup 2) (mem:BLK (match_dup 3)) 
+              (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+     (set (match_dup 0) (match_dup 1))
+     (use (const_int 1))])]
+  "operands[4] = gen_label_rtx ();")
+
+(define_insn "*mvc"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (match_operand:BLK 1 "memory_operand" "Q"))
+   (use (match_operand 2 "const_int_operand" "n"))]
+  ""
+  "mvc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
 
 ; Move a block of arbitrary length.
 
     [(set (match_operand:BLK 0 "memory_operand" "")
           (const_int 0))
      (use (match_operand 1 "nonmemory_operand" ""))
+     (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
      (clobber (match_dup 2))
      (clobber (reg:CC 33))])]
   ""
   "operands[2] = gen_rtx_SCRATCH (Pmode);")
 
 (define_insn "*clrmem_short"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
         (const_int 0))
-   (use (match_operand 1 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch 2 "=X,&a"))
+   (use (match_operand 1 "nonmemory_operand" "n,a,a"))
+   (use (match_operand 2 "immediate_operand" "X,R,X"))
+   (clobber (match_scratch 3 "=X,X,&a"))
    (clobber (reg:CC 33))]
   "(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
-   && GET_MODE (operands[2]) == Pmode"
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return "xc\t%O0(%b1+1,%R0),%0";
+   && GET_MODE (operands[3]) == Pmode"
+  "#"
+  [(set_attr "op_type" "SS,RX,RX")
+   (set_attr "type"    "cs")])
 
-      case 1:
-       output_asm_insn ("bras\t%2,.+10", operands);
-       output_asm_insn ("xc\t%O0(1,%R0),%0", operands);
-       return "ex\t%1,0(%2)";
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (const_int 0))
+   (use (match_operand 1 "const_int_operand" ""))
+   (use (match_operand 2 "immediate_operand" ""))
+   (clobber (scratch))
+   (clobber (reg:CC 33))]
+  "reload_completed"
+  [(parallel
+    [(set (match_dup 0) (const_int 0))
+     (use (match_dup 1))
+     (clobber (reg:CC 33))])]
+  "operands[1] = GEN_INT ((INTVAL (operands[1]) & 0xff) + 1);")
 
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (const_int 0))
+   (use (match_operand 1 "register_operand" ""))
+   (use (match_operand 2 "memory_operand" ""))
+   (clobber (scratch))
+   (clobber (reg:CC 33))]
+  "reload_completed"
+  [(parallel
+    [(unspec [(match_dup 1) (match_dup 2)
+              (const_int 0)] UNSPEC_EXECUTE)
+     (set (match_dup 0) (const_int 0))
+     (use (const_int 1))
+     (clobber (reg:CC 33))])]
+  "")
+
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (const_int 0))
+   (use (match_operand 1 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (match_operand 2 "register_operand" ""))
+   (clobber (reg:CC 33))]
+  "reload_completed && TARGET_CPU_ZARCH"
+  [(set (match_dup 2) (label_ref (match_dup 3)))
+   (parallel
+    [(unspec [(match_dup 1) (mem:BLK (match_dup 2)) 
+              (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+     (set (match_dup 0) (const_int 0))
+     (use (const_int 1))
+     (clobber (reg:CC 33))])]
+  "operands[3] = gen_label_rtx ();")
+
+(define_insn "*xc_zero"
+  [(set (match_operand:BLK 0 "memory_operand" "=Q")
+        (const_int 0))
+   (use (match_operand 1 "const_int_operand" "n"))
+   (clobber (reg:CC 33))]
+  ""
+  "xc\t%O0(%1,%R0),%0"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
 
 ; Clear a block of arbitrary length.
 
           (compare:CCU (match_operand:BLK 0 "memory_operand" "")
                        (match_operand:BLK 1 "memory_operand" "")))
      (use (match_operand 2 "nonmemory_operand" ""))
+     (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
      (clobber (match_dup 3))])]
   ""
   "operands[3] = gen_rtx_SCRATCH (Pmode);")
 
 (define_insn "*cmpmem_short"
   [(set (reg:CCU 33)
-        (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q,Q")
-                     (match_operand:BLK 1 "memory_operand" "Q,Q")))
-   (use (match_operand 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch 3 "=X,&a"))]
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+                     (match_operand:BLK 1 "memory_operand" "Q,Q,Q")))
+   (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+   (use (match_operand 3 "immediate_operand" "X,R,X"))
+   (clobber (match_scratch 4 "=X,X,&a"))]
   "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
-   && GET_MODE (operands[3]) == Pmode"
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return "clc\t%O0(%b2+1,%R0),%1";
+   && GET_MODE (operands[4]) == Pmode"
+  "#"
+  [(set_attr "op_type" "SS,RX,RX")
+   (set_attr "type"    "cs")])
 
-      case 1:
-       output_asm_insn ("bras\t%3,.+10", operands);
-       output_asm_insn ("clc\t%O0(1,%R0),%1", operands);
-       return "ex\t%2,0(%3)";
+(define_split
+  [(set (reg:CCU 33)
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+                     (match_operand:BLK 1 "memory_operand" "")))
+   (use (match_operand 2 "const_int_operand" ""))
+   (use (match_operand 3 "immediate_operand" ""))
+   (clobber (scratch))]
+  "reload_completed"
+  [(parallel
+    [(set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+     (use (match_dup 2))])]
+  "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
 
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+(define_split
+  [(set (reg:CCU 33)
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+                     (match_operand:BLK 1 "memory_operand" "")))
+   (use (match_operand 2 "register_operand" ""))
+   (use (match_operand 3 "memory_operand" ""))
+   (clobber (scratch))]
+  "reload_completed"
+  [(parallel
+    [(unspec [(match_dup 2) (match_dup 3)
+              (const_int 0)] UNSPEC_EXECUTE)
+     (set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+     (use (const_int 1))])]
+  "")
+
+(define_split
+  [(set (reg:CCU 33)
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+                     (match_operand:BLK 1 "memory_operand" "")))
+   (use (match_operand 2 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (match_operand 3 "register_operand" ""))]
+  "reload_completed && TARGET_CPU_ZARCH"
+  [(set (match_dup 3) (label_ref (match_dup 4)))
+   (parallel
+    [(unspec [(match_dup 2) (mem:BLK (match_dup 3)) 
+              (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+     (set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+     (use (const_int 1))])]
+  "operands[4] = gen_label_rtx ();")
+
+(define_insn "*clc"
+  [(set (reg:CCU 33)
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q")
+                     (match_operand:BLK 1 "memory_operand" "Q")))
+   (use (match_operand 2 "const_int_operand" "n"))]
+  ""
+  "clc\t%O0(%2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "type"    "cs")])
 
 ; Compare a block of arbitrary length.
 
    (set (attr "length")
         (symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
 
-(define_insn "pool_start_31"
-  [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
-  "!TARGET_CPU_ZARCH"
-  ".align\t4"
-  [(set_attr "op_type"  "NN")
-   (set_attr "length"   "2")])
-
-(define_insn "pool_end_31"
-  [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
-  "!TARGET_CPU_ZARCH"
-  ".align\t2"
-  [(set_attr "op_type"  "NN")
-   (set_attr "length"   "2")])
+(define_insn "pool_align"
+  [(unspec_volatile [(match_operand 0 "const_int_operand" "n")]
+                    UNSPECV_POOL_ALIGN)]
+  ""
+  ".align\t%0"
+  [(set_attr "op_type" "NN")
+   (set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
 
-(define_insn "pool_start_64"
-  [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
-  "TARGET_CPU_ZARCH"
-  ".section\t.rodata\;.align\t8"
-  [(set_attr "op_type"  "NN")
-   (set_attr "length"   "0")])
+(define_insn "pool_section_start"
+  [(unspec_volatile [(const_int 1)] UNSPECV_POOL_SECTION)]
+  ""
+  ".section\t.rodata"
+  [(set_attr "op_type" "NN")
+   (set_attr "length"  "0")])
 
-(define_insn "pool_end_64"
-  [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
-  "TARGET_CPU_ZARCH"
+(define_insn "pool_section_end"
+  [(unspec_volatile [(const_int 0)] UNSPECV_POOL_SECTION)]
+  ""
   ".previous"
-  [(set_attr "op_type"  "NN")
-   (set_attr "length"   "0")])
+  [(set_attr "op_type" "NN")
+   (set_attr "length"  "0")])
 
 (define_insn "main_base_31_small"
   [(set (match_operand 0 "register_operand" "=a")