2005-08-12 Andreas Krebbel <krebbel1@de.ibm.com>
+ * config/s390/predicates.md (setmem_operand): New predicate.
+ (shift_count_operand): Accept ANDs with special constants as
+ operand.
+ * config/s390/s390.c (print_shift_count_operand): Skip ANDs
+ with special constants.
+ * config/s390/s390.md ("setmem_long", "*setmem_long"): Replaced
+ shift_count_operand with setmem_operand.
+
+2005-08-12 Andreas Krebbel <krebbel1@de.ibm.com>
+
* config/s390/s390.c (s390_extract_part, s390_single_part):
Type cast added.
(s390_const_ok_for_constraint_p): Added SImode to the N constraint.
(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;
+
+ /* 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
{
HOST_WIDE_INT offset = 0;
+ /* Shift count operands are always truncated to the 6 least significant bits and
+ the setmem padding byte to the least 8 significant bits. Hence we can drop
+ pointless ANDs. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ {
+ if ((INTVAL (XEXP (op, 1)) & 63) != 63)
+ gcc_unreachable ();
+
+ op = XEXP (op, 0);
+ }
+
/* We can have an integer constant, an address register,
or a sum of the two. */
if (GET_CODE (op) == CONST_INT)
[(parallel
[(clobber (match_dup 1))
(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand 2 "shift_count_operand" ""))
+ (match_operand 2 "setmem_operand" ""))
(use (match_operand 1 "general_operand" ""))
(use (match_dup 3))
(clobber (reg:CC CC_REGNUM))])]
(define_insn "*setmem_long"
[(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
(set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (match_operand 2 "shift_count_operand" "Y"))
+ (match_operand 2 "setmem_operand" "Y"))
(use (match_dup 3))
(use (match_operand:<DBL> 1 "register_operand" "d"))
(clobber (reg:CC CC_REGNUM))]