aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390/predicates.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/s390/predicates.md')
-rw-r--r--gcc/config/s390/predicates.md56
1 files changed, 55 insertions, 1 deletions
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index fb8a9a40085..9f8f8237075 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -75,13 +75,63 @@
(and (match_test "mode == Pmode")
(match_test "!legitimate_la_operand_p (op)"))))
+;; Return true if OP is a valid operand for setmem.
+
+(define_predicate "setmem_operand"
+ (match_code "reg, subreg, plus, const_int")
+{
+ HOST_WIDE_INT offset = 0;
+
+ /* The padding byte operand of the mvcle instruction is always truncated
+ to the 8 least significant bits. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & 255) == 255)
+ op = XEXP (op, 0);
+
+ /* We can have an integer constant, an address register,
+ or a sum of the two. Note that reload already checks
+ that any register present is an address register, so
+ we just check for any register here. */
+ if (GET_CODE (op) == CONST_INT)
+ {
+ offset = INTVAL (op);
+ op = NULL_RTX;
+ }
+ if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ {
+ offset = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ }
+ while (op && GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ if (op && GET_CODE (op) != REG)
+ return false;
+
+ if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && !GENERAL_REGNO_P (REGNO (op)))
+ return false;
+
+ /* Unfortunately we have to reject constants that are invalid
+ for an address, or else reload will get confused. */
+ if (!DISP_IN_RANGE (offset))
+ return false;
+
+ return true;
+})
+
;; Return true if OP is a valid shift count operand.
(define_predicate "shift_count_operand"
- (match_code "reg, subreg, plus, const_int")
+ (match_code "reg, subreg, plus, const_int, and")
{
HOST_WIDE_INT offset = 0;
+ /* Shift count operands are always truncated to the 6 least significant bits.
+ So we can accept pointless ANDs here. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & 63) == 63)
+ op = XEXP (op, 0);
+
/* We can have an integer constant, an address register,
or a sum of the two. Note that reload already checks
that any register present is an address register, so
@@ -101,6 +151,10 @@
if (op && GET_CODE (op) != REG)
return false;
+ if (op && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && !GENERAL_REGNO_P (REGNO (op)))
+ return false;
+
/* Unfortunately we have to reject constants that are invalid
for an address, or else reload will get confused. */
if (!DISP_IN_RANGE (offset))