aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2001-09-29 22:56:14 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2001-09-29 22:56:14 +0000
commitba95698296f3733f461f9732b3be5c8dc20cee6a (patch)
tree78a147c5f5a1ff5ea621fbfe6e1fbe64a319a2bb
parent3d17d93d9fe5c1141c319158e756f6b9b6300f86 (diff)
downloadgcc-ba95698296f3733f461f9732b3be5c8dc20cee6a.zip
gcc-ba95698296f3733f461f9732b3be5c8dc20cee6a.tar.gz
gcc-ba95698296f3733f461f9732b3be5c8dc20cee6a.tar.bz2
s390.h (EXTRA_CC_MODES): Add CCLmode.
* config/s390/s390.h (EXTRA_CC_MODES): Add CCLmode. (SELECT_CC_MODE): Use s390_select_ccmode. * config/s390/s390-protos.h (s390_select_ccmode): Add. * config/s390/s390.c (s390_select_ccmode): New. (s390_match_ccmode): Add CCLmode. (s390_branch_condition_mask, s390_branch_condition_mnemonic): New. (output_branch_condition, output_inverse_branch_condition): Removed. (print_operand): Use s390_branch_condition_mnemonic. * config/s390/s390.md (addsi3_cc, addsi3_cconly, addsi3_cconly2, subsi3_cc, subsi3_cconly): Use logical instructions and CCLmode. (bunordered, bordered, buneq, bungt, bunlt, bnuge, bunle, bltgt): New. * config/s390/s390.c (check_and_change_labels): Preserve CC mode when converting conditional branches to far branches. * config/s390/s390.md (cmpstr_const, cmpstr_64, cmpstr_31, cmpint_si, cmpint_di): Use CCSmode instead of CCUmode. * config/s390/s390.c (legitimate_la_operand_p): New. * config/s390/s390-protos.h (legitimate_la_operand_p): Add. * config/s390/s390.md (movsi): Convert load address patterns to arithmetic operations when necessary. (addaddr_picR, addaddr_picL, addaddr_picN): Removed. (do_la): Renamed to *do_la and use legitimate_la_operand_p. (*do_la_reg_0): Don't use before reload. * config/s390/s390.c (legitimize_address): Make more efficient use of two-register addressing mode. * config/s390/s390.c (s390_function_prologue): Fix incorrect prolog with -mno-backchain in some corner cases. * config/s390/s390.md (cmpsi_cct): Operands 0 and 1 do not commute. From-SVN: r45891
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c331
-rw-r--r--gcc/config/s390/s390.h9
-rw-r--r--gcc/config/s390/s390.md202
5 files changed, 412 insertions, 167 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8e5d182..c89d7c8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,38 @@
+2001-09-30 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.h (EXTRA_CC_MODES): Add CCLmode.
+ (SELECT_CC_MODE): Use s390_select_ccmode.
+ * config/s390/s390-protos.h (s390_select_ccmode): Add.
+ * config/s390/s390.c (s390_select_ccmode): New.
+ (s390_match_ccmode): Add CCLmode.
+ (s390_branch_condition_mask, s390_branch_condition_mnemonic): New.
+ (output_branch_condition, output_inverse_branch_condition): Removed.
+ (print_operand): Use s390_branch_condition_mnemonic.
+ * config/s390/s390.md (addsi3_cc, addsi3_cconly, addsi3_cconly2,
+ subsi3_cc, subsi3_cconly): Use logical instructions and CCLmode.
+ (bunordered, bordered, buneq, bungt, bunlt, bnuge, bunle, bltgt): New.
+
+ * config/s390/s390.c (check_and_change_labels): Preserve CC mode
+ when converting conditional branches to far branches.
+ * config/s390/s390.md (cmpstr_const, cmpstr_64, cmpstr_31, cmpint_si,
+ cmpint_di): Use CCSmode instead of CCUmode.
+
+ * config/s390/s390.c (legitimate_la_operand_p): New.
+ * config/s390/s390-protos.h (legitimate_la_operand_p): Add.
+ * config/s390/s390.md (movsi): Convert load address patterns to
+ arithmetic operations when necessary.
+ (addaddr_picR, addaddr_picL, addaddr_picN): Removed.
+ (do_la): Renamed to *do_la and use legitimate_la_operand_p.
+ (*do_la_reg_0): Don't use before reload.
+
+ * config/s390/s390.c (legitimize_address): Make more efficient
+ use of two-register addressing mode.
+
+ * config/s390/s390.c (s390_function_prologue): Fix incorrect prolog
+ with -mno-backchain in some corner cases.
+
+ * config/s390/s390.md (cmpsi_cct): Operands 0 and 1 do not commute.
+
2001-09-29 Alexandre Oliva <aoliva@redhat.com>
* reload.c (find_reloads): Mark new USE insns with QImode.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 7f16843..baee5a0 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -42,7 +42,9 @@ extern int load_multiple_operation PARAMS ((rtx, enum machine_mode));
extern int store_multiple_operation PARAMS ((rtx, enum machine_mode));
extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
+extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
extern int symbolic_reference_mentioned_p PARAMS ((rtx));
+extern int legitimate_la_operand_p PARAMS ((rtx));
extern int legitimate_pic_operand_p PARAMS ((rtx));
extern int legitimate_constant_p PARAMS ((rtx));
extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index e4bc735..647a5fd 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -94,11 +94,11 @@ struct s390_address
};
static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
+static int s390_branch_condition_mask PARAMS ((rtx));
+static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));
static int base_n_index_p PARAMS ((rtx));
static int check_mode PARAMS ((rtx, enum machine_mode *));
static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
-static void output_branch_condition PARAMS ((FILE *, rtx));
-static void output_inverse_branch_condition PARAMS ((FILE *, rtx));
static int reg_used_in_mem_p PARAMS ((int, rtx));
static int addr_generation_dependency_p PARAMS ((rtx, rtx));
static int other_chunk PARAMS ((int *, int, int));
@@ -135,9 +135,6 @@ s390_match_ccmode_set (set, req_mode)
set_mode = GET_MODE (SET_DEST (set));
switch (set_mode)
{
- case CCmode:
- return 0;
-
case CCSmode:
if (req_mode != CCSmode)
return 0;
@@ -146,6 +143,10 @@ s390_match_ccmode_set (set, req_mode)
if (req_mode != CCUmode)
return 0;
break;
+ case CCLmode:
+ if (req_mode != CCLmode)
+ return 0;
+ break;
case CCZmode:
if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode)
return 0;
@@ -184,6 +185,161 @@ s390_match_ccmode (insn, req_mode)
return 1;
}
+/* Given a comparison code OP (EQ, NE, etc.) and the operands
+ OP0 and OP1 of a COMPARE, return the mode to be used for the
+ comparison. */
+
+enum machine_mode
+s390_select_ccmode (code, op0, op1)
+ enum rtx_code code;
+ rtx op0;
+ rtx op1;
+{
+ switch (code)
+ {
+ case EQ:
+ case NE:
+ if (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
+ || GET_CODE (op1) == NEG)
+ return CCLmode;
+
+ return CCZmode;
+
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case UNORDERED:
+ case ORDERED:
+ case UNEQ:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ case LTGT:
+ return CCSmode;
+
+ case LEU:
+ case LTU:
+ case GEU:
+ case GTU:
+ return CCUmode;
+
+ default:
+ abort ();
+ }
+}
+
+/* Return branch condition mask to implement a branch
+ specified by CODE. */
+
+static int
+s390_branch_condition_mask (code)
+ rtx code;
+{
+ const int CC0 = 1 << 3;
+ const int CC1 = 1 << 2;
+ const int CC2 = 1 << 1;
+ const int CC3 = 1 << 0;
+
+ if (GET_CODE (XEXP (code, 0)) != REG
+ || REGNO (XEXP (code, 0)) != CC_REGNUM
+ || XEXP (code, 1) != const0_rtx)
+ abort ();
+
+ switch (GET_MODE (XEXP (code, 0)))
+ {
+ case CCZmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCLmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0 | CC2;
+ case NE: return CC1 | CC3;
+ case UNORDERED: return CC2 | CC3; /* carry */
+ case ORDERED: return CC0 | CC1; /* no carry */
+ default:
+ abort ();
+ }
+ break;
+
+ case CCUmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LTU: return CC1;
+ case GTU: return CC2;
+ case LEU: return CC0 | CC1;
+ case GEU: return CC0 | CC2;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCSmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1;
+ case GT: return CC2;
+ case LE: return CC0 | CC1;
+ case GE: return CC0 | CC2;
+ case UNORDERED: return CC3;
+ case ORDERED: return CC0 | CC1 | CC2;
+ case UNEQ: return CC0 | CC3;
+ case UNLT: return CC1 | CC3;
+ case UNGT: return CC2 | CC3;
+ case UNLE: return CC0 | CC1 | CC3;
+ case UNGE: return CC0 | CC2 | CC3;
+ case LTGT: return CC1 | CC2;
+ default:
+ abort ();
+ }
+
+ default:
+ abort ();
+ }
+}
+
+/* If INV is false, return assembler mnemonic string to implement
+ a branch specified by CODE. If INV is true, return mnemonic
+ for the corresponding inverted branch. */
+
+static const char *
+s390_branch_condition_mnemonic (code, inv)
+ rtx code;
+ int inv;
+{
+ static const char *mnemonic[16] =
+ {
+ NULL, "o", "h", "nle",
+ "l", "nhe", "lh", "ne",
+ "e", "nlh", "he", "nl",
+ "le", "nh", "no", NULL
+ };
+
+ int mask = s390_branch_condition_mask (code);
+
+ if (inv)
+ mask ^= 15;
+
+ if (mask < 1 || mask > 14)
+ abort ();
+
+ return mnemonic[mask];
+}
+
+
/* Change optimizations to be performed, depending on the
optimization level.
@@ -887,6 +1043,40 @@ legitimate_address_p (mode, addr, strict)
return s390_decompose_address (addr, NULL, strict);
}
+/* Return 1 if OP is a valid operand for the LA instruction.
+ In 31-bit, we need to prove that the result is used as an
+ address, as LA performs only a 31-bit addition. */
+
+int
+legitimate_la_operand_p (op)
+ register rtx op;
+{
+ struct s390_address addr;
+ if (!s390_decompose_address (op, &addr, FALSE))
+ return FALSE;
+
+ if (TARGET_64BIT)
+ return TRUE;
+
+ /* Use of the base or stack pointer implies address. */
+
+ if (addr.base && GET_CODE (addr.base) == REG)
+ {
+ if (REGNO (addr.base) == BASE_REGISTER
+ || REGNO (addr.base) == STACK_POINTER_REGNUM)
+ return TRUE;
+ }
+
+ if (addr.indx && GET_CODE (addr.indx) == REG)
+ {
+ if (REGNO (addr.indx) == BASE_REGISTER
+ || REGNO (addr.indx) == STACK_POINTER_REGNUM)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* Return a legitimate reference for ORIG (an address) using the
register REG. If REG is 0, a new pseudo is generated.
@@ -1199,87 +1389,52 @@ legitimize_address (x, oldx, mode)
register rtx oldx ATTRIBUTE_UNUSED;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- if (flag_pic && SYMBOLIC_CONST (x))
- return legitimize_pic_address (x, 0);
-
- return x;
-}
+ rtx constant_term = const0_rtx;
-
-/* Output branch condition code of CODE in assembler
- syntax to stdio stream FILE. */
-
-static void
-output_branch_condition (file, code)
- FILE *file;
- rtx code;
-{
- switch (GET_CODE (code))
+ if (flag_pic)
{
- case EQ:
- fprintf (file, "e");
- break;
- case NE:
- fprintf (file, "ne");
- break;
- case GT:
- case GTU:
- fprintf (file, "h");
- break;
- case LT:
- case LTU:
- fprintf (file, "l");
- break;
- case GE:
- case GEU:
- fprintf (file, "he");
- break;
- case LE:
- case LEU:
- fprintf (file, "le");
- break;
- default:
- fatal_insn ("Unknown CC code", code);
+ if (SYMBOLIC_CONST (x)
+ || (GET_CODE (x) == PLUS
+ && (SYMBOLIC_CONST (XEXP (x, 0))
+ || SYMBOLIC_CONST (XEXP (x, 1)))))
+ x = legitimize_pic_address (x, 0);
+
+ if (legitimate_address_p (mode, x, FALSE))
+ return x;
}
-}
-/* Output the inverse of the branch condition code of CODE
- in assembler syntax to stdio stream FILE. */
+ x = eliminate_constant_term (x, &constant_term);
-static void
-output_inverse_branch_condition (file, code)
- FILE *file;
- rtx code;
-{
- switch (GET_CODE (code))
+ if (GET_CODE (x) == PLUS)
{
- case EQ:
- fprintf (file, "ne");
- break;
- case NE:
- fprintf (file, "e");
- break;
- case GT:
- case GTU:
- fprintf (file, "nh");
- break;
- case LT:
- case LTU:
- fprintf (file, "nl");
- break;
- case GE:
- case GEU:
- fprintf (file, "nhe");
- break;
- case LE:
- case LEU:
- fprintf (file, "nle");
- break;
- default:
- fatal_insn ("Unknown CC code", code);
+ if (GET_CODE (XEXP (x, 0)) == REG)
+ {
+ register rtx temp = gen_reg_rtx (Pmode);
+ register rtx val = force_operand (XEXP (x, 1), temp);
+ if (val != temp)
+ emit_move_insn (temp, val);
+
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0), temp);
+ }
+
+ else if (GET_CODE (XEXP (x, 1)) == REG)
+ {
+ register rtx temp = gen_reg_rtx (Pmode);
+ register rtx val = force_operand (XEXP (x, 0), temp);
+ if (val != temp)
+ emit_move_insn (temp, val);
+
+ x = gen_rtx_PLUS (Pmode, temp, XEXP (x, 1));
+ }
}
+
+ if (constant_term != const0_rtx)
+ x = gen_rtx_PLUS (Pmode, x, constant_term);
+
+ return x;
}
+
/* Output symbolic constant X in assembler syntax to
stdio stream FILE. */
@@ -1417,11 +1572,11 @@ print_operand (file, x, code)
switch (code)
{
case 'C':
- output_branch_condition (file, x);
+ fprintf (file, s390_branch_condition_mnemonic (x, FALSE));
return;
case 'D':
- output_inverse_branch_condition (file, x);
+ fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
return;
case 'Y':
@@ -1806,7 +1961,7 @@ check_and_change_labels (insn, ltorg_uids)
int *ltorg_uids;
{
rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- rtx target, jump;
+ rtx target, jump, cjump;
rtx pattern, tmp, body, label1;
int addr0, addr1;
@@ -1878,7 +2033,10 @@ check_and_change_labels (insn, ltorg_uids)
}
label1 = gen_label_rtx ();
- emit_jump_insn_before (gen_icjump (label1, XEXP (body, 0)), insn);
+ cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
+ cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), pc_rtx, cjump);
+ cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
+ emit_jump_insn_before (cjump, insn);
emit_insn_before (gen_movsi (temp_reg, target), insn);
tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
@@ -1912,7 +2070,10 @@ check_and_change_labels (insn, ltorg_uids)
}
label1 = gen_label_rtx ();
- emit_jump_insn_before (gen_cjump (label1, XEXP (body, 0)), insn);
+ cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
+ cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), cjump, pc_rtx);
+ cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
+ emit_jump_insn_before (cjump, insn);
emit_insn_before (gen_movsi (temp_reg, target), insn);
tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
@@ -2541,8 +2702,7 @@ s390_function_prologue (file, lsize)
/* Decrement stack. */
- if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET +
- lsize + STACK_POINTER_OFFSET > 4095
+ if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
|| frame_pointer_needed
|| current_function_calls_alloca))
{
@@ -2582,8 +2742,7 @@ s390_function_prologue (file, lsize)
/* Generate backchain. */
- if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET +
- lsize + STACK_POINTER_OFFSET > 4095
+ if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
|| frame_pointer_needed
|| current_function_calls_alloca))
{
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index d250f05..90ba647 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1687,6 +1687,7 @@ do { \
#define EXTRA_CC_MODES \
CC (CCZmode, "CCZ") \
CC (CCAmode, "CCA") \
+ CC (CCLmode, "CCL") \
CC (CCUmode, "CCU") \
CC (CCSmode, "CCS") \
CC (CCTmode, "CCT")
@@ -1694,13 +1695,7 @@ do { \
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) \
- ( (OP) == EQ || (OP) == NE ? CCZmode \
- : (OP) == LE || (OP) == LT || \
- (OP) == GE || (OP) == GT ? CCSmode \
- : (OP) == LEU || (OP) == LTU || \
- (OP) == GEU || (OP) == GTU ? CCUmode \
- : CCmode )
+#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
/* Define the information needed to generate branch and scc insns. This is
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 853ac9b..18e9c1c 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -369,7 +369,7 @@
(define_insn "*cmpsi_cct"
[(set (reg 33)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "%d")
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "const1_operand" "")
(match_operand:SI 2 "immediate_operand" "I"))
(const_int 0)))]
@@ -856,6 +856,19 @@
if (flag_pic && SYMBOLIC_CONST (operands[1]))
emit_pic_move (operands, SImode);
+
+ /* expr.c tries to load an effective address using
+ force_reg. This fails because we don't have a
+ generic load_address pattern. Convert the move
+ to a proper arithmetic operation instead, unless
+ it is guaranteed to be OK. */
+ if (GET_CODE (operands[1]) == PLUS
+ && !legitimate_la_operand_p (operands[1]))
+ {
+ operands[1] = force_operand (operands[1], operands[0]);
+ if (operands[1] == operands[0])
+ DONE;
+ }
}")
(define_insn "*movsi"
@@ -1835,8 +1848,8 @@
; Compare a block that is less than 256 bytes in length.
(define_insn "cmpstr_const"
- [(set (reg:CCU 33)
- (compare:CCU (match_operand:BLK 0 "s_operand" "oQ")
+ [(set (reg:CCS 33)
+ (compare:CCS (match_operand:BLK 0 "s_operand" "oQ")
(match_operand:BLK 1 "s_operand" "oQ")))
(use (match_operand 2 "immediate_operand" "I"))]
"(unsigned) INTVAL (operands[2]) < 256"
@@ -1848,8 +1861,8 @@
; Compare a block that is larger than 255 bytes in length.
(define_insn "cmpstr_64"
- [(set (reg:CCU 33)
- (compare:CCU (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+ [(set (reg:CCS 33)
+ (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
(mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
(clobber (subreg:DI (match_dup 0) 0))
(clobber (subreg:DI (match_dup 0) 8))
@@ -1862,8 +1875,8 @@
(set_attr "type" "other")])
(define_insn "cmpstr_31"
- [(set (reg:CCU 33)
- (compare:CCU (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+ [(set (reg:CCS 33)
+ (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
(mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
(clobber (subreg:SI (match_dup 0) 0))
(clobber (subreg:SI (match_dup 0) 4))
@@ -1879,7 +1892,7 @@
(define_insn "cmpint_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (compare:SI (reg:CCU 33) (const_int 0)))]
+ (compare:SI (reg:CCS 33) (const_int 0)))]
""
"*
{
@@ -1896,7 +1909,7 @@
(define_insn "cmpint_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (compare:DI (reg:CCU 33) (const_int 0)))]
+ (compare:DI (reg:CCS 33) (const_int 0)))]
"TARGET_64BIT"
"*
{
@@ -2907,76 +2920,44 @@
(set_attr "atype" "mem")
(set_attr "type" "la")])
-(define_insn "*addaddr_picR"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (plus:SI (match_operand:SI 1 "register_operand" "a")
- (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)))]
- ""
- "la\\t%0,0(%1,%2)"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
-
-(define_insn "*addaddr_picL"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)
- (match_operand:SI 1 "register_operand" "a")))]
- ""
- "la\\t%0,0(%1,%2)"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
-
-(define_insn "*addaddr_picN"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:SI 1 "register_operand" "a")] 101))]
- ""
- "la\\t%0,0(%1)"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
-
(define_insn "*addsi3_cc"
[(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,m"))
+ (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonimmediate_operand" "d,m"))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (set (match_operand:SI 0 "register_operand" "=d,d")
(plus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCSmode)"
+ "s390_match_ccmode(insn, CCLmode)"
"@
- ar\\t%0,%2
- ahi\\t%0,%h2
- a\\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
(define_insn "*addsi3_cconly"
[(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,m"))
+ (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCLmode)"
"@
- ar\\t%0,%2
- ahi\\t%0,%h2
- a\\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
(define_insn "*addsi3_cconly2"
[(set (reg 33)
- (compare (match_operand:SI 1 "register_operand" "%0,0,0")
- (neg:SI (match_operand:SI 2 "general_operand" "d,K,m"))))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
+ (compare (match_operand:SI 1 "register_operand" "%0,0")
+ (neg:SI (match_operand:SI 2 "general_operand" "d,m"))))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCLmode)"
"@
- ar\\t%0,%2
- ahi\\t%0,%h2
- a\\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
@@ -2991,10 +2972,11 @@
[(set_attr "op_type" "RR,RI,RX")
(set_attr "atype" "reg,reg,mem")])
-(define_insn "do_la"
+(define_insn "*do_la"
[(set (match_operand:SI 0 "register_operand" "=a")
(match_operand:QI 1 "address_operand" "p"))]
- "volatile_ok"
+ "reload_in_progress || reload_completed
+ || legitimate_la_operand_p (operands[1])"
"la\\t%0,%a1"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")
@@ -3004,7 +2986,7 @@
[(set (match_operand:SI 0 "register_operand" "=d")
(plus:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "d")))]
- ""
+ "reload_in_progress || reload_completed"
"brxle\\t%0,%2,.+4"
[(set_attr "op_type" "RSI")
(set_attr "atype" "reg")])
@@ -3220,10 +3202,10 @@
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d,d")
(minus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCSmode)"
+ "s390_match_ccmode(insn, CCLmode)"
"@
- sr\\t%0,%2
- s\\t%0,%2"
+ slr\\t%0,%2
+ sl\\t%0,%2"
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
@@ -3233,10 +3215,10 @@
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
+ "s390_match_ccmode(insn, CCLmode)"
"@
- sr\\t%0,%2
- s\\t%0,%2"
+ slr\\t%0,%2
+ sl\\t%0,%2"
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
@@ -4945,6 +4927,78 @@
""
"{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+(define_expand "bunordered"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (unordered (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bordered"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ordered (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "buneq"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (uneq (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bungt"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ungt (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bunlt"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (unlt (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bunge"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (unge (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bunle"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (unle (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bltgt"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ltgt (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
;;
;;- Conditional jump instructions.