2003-11-30 Andreas Krebbel <krebbel1@de.ibm.com>
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Nov 2003 15:51:36 +0000 (15:51 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Nov 2003 15:51:36 +0000 (15:51 +0000)
* config/s390/s390.md ("tmdi_reg", "tmsi_reg", "*movdi_64", "*movdi_31",
"iordi3"): Insns now use multiple letter constraints.
("*movdi_lhi", "*movdi_lli", "*movdi_lay"): Insns deleted. They are now
covered by "*movdi_64".
("*movsi_lhi", "*movsi_lli", "*movsi_lay"): Insns deleted. They are now
covered by "*movsi_zarch" and "*movsi_esa".
("*movsi_zarch", "*movsi_!zarch"): New insns.
("*llgt_sisi_split", "*llgt_didi_split"): Insns deleted. Now covered
by "*andsi3_zarch" and "anddi3".
("*anddi3_ni"): Insn merged with "anddi3".
("*andsi3_ni"): Insn merged with "*andsi3_zarch".
("*andsi3_zarch", "*andsi3_esa"): New insns.
("*iordi3_oi"): Insn merged with "iordi3".
("*iorsi3_oi"): Insn merged with "*iorsi3_zarch".
("*iorsi3_zarch", "*iorsi3_esa"): New insns.

* config/s390/s390.c (s390_single_qi, s390_single_hi): Functions
merged to s390_single_part.
(s390_single_part): New function.
NOTE: Semantics have changed a bit. Now the value of the part must
be different from the others to get a non-negative return value.
(s390_extract_qi, s390_extract_hi): Functions merged to
s390_extract_part.
(s390_extract_part, s390_extra_constraint_str,
s390_const_ok_for_constraint_p): New functions. The L constraint got a
new meaning and the N constraint was added as a multiple letter
constraint.
(s390_extra_constraint): Function deleted.
(print_operand): New output modifier 'i' and 'j' added.
All uses of CONST_OK_FOR_LETTER_P were replaced by
CONST_OK_FOR_CONSTRAINT_P.

* config/s390/s390-protos.h: Function prototypes adapted.
* doc/md.texi: Documentation for new constraint letters added.

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

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

index 9a7c5be..2b9a4a9 100644 (file)
@@ -1,3 +1,40 @@
+2003-11-30  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * config/s390/s390.md ("tmdi_reg", "tmsi_reg", "*movdi_64", "*movdi_31", 
+       "iordi3"): Insns now use multiple letter constraints.
+       ("*movdi_lhi", "*movdi_lli", "*movdi_lay"): Insns deleted. They are now
+       covered by "*movdi_64".
+       ("*movsi_lhi", "*movsi_lli", "*movsi_lay"): Insns deleted. They are now
+       covered by "*movsi_zarch" and "*movsi_esa".
+       ("*movsi_zarch", "*movsi_!zarch"): New insns.
+       ("*llgt_sisi_split", "*llgt_didi_split"): Insns deleted. Now covered 
+       by "*andsi3_zarch" and "anddi3".
+       ("*anddi3_ni"): Insn merged with "anddi3".
+       ("*andsi3_ni"): Insn merged with "*andsi3_zarch".
+       ("*andsi3_zarch", "*andsi3_esa"): New insns.
+       ("*iordi3_oi"): Insn merged with "iordi3".
+       ("*iorsi3_oi"): Insn merged with "*iorsi3_zarch".
+       ("*iorsi3_zarch", "*iorsi3_esa"): New insns.
+
+       * config/s390/s390.c (s390_single_qi, s390_single_hi): Functions 
+       merged to s390_single_part.
+       (s390_single_part): New function.
+       NOTE: Semantics have changed a bit. Now the value of the part must
+       be different from the others to get a non-negative return value.
+       (s390_extract_qi, s390_extract_hi): Functions merged to 
+       s390_extract_part.
+       (s390_extract_part, s390_extra_constraint_str,
+       s390_const_ok_for_constraint_p): New functions. The L constraint got a 
+       new meaning and the N constraint was added as a multiple letter 
+       constraint.
+       (s390_extra_constraint): Function deleted.
+       (print_operand): New output modifier 'i' and 'j' added.
+       All uses of CONST_OK_FOR_LETTER_P were replaced by 
+       CONST_OK_FOR_CONSTRAINT_P.
+
+       * config/s390/s390-protos.h: Function prototypes adapted.
+       * doc/md.texi: Documentation for new constraint letters added.
+
 2003-11-30  Andreas Schwab  <schwab@suse.de>
 
        * Makefile.in ($(DESTDIR)$(infodir)/%.info): Fix missing semicolon.
index 1ab6b09..c45ff4d 100644 (file)
@@ -30,7 +30,8 @@ extern void s390_emit_epilogue (void);
 extern void s390_function_profiler (FILE *, int);
 
 #ifdef RTX_CODE
-extern int s390_extra_constraint (rtx, int);
+extern int s390_extra_constraint_str (rtx, int, const char *);
+extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
 extern int const0_operand (rtx, enum machine_mode);
 extern int consttable_operand (rtx, enum machine_mode);
 extern int larl_operand (rtx, enum machine_mode);
@@ -40,10 +41,8 @@ extern int shift_count_operand (rtx, enum machine_mode);
 extern int bras_sym_operand (rtx, enum machine_mode);
 extern int load_multiple_operation (rtx, enum machine_mode);
 extern int store_multiple_operation (rtx, enum machine_mode);
-extern int s390_single_hi (rtx, enum machine_mode, int);
-extern int s390_extract_hi (rtx, enum machine_mode, int);
-extern int s390_single_qi (rtx, enum machine_mode, int);
-extern int s390_extract_qi (rtx, enum machine_mode, int);
+extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
+extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
 extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
 extern int tls_symbolic_operand (rtx);
 
index c83316b..ef9c213 100644 (file)
@@ -374,7 +374,7 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
       case EQ:
       case NE:
        if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
-           && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K'))
+           && CONST_OK_FOR_CONSTRAINT_P (INTVAL (XEXP (op0, 1)), 'K', "K"))
          return CCAPmode;
        if ((GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
             || GET_CODE (op1) == NEG)
@@ -410,7 +410,7 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
       case GE:
       case GT:
          if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K'))
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (XEXP (op0, 1)), 'K', "K"))
             {
              if (INTVAL (XEXP((op0), 1)) < 0)
                return CCANmode;
@@ -760,198 +760,68 @@ s390_branch_condition_mnemonic (rtx code, int inv)
   return mnemonic[mask];
 }
 
-/* If OP is an integer constant of mode MODE with exactly one
-   HImode subpart unequal to DEF, return the number of that
-   subpart.  As a special case, all HImode subparts of OP are
-   equal to DEF, return zero.  Otherwise, return -1.  */
+/* Return the part of op which has a value different from def.
+   The size of the part is determined by mode.
+   Use this function only if you already know that op really 
+   contains such a part.  */
 
-int
-s390_single_hi (rtx op, enum machine_mode mode, int def)
+unsigned HOST_WIDE_INT
+s390_extract_part (rtx op, enum machine_mode mode, int def)
 {
-  if (GET_CODE (op) == CONST_INT)
-    {
-      unsigned HOST_WIDE_INT value = 0;
-      int n_parts = GET_MODE_SIZE (mode) / 2;
-      int i, part = -1;
-
-      for (i = 0; i < n_parts; i++)
-        {
-          if (i == 0)
-            value = (unsigned HOST_WIDE_INT) INTVAL (op);
-          else
-            value >>= 16;
-
-          if ((value & 0xffff) != (unsigned)(def & 0xffff))
-            {
-              if (part != -1)
-                return -1;
-              else
-                part = i;
-            }
-        }
-
-      return part == -1 ? 0 : (n_parts - 1 - part);
-    }
-
-  else if (GET_CODE (op) == CONST_DOUBLE
-           && GET_MODE (op) == VOIDmode)
-    {
-      unsigned HOST_WIDE_INT value = 0;
-      int n_parts = GET_MODE_SIZE (mode) / 2;
-      int i, part = -1;
-
-      for (i = 0; i < n_parts; i++)
-        {
-          if (i == 0)
-            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
-          else if (i == HOST_BITS_PER_WIDE_INT / 16)
-            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
-          else
-            value >>= 16;
-
-          if ((value & 0xffff) != (unsigned)(def & 0xffff))
-            {
-              if (part != -1)
-                return -1;
-              else
-                part = i;
-            }
-        }
-
-      return part == -1 ? 0 : (n_parts - 1 - part);
-    }
-
-  return -1;
-}
-
-/* Extract the HImode part number PART from integer
-   constant OP of mode MODE.  */
-
-int
-s390_extract_hi (rtx op, enum machine_mode mode, int part)
-{
-  int n_parts = GET_MODE_SIZE (mode) / 2;
-  if (part < 0 || part >= n_parts)
-    abort();
-  else
-    part = n_parts - 1 - part;
-
-  if (GET_CODE (op) == CONST_INT)
-    {
-      unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
-      return ((value >> (16 * part)) & 0xffff);
-    }
-  else if (GET_CODE (op) == CONST_DOUBLE
-           && GET_MODE (op) == VOIDmode)
+  unsigned HOST_WIDE_INT value = 0;
+  int max_parts = HOST_BITS_PER_WIDE_INT / GET_MODE_BITSIZE (mode);
+  int part_bits = GET_MODE_BITSIZE (mode);
+  unsigned HOST_WIDE_INT part_mask = (1 << part_bits) - 1;
+  int i;
+  
+  for (i = 0; i < max_parts; i++)
     {
-      unsigned HOST_WIDE_INT value;
-      if (part < HOST_BITS_PER_WIDE_INT / 16)
-        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+      if (i == 0)
+       value = (unsigned HOST_WIDE_INT) INTVAL (op);
       else
-        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
-        part -= HOST_BITS_PER_WIDE_INT / 16;
-
-      return ((value >> (16 * part)) & 0xffff);
+       value >>= part_bits;
+      
+      if ((value & part_mask) != (def & part_mask))
+       return value & part_mask;
     }
-
+  
   abort ();
 }
 
 /* If OP is an integer constant of mode MODE with exactly one
-   QImode subpart unequal to DEF, return the number of that
-   subpart.  As a special case, all QImode subparts of OP are
-   equal to DEF, return zero.  Otherwise, return -1.  */
+   part of mode PART_MODE unequal to DEF, return the number of that
+   part. Otherwise, return -1.  */
 
 int
-s390_single_qi (rtx op, enum machine_mode mode, int def)
-{
-  if (GET_CODE (op) == CONST_INT)
-    {
-      unsigned HOST_WIDE_INT value = 0;
-      int n_parts = GET_MODE_SIZE (mode);
-      int i, part = -1;
-
-      for (i = 0; i < n_parts; i++)
-        {
-          if (i == 0)
-            value = (unsigned HOST_WIDE_INT) INTVAL (op);
-          else
-            value >>= 8;
-
-          if ((value & 0xff) != (unsigned)(def & 0xff))
-            {
-              if (part != -1)
-                return -1;
-              else
-                part = i;
-            }
-        }
-
-      return part == -1 ? 0 : (n_parts - 1 - part);
-    }
-
-  else if (GET_CODE (op) == CONST_DOUBLE
-           && GET_MODE (op) == VOIDmode)
-    {
-      unsigned HOST_WIDE_INT value = 0;
-      int n_parts = GET_MODE_SIZE (mode);
-      int i, part = -1;
-
-      for (i = 0; i < n_parts; i++)
-        {
-          if (i == 0)
-            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
-          else if (i == HOST_BITS_PER_WIDE_INT / 8)
-            value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
-          else
-            value >>= 8;
-
-          if ((value & 0xff) != (unsigned)(def & 0xff))
-            {
-              if (part != -1)
-                return -1;
-              else
-                part = i;
-            }
-        }
-
-      return part == -1 ? 0 : (n_parts - 1 - part);
-    }
-
-  return -1;
-}
-
-/* Extract the QImode part number PART from integer
-   constant OP of mode MODE.  */
-
-int
-s390_extract_qi (rtx op, enum machine_mode mode, int part)
-{
-  int n_parts = GET_MODE_SIZE (mode);
-  if (part < 0 || part >= n_parts)
-    abort();
-  else
-    part = n_parts - 1 - part;
-
-  if (GET_CODE (op) == CONST_INT)
-    {
-      unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
-      return ((value >> (8 * part)) & 0xff);
-    }
-  else if (GET_CODE (op) == CONST_DOUBLE
-           && GET_MODE (op) == VOIDmode)
-    {
-      unsigned HOST_WIDE_INT value;
-      if (part < HOST_BITS_PER_WIDE_INT / 8)
-        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+s390_single_part (rtx op, 
+                 enum machine_mode mode, 
+                 enum machine_mode part_mode,
+                 int def)
+{
+  unsigned HOST_WIDE_INT value = 0;
+  int n_parts = GET_MODE_SIZE (mode) / GET_MODE_SIZE (part_mode);
+  unsigned HOST_WIDE_INT part_mask = (1 << GET_MODE_BITSIZE (part_mode)) - 1;
+  int i, part = -1;
+
+  if (GET_CODE (op) != CONST_INT)
+    return -1;
+  
+  for (i = 0; i < n_parts; i++)
+    {
+      if (i == 0)
+       value = (unsigned HOST_WIDE_INT) INTVAL (op);
       else
-        value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
-        part -= HOST_BITS_PER_WIDE_INT / 8;
-
-      return ((value >> (8 * part)) & 0xff);
+       value >>= GET_MODE_BITSIZE (part_mode);
+      
+      if ((value & part_mask) != (def & part_mask))
+       {
+         if (part != -1)
+           return -1;
+         else
+           part = i;
+       }
     }
-
-  abort ();
+  return part == -1 ? -1 : n_parts - 1 - part;
 }
 
 /* Check whether we can (and want to) split a double-word
@@ -1353,10 +1223,13 @@ s390_short_displacement (rtx disp)
 /* Return true if OP is a valid operand for a C constraint.  */
 
 int
-s390_extra_constraint (rtx op, int c)
+s390_extra_constraint_str (rtx op, int c, const char * str)
 {
   struct s390_address addr;
 
+  if (c != str[0])
+    abort ();
+
   switch (c)
     {
     case 'Q':
@@ -1442,6 +1315,78 @@ s390_extra_constraint (rtx op, int c)
   return 1;
 }
 
+/* Return true if VALUE matches the constraint STR.  */
+
+int
+s390_const_ok_for_constraint_p (HOST_WIDE_INT value,
+                               int c,
+                               const char * str)
+{
+  enum machine_mode mode, part_mode;
+  int def;
+  unsigned char part;
+
+  if (c != str[0])
+    abort ();
+
+  switch (str[0])
+    {
+    case 'I':
+      return (unsigned int)value < 256;
+
+    case 'J':
+      return (unsigned int)value < 4096;
+
+    case 'K':
+      return value >= -32768 && value < 32768;
+
+    case 'L':
+      return (TARGET_LONG_DISPLACEMENT ? 
+             (value >= -524288 && value <= 524287) 
+             : (value >= 0 && value <= 4095));
+    case 'M':
+      return value == 2147483647;
+
+    case 'N':
+      part = str[1] - '0';
+
+      switch (str[2])
+       {
+       case 'H': part_mode = HImode; break;
+       case 'Q': part_mode = QImode; break;
+       default:  return 0;
+       }
+      
+      switch (str[3])
+       {
+       case 'H': mode = HImode; break;
+       case 'S': mode = SImode; break;
+       case 'D': mode = DImode; break;
+       default: return 0;
+       }
+
+      switch (str[4])
+       {
+       case '0': def = 0;  break;
+       case 'F': def = -1; break;
+       default: return 0;
+       }
+
+      if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode))
+       return 0;
+
+      if (s390_single_part (GEN_INT (value), mode, part_mode, def) != part)
+       return 0;
+
+      break;
+
+    default:
+      return 0;
+    }
+
+  return 1;
+}
+
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
@@ -1866,12 +1811,12 @@ legitimate_reload_constant_p (register rtx op)
 
   /* Accept l(g)hi operands.  */
   if (GET_CODE (op) == CONST_INT
-      && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
+      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', "K"))
     return 1;
 
   /* Accept lliXX operands.  */
   if (TARGET_ZARCH
-      && s390_single_hi (op, DImode, 0) >= 0)
+      && s390_single_part (op, DImode, HImode, 0) >= 0)
   return 1;
 
   /* Accept larl operands.  */
@@ -3493,7 +3438,9 @@ print_operand_address (FILE *file, rtx addr)
 
     'b': print integer X as if it's an unsigned byte.
     'x': print integer X as if it's an unsigned word.
-    'h': print integer X as if it's a signed word.  */
+    'h': print integer X as if it's a signed word.
+    'i': print the first nonzero HImode part of X.
+    'j': print the first HImode part unequal to 0xffff of X.  */
 
 void
 print_operand (FILE *file, rtx x, int code)
@@ -3609,6 +3556,12 @@ print_operand (FILE *file, rtx x, int code)
         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
       else if (code == 'h')
         fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
+      else if (code == 'i')
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, 
+                s390_extract_part (x, HImode, 0));
+      else if (code == 'j')
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, 
+                s390_extract_part (x, HImode, -1));    
       else
         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
       break;
@@ -5694,7 +5647,7 @@ s390_emit_prologue (void)
        }
       else
        {
-         if (!CONST_OK_FOR_LETTER_P (INTVAL (frame_off), 'K'))
+         if (!CONST_OK_FOR_CONSTRAINT_P (INTVAL (frame_off), 'K', "K"))
            frame_off = force_const_mem (Pmode, frame_off);
 
           insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
@@ -5889,7 +5842,7 @@ s390_emit_epilogue (void)
        }
       else
        {
-         if (!CONST_OK_FOR_LETTER_P (INTVAL (frame_off), 'K'))
+         if (!CONST_OK_FOR_CONSTRAINT_P (INTVAL (frame_off), 'K', "K"))
            frame_off = force_const_mem (Pmode, frame_off);
 
          insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
@@ -6898,9 +6851,9 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
     {
       /* Setup literal pool pointer if required.  */
       if ((!DISP_IN_RANGE (delta)
-          && !CONST_OK_FOR_LETTER_P (delta, 'K'))
+          && !CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
          || (!DISP_IN_RANGE (vcall_offset)
-             && !CONST_OK_FOR_LETTER_P (vcall_offset, 'K')))
+             && !CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K")))
        {
          op[5] = gen_label_rtx ();
          output_asm_insn ("larl\t%4,%5", op);
@@ -6909,11 +6862,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
       /* Add DELTA to this pointer.  */
       if (delta)
        {
-         if (CONST_OK_FOR_LETTER_P (delta, 'J'))
+         if (CONST_OK_FOR_CONSTRAINT_P (delta, 'J', "J"))
            output_asm_insn ("la\t%1,%2(%1)", op);
          else if (DISP_IN_RANGE (delta))
            output_asm_insn ("lay\t%1,%2(%1)", op);
-         else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
+         else if (CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
            output_asm_insn ("aghi\t%1,%2", op);
          else
            {
@@ -6930,7 +6883,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
              output_asm_insn ("lg\t%4,0(%1)", op);
              output_asm_insn ("ag\t%1,%3(%4)", op);
            }
-         else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+         else if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K"))
            {
              output_asm_insn ("lghi\t%4,%3", op);
              output_asm_insn ("ag\t%4,0(%1)", op);
@@ -6973,9 +6926,9 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
       /* Setup base pointer if required.  */
       if (!vcall_offset
          || (!DISP_IN_RANGE (delta)
-              && !CONST_OK_FOR_LETTER_P (delta, 'K'))
+              && !CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
          || (!DISP_IN_RANGE (delta)
-              && !CONST_OK_FOR_LETTER_P (vcall_offset, 'K')))
+              && !CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K")))
        {
          op[5] = gen_label_rtx ();
          output_asm_insn ("basr\t%4,0", op);
@@ -6986,11 +6939,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
       /* Add DELTA to this pointer.  */
       if (delta)
        {
-         if (CONST_OK_FOR_LETTER_P (delta, 'J'))
+         if (CONST_OK_FOR_CONSTRAINT_P (delta, 'J', "J"))
            output_asm_insn ("la\t%1,%2(%1)", op);
          else if (DISP_IN_RANGE (delta))
            output_asm_insn ("lay\t%1,%2(%1)", op);
-         else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
+         else if (CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
            output_asm_insn ("ahi\t%1,%2", op);
          else
            {
@@ -7002,7 +6955,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
       /* Perform vcall adjustment.  */
       if (vcall_offset)
         {
-         if (CONST_OK_FOR_LETTER_P (vcall_offset, 'J'))
+         if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'J', "J"))
            {
              output_asm_insn ("lg\t%4,0(%1)", op);
              output_asm_insn ("a\t%1,%3(%4)", op);
@@ -7012,7 +6965,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
              output_asm_insn ("lg\t%4,0(%1)", op);
              output_asm_insn ("ay\t%1,%3(%4)", op);
            }
-         else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+         else if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K"))
            {
              output_asm_insn ("lhi\t%4,%3", op);
              output_asm_insn ("a\t%4,0(%1)", op);
index e3eaf91..cbe02d6 100644 (file)
@@ -536,21 +536,20 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
    (C) == 'd' ? GENERAL_REGS :                                          \
    (C) == 'f' ? FP_REGS : NO_REGS)
 
-#define CONST_OK_FOR_LETTER_P(VALUE, C)                                 \
-  ((C) == 'I' ? (unsigned long) (VALUE) < 256 :                         \
-   (C) == 'J' ? (unsigned long) (VALUE) < 4096 :                        \
-   (C) == 'K' ? (VALUE) >= -32768 && (VALUE) < 32768 :                  \
-   (C) == 'L' ? (unsigned long) (VALUE) < 65536 : 0)
+#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR)                          \
+  s390_const_ok_for_constraint_p ((VALUE), (C), (STR))
 
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  1
+#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(VALUE, C, STR)  1
 
-#define EXTRA_CONSTRAINT(OP, C)                                \
-  s390_extra_constraint ((OP), (C))
+#define EXTRA_CONSTRAINT_STR(OP, C, STR)                                       \
+  s390_extra_constraint_str ((OP), (C), (STR))
 #define EXTRA_MEMORY_CONSTRAINT(C, STR)                                \
   ((C) == 'Q' || (C) == 'R' || (C) == 'S' || (C) == 'T')
 #define EXTRA_ADDRESS_CONSTRAINT(C, STR)                       \
   ((C) == 'U' || (C) == 'W' || (C) == 'Y')
 
+#define CONSTRAINT_LEN(C, STR)                                   \
+  ((C) == 'N' ? 5 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
 
 /* Stack layout and calling conventions.  */
 
index 8b94983..2b79f75 100644 (file)
 ;;    I -- An 8-bit constant (0..255).
 ;;    J -- A 12-bit constant (0..4095).
 ;;    K -- A 16-bit constant (-32768..32767).
-;;    Q -- A memory reference without index-register.
-;;    S -- Valid operand for the LARL instruction.
+;;    L -- Value appropriate as displacement. 
+;;         (0..4095) for short displacement
+;;         (-524288..524287) for long displacement
+;;    M -- Constant integer with a value of 0x7fffffff.
+;;    N -- Multiple letter constraint followed by 4 parameter letters.
+;;         0..9:  number of the part counting from most to least significant
+;;         H,Q:   mode of the part
+;;         D,S,H: mode of the containing operand
+;;         0,F:   value of the other parts (F - all bits set)
+;;         
+;;         The constraint matches if the specified part of a constant
+;;         has a value different from its other parts.
+;;    Q -- Memory reference without index register and with short displacement.
+;;    R -- Memory reference with index register and short displacement.
+;;    S -- Memory reference without index register but with long displacement.
+;;    T -- Memory reference with index register and long displacement.
+;;    U -- Pointer with short displacement.
+;;    W -- Pointer with long displacement.
+;;    Y -- Shift count operand.
 ;;
 ;; Special formats used for outputting 390 instructions.
 ;;
-;;   %b -- Print a constant byte integer.               xy
-;;   %h -- Print a signed 16-bit.                       wxyz
-;;   %N -- Print next register (second word of a DImode reg) or next word.
-;;   %M -- Print next register (second word of a TImode reg) or next word.
-;;   %O -- Print the offset of a memory reference (PLUS (REG) (CONST_INT)).
-;;   %R -- Print the register of a memory reference (PLUS (REG) (CONST_INT)).
+;;     %C: print opcode suffix for branch condition.
+;;     %D: print opcode suffix for inverse branch condition.
+;;     %J: print tls_load/tls_gdcall/tls_ldcall suffix
+;;     %O: print only the displacement of a memory reference.
+;;     %R: print only the base register of a memory reference.
+;;     %N: print the second word of a DImode operand.
+;;     %M: print the second word of a TImode operand.
+
+;;     %b: print integer X as if it's an unsigned byte.
+;;     %x: print integer X as if it's an unsigned word.
+;;     %h: print integer X as if it's a signed word.
+;;     %i: print the first nonzero HImode part of X
+;;     %j: print the first HImode part unequal to 0xffff of X
+
 ;;
 ;; We have a special constraint for pattern matching.
 ;;
                          (match_operand:DI 1 "immediate_operand" "n,n"))
                  (match_operand:DI 2 "immediate_operand" "n,n")))]
   "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_qi (operands[1], DImode, 0) >= 0"
+   && s390_single_part (operands[1], DImode, QImode, 0) >= 0"
 {
-  int part = s390_single_qi (operands[1], DImode, 0);
-  operands[1] = GEN_INT (s390_extract_qi (operands[1], DImode, part));
+  int part = s390_single_part (operands[1], DImode, QImode, 0);
+  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
 
   operands[0] = gen_rtx_MEM (QImode,
                             plus_constant (XEXP (operands[0], 0), part));
                          (match_operand:SI 1 "immediate_operand" "n,n"))
                  (match_operand:SI 2 "immediate_operand" "n,n")))]
   "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_qi (operands[1], SImode, 0) >= 0"
+   && s390_single_part (operands[1], SImode, QImode, 0) >= 0"
 {
-  int part = s390_single_qi (operands[1], SImode, 0);
-  operands[1] = GEN_INT (s390_extract_qi (operands[1], SImode, part));
+  int part = s390_single_part (operands[1], SImode, QImode, 0);
+  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
 
   operands[0] = gen_rtx_MEM (QImode,
                             plus_constant (XEXP (operands[0], 0), part));
                          (match_operand:SI 1 "immediate_operand" "n,n"))
                  (match_operand:SI 2 "immediate_operand" "n,n")))]
   "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_qi (operands[1], HImode, 0) >= 0"
+   && s390_single_part (operands[1], HImode, QImode, 0) >= 0"
 {
-  int part = s390_single_qi (operands[1], HImode, 0);
-  operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
+  int part = s390_single_part (operands[1], HImode, QImode, 0);
+  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
 
   operands[0] = gen_rtx_MEM (QImode,
                             plus_constant (XEXP (operands[0], 0), part));
 
 (define_insn "*tmdi_reg"
   [(set (reg 33)
-        (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "d")
-                         (match_operand:DI 1 "immediate_operand" "n"))
-                 (match_operand:DI 2 "immediate_operand" "n")))]
+        (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "d,d,d,d")
+                         (match_operand:DI 1 "immediate_operand" 
+                                            "N0HD0,N1HD0,N2HD0,N3HD0"))
+                 (match_operand:DI 2 "immediate_operand" "n,n,n,n")))]
   "TARGET_64BIT
    && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
-   && s390_single_hi (operands[1], DImode, 0) >= 0"
-{
-  int part = s390_single_hi (operands[1], DImode, 0);
-  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
-
-  switch (part)
-    {
-      case 0: return "tmhh\t%0,%x1";
-      case 1: return "tmhl\t%0,%x1";
-      case 2: return "tmlh\t%0,%x1";
-      case 3: return "tmll\t%0,%x1";
-      default: abort ();
-    }
-}
+   && s390_single_part (operands[1], DImode, HImode, 0) >= 0"
+  "@
+   tmhh\t%0,%i1
+   tmhl\t%0,%i1
+   tmlh\t%0,%i1
+   tmll\t%0,%i1"
   [(set_attr "op_type" "RI")])
 
 (define_insn "*tmsi_reg"
   [(set (reg 33)
-        (compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "d")
-                         (match_operand:SI 1 "immediate_operand" "n"))
-                 (match_operand:SI 2 "immediate_operand" "n")))]
+        (compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "d,d")
+                         (match_operand:SI 1 "immediate_operand" "N0HS0,N1HS0"))
+                 (match_operand:SI 2 "immediate_operand" "n,n")))]
   "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
-   && s390_single_hi (operands[1], SImode, 0) >= 0"
-{
-  int part = s390_single_hi (operands[1], SImode, 0);
-  operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
-
-  switch (part)
-    {
-      case 0: return "tmh\t%0,%x1";
-      case 1: return "tml\t%0,%x1";
-      default: abort ();
-    }
-}
+   && s390_single_part (operands[1], SImode, HImode, 0) >= 0"
+  "@
+   tmh\t%0,%i1
+   tml\t%0,%i1"
   [(set_attr "op_type" "RI")])
 
 (define_insn "*tmhi_full"
     operands[1] = force_const_mem (DImode, operands[1]);
 })
 
-(define_insn "*movdi_lhi"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (match_operand:DI 1 "immediate_operand" "K"))]
-  "TARGET_64BIT
-   && GET_CODE (operands[1]) == CONST_INT
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
-   && !FP_REG_P (operands[0])"
-  "lghi\t%0,%h1"
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*movdi_lli"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (match_operand:DI 1 "immediate_operand" "n"))]
-  "TARGET_64BIT && s390_single_hi (operands[1], DImode, 0) >= 0
-   && !FP_REG_P (operands[0])"
-{
-  int part = s390_single_hi (operands[1], DImode, 0);
-  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
-
-  switch (part)
-    {
-      case 0: return "llihh\t%0,%x1";
-      case 1: return "llihl\t%0,%x1";
-      case 2: return "llilh\t%0,%x1";
-      case 3: return "llill\t%0,%x1";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*movdi_lay"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (match_operand:DI 1 "address_operand" "p"))]
-  "TARGET_64BIT
-   && TARGET_LONG_DISPLACEMENT
-   && GET_CODE (operands[1]) == CONST_INT
-   && !FP_REG_P (operands[0])"
-  "lay\t%0,%a1"
-  [(set_attr "op_type" "RXY")
-   (set_attr "type" "la")])
-
 (define_insn "*movdi_larl"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (match_operand:DI 1 "larl_operand" "X"))]
     (set_attr "type"    "larl")])
 
 (define_insn "*movdi_64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,m,!*f,!*f,!*f,!R,!T,?Q")
-        (match_operand:DI 1 "general_operand" "d,m,d,*f,R,T,*f,*f,?Q"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" 
+                            "=d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,?Q")
+        (match_operand:DI 1 "general_operand" 
+                            "K,N0HD0,N1HD0,N2HD0,N3HD0,L,d,m,d,*f,R,T,*f,*f,?Q"))]
   "TARGET_64BIT"
   "@
+   lghi\t%0,%h1
+   llihh\t%0,%i1
+   llihl\t%0,%i1
+   llilh\t%0,%i1
+   llill\t%0,%i1
+   lay\t%0,%a1
    lgr\t%0,%1
    lg\t%0,%1
    stg\t%1,%0
    std\t%1,%0
    stdy\t%1,%0
    mvc\t%O0(8,%R0),%1"
-  [(set_attr "op_type" "RRE,RXY,RXY,RR,RX,RXY,RX,RXY,SS")
-   (set_attr "type" "lr,load,store,floadd,floadd,floadd,fstored,fstored,cs")])
+  [(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,RR,RX,RXY,RX,RXY,SS")
+   (set_attr "type" "*,*,*,*,*,la,lr,load,store,floadd,floadd,floadd,
+                     fstored,fstored,cs")])
 
 (define_insn "*movdi_31"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!*f,!R,!T,Q")
     operands[1] = force_const_mem (SImode, operands[1]);
 })
 
-(define_insn "*movsi_lhi"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (match_operand:SI 1 "immediate_operand" "K"))]
-  "GET_CODE (operands[1]) == CONST_INT
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
-   && !FP_REG_P (operands[0])"
-  "lhi\t%0,%h1"
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*movsi_lli"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (match_operand:SI 1 "immediate_operand" "n"))]
-  "TARGET_ZARCH && s390_single_hi (operands[1], SImode, 0) >= 0
-   && !FP_REG_P (operands[0])"
-{
-  int part = s390_single_hi (operands[1], SImode, 0);
-  operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
-
-  switch (part)
-    {
-      case 0: return "llilh\t%0,%x1";
-      case 1: return "llill\t%0,%x1";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*movsi_lay"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (match_operand:SI 1 "address_operand" "p"))]
-  "TARGET_LONG_DISPLACEMENT
-   && GET_CODE (operands[1]) == CONST_INT
-   && !FP_REG_P (operands[0])"
-  "lay\t%0,%a1"
-  [(set_attr "op_type" "RXY")
-   (set_attr "type" "la")])
-
 (define_insn "*movsi_larl"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (match_operand:SI 1 "larl_operand" "X"))]
    [(set_attr "op_type" "RIL")
     (set_attr "type"    "larl")])
 
-(define_insn "*movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,T,!*f,!*f,!*f,!R,!T,?Q")
-        (match_operand:SI 1 "general_operand" "d,R,T,d,d,*f,R,T,*f,*f,?Q"))]
-  ""
+(define_insn "*movsi_zarch"
+  [(set (match_operand:SI 0 "nonimmediate_operand" 
+                            "=d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,?Q")
+        (match_operand:SI 1 "general_operand" 
+                            "K,N0HS0,N1HS0,L,d,R,T,d,d,*f,R,T,*f,*f,?Q"))]
+  "TARGET_ZARCH"
   "@
+   lhi\t%0,%h1
+   llilh\t%0,%i1
+   llill\t%0,%i1
+   lay\t%0,%a1
    lr\t%0,%1
    l\t%0,%1
    ly\t%0,%1
    ste\t%1,%0
    stey\t%1,%0
    mvc\t%O0(4,%R0),%1"
-  [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
-   (set_attr "type" "lr,load,load,store,store,floads,floads,floads,fstores,fstores,cs")])
+  [(set_attr "op_type" "RI,RI,RI,RXY,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
+   (set_attr "type" "*,*,*,la,lr,load,load,store,store,floads,floads,floads,fstores,fstores,cs")])
+
+(define_insn "*movsi_esa"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,?Q")
+        (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,?Q"))]
+  "!TARGET_ZARCH"
+  "@
+   lhi\t%0,%h1
+   lr\t%0,%1
+   l\t%0,%1
+   st\t%1,%0
+   ler\t%0,%1
+   le\t%0,%1
+   ste\t%1,%0
+   mvc\t%O0(4,%R0),%1"
+  [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,SS")
+   (set_attr "type" "*,lr,load,store,floads,floads,fstores,cs")])
 
 (define_peephole2
   [(set (match_operand:SI 0 "register_operand" "")
    llgt\t%0,%1"
   [(set_attr "op_type"  "RRE,RXE")])
 
-(define_insn_and_split "*llgt_sisi_split"
-  [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (and:SI (match_operand:SI 1 "nonimmediate_operand" "d,m")
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
                (const_int 2147483647)))
    (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "#"
-  "&& reload_completed"
+  "TARGET_64BIT && reload_completed"
   [(set (match_dup 0)
         (and:SI (match_dup 1)
                (const_int 2147483647)))]
    llgt\t%0,%N1"
   [(set_attr "op_type"  "RRE,RXE")])
 
-(define_insn_and_split "*llgt_didi_split"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
                 (const_int 2147483647)))
    (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "#"
-  "&& reload_completed"
+  "TARGET_64BIT && reload_completed"
   [(set (match_dup 0)
         (and:DI (match_dup 1)
                 (const_int 2147483647)))]
         (plus:DI (match_dup 1) (match_dup 2)))]
   "TARGET_64BIT
    && s390_match_ccmode (insn, CCAmode)
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")"
   "aghi\t%0,%h2"
   [(set_attr "op_type"  "RI")])
 
    (set (match_operand:SI 0 "register_operand" "=d")
         (plus:SI (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode (insn, CCAmode)
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")"
   "ahi\t%0,%h2"
   [(set_attr "op_type"  "RI")])
 
    ng\t%0,%2"
   [(set_attr "op_type"  "RRE,RXY")])
 
-(define_insn "*anddi3_ni"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (and:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                (match_operand:DI 2 "immediate_operand" "n")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT && s390_single_hi (operands[2], DImode, -1) >= 0"
-{
-  int part = s390_single_hi (operands[2], DImode, -1);
-  operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
-
-  switch (part)
-    {
-      case 0: return "nihh\t%0,%x2";
-      case 1: return "nihl\t%0,%x2";
-      case 2: return "nilh\t%0,%x2";
-      case 3: return "nill\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type"  "RI")])
-
 (define_insn "anddi3"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
-                (match_operand:DI 2 "general_operand" "d,m")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT"
-  "@
-   ngr\t%0,%2
-   ng\t%0,%2"
-  [(set_attr "op_type"  "RRE,RXY")])
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d,d,d,d,d,d")
+       (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o,0,0,0,0,0,0")
+               (match_operand:DI 2 "general_operand" 
+                                   "M,M,N0HDF,N1HDF,N2HDF,N3HDF,d,m")))
+     (clobber (reg:CC 33))]
+   "TARGET_64BIT"
+   "@
+    #
+    #
+    nihh\t%0,%j2
+    nihl\t%0,%j2
+    nilh\t%0,%j2
+    nill\t%0,%j2
+    ngr\t%0,%2
+    ng\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY")])
 
 (define_insn "*anddi3_ss"
   [(set (match_operand:DI 0 "s_operand" "=Q")
    ny\t%0,%2"
   [(set_attr "op_type"  "RR,RX,RXY")])
 
-(define_insn "*andsi3_ni"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (and:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                (match_operand:SI 2 "immediate_operand" "n")))
-   (clobber (reg:CC 33))]
-  "TARGET_ZARCH && s390_single_hi (operands[2], SImode, -1) >= 0"
-{
-  int part = s390_single_hi (operands[2], SImode, -1);
-  operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
-
-  switch (part)
-    {
-      case 0: return "nilh\t%0,%x2";
-      case 1: return "nill\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type"  "RI")])
+(define_expand "andsi3"
+  [(parallel 
+    [(set (match_operand:SI 0 "register_operand" "")
+         (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))
+     (clobber (reg:CC 33))])]
+  ""
+  "")
 
-(define_insn "andsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-        (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
-                (match_operand:SI 2 "general_operand" "d,R,T")))
+(define_insn "*andsi3_zarch"
+  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d,d,d")
+        (and:SI (match_operand:SI 1 "nonimmediate_operand" "d,o,0,0,0,0,0")
+                (match_operand:SI 2 "general_operand" "M,M,N0HSF,N1HSF,d,R,T")))
    (clobber (reg:CC 33))]
-  ""
+  "TARGET_ZARCH"
   "@
+   #
+   #
+   nilh\t%0,%j2
+   nill\t%0,%j2   
    nr\t%0,%2
    n\t%0,%2
    ny\t%0,%2"
-  [(set_attr "op_type"  "RR,RX,RXY")])
+  [(set_attr "op_type"  "RRE,RXE,RI,RI,RR,RX,RXY")])
+
+(define_insn "*andsi3_esa"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+                (match_operand:SI 2 "general_operand" "d,R")))
+   (clobber (reg:CC 33))]
+  "!TARGET_ZARCH"
+  "@
+   nr\t%0,%2
+   n\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")])
 
 (define_insn "*andsi3_ss"
   [(set (match_operand:SI 0 "s_operand" "=Q")
    og\t%0,%2"
   [(set_attr "op_type"  "RRE,RXY")])
 
-(define_insn "*iordi3_oi"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                (match_operand:DI 2 "immediate_operand" "n")))
-   (clobber (reg:CC 33))]
-  "TARGET_64BIT && s390_single_hi (operands[2], DImode, 0) >= 0"
-{
-  int part = s390_single_hi (operands[2], DImode, 0);
-  operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
-
-  switch (part)
-    {
-      case 0: return "oihh\t%0,%x2";
-      case 1: return "oihl\t%0,%x2";
-      case 2: return "oilh\t%0,%x2";
-      case 3: return "oill\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type"  "RI")])
-
 (define_insn "iordi3"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
-                (match_operand:DI 2 "general_operand" "d,m")))
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d,d,d,d")
+        (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,0,0,0,0")
+                (match_operand:DI 2 "general_operand" "N0HD0,N1HD0,N2HD0,N3HD0,d,m")))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "@
+   oihh\t%0,%i2
+   oihl\t%0,%i2
+   oilh\t%0,%i2
+   oill\t%0,%i2
    ogr\t%0,%2
    og\t%0,%2"
-  [(set_attr "op_type"  "RRE,RXY")])
+  [(set_attr "op_type"  "RI,RI,RI,RI,RRE,RXY")])
 
 (define_insn "*iordi3_ss"
   [(set (match_operand:DI 0 "s_operand" "=Q")
    oy\t%0,%2"
   [(set_attr "op_type"  "RR,RX,RXY")])
 
-(define_insn "*iorsi3_oi"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                (match_operand:SI 2 "immediate_operand" "n")))
-   (clobber (reg:CC 33))]
-  "TARGET_ZARCH && s390_single_hi (operands[2], SImode, 0) >= 0"
-{
-  int part = s390_single_hi (operands[2], SImode, 0);
-  operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
-
-  switch (part)
-    {
-      case 0: return "oilh\t%0,%x2";
-      case 1: return "oill\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type"  "RI")])
+(define_expand "iorsi3"
+  [(parallel 
+    [(set (match_operand:SI 0 "register_operand" "")
+         (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
+                 (match_operand:SI 2 "general_operand" "")))
+     (clobber (reg:CC 33))])]
+  ""
+  "")
 
-(define_insn "iorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
-                (match_operand:SI 2 "general_operand" "d,R,T")))
+(define_insn "iorsi3_zarch"
+  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
+        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0,0,0")
+                (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,d,R,T")))
    (clobber (reg:CC 33))]
-  ""
+  "TARGET_ZARCH"
   "@
+   oilh\t%0,%i2
+   oill\t%0,%i2
    or\t%0,%2
    o\t%0,%2
    oy\t%0,%2"
-  [(set_attr "op_type"  "RR,RX,RXY")])
+  [(set_attr "op_type"  "RI,RI,RR,RX,RXY")])
+
+(define_insn "iorsi3_esa"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+                (match_operand:SI 2 "general_operand" "d,R")))
+   (clobber (reg:CC 33))]
+  "!TARGET_ZARCH"
+  "@
+   or\t%0,%2
+   o\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")])
 
 (define_insn "*iorsi3_ss"
   [(set (match_operand:SI 0 "s_operand" "=Q")
index ce59a0f..5e3618f 100644 (file)
@@ -2196,13 +2196,52 @@ Unsigned 12-bit constant (0--4095)
 Signed 16-bit constant (@minus{}32768--32767)
 
 @item L
-Unsigned 16-bit constant (0--65535)
+Value appropriate as displacement.
+@table @code
+       @item (0..4095)
+       for short displacement
+       @item (-524288..524287)
+       for long displacement
+@end table
+
+@item M
+Constant integer with a value of 0x7fffffff.
+
+@item N
+Multiple letter constraint followed by 4 parameter letters.
+@table @code
+         @item 0..9:
+         number of the part counting from most to least significant
+         @item H,Q:
+         mode of the part
+         @item D,S,H:
+         mode of the containing operand
+         @item 0,F:
+         value of the other parts (F - all bits set)
+@end table
+The constraint matches if the specified part of a constant
+has a value different from it's other parts.
 
 @item Q
-Memory reference without index register
+Memory reference without index register and with short displacement.
+
+@item R
+Memory reference with index register and short displacement.
 
 @item S
-Symbolic constant suitable for use with the @code{larl} instruction
+Memory reference without index register but with long displacement.
+
+@item T
+Memory reference with index register and long displacement.
+
+@item U
+Pointer with short displacement.
+
+@item W
+Pointer with long displacement.
+
+@item Y
+Shift count operand.
 
 @end table