diff options
Diffstat (limited to 'gcc/config/s390/predicates.md')
-rw-r--r-- | gcc/config/s390/predicates.md | 56 |
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)) |