--- gcc/config/s390/constraints.md | 11 ++++- gcc/config/s390/predicates.md | 6 +++ gcc/config/s390/s390.c | 92 +++++++++++++++++++++++++++------------- gcc/config/s390/s390.md | 48 +++++---------------- 4 files changed, 90 insertions(+), 67 deletions(-)
diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md index 8564b66..9d416ad 100644 --- a/gcc/config/s390/constraints.md +++ b/gcc/config/s390/constraints.md @@ -45,6 +45,8 @@ ;; 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) +;; -- +;; xx[DS]q satisfies s390_contiguous_bitmask_p for DImode or SImode ;; ;; The constraint matches if the specified part of a constant ;; has a value different from its other parts. If the letter x @@ -330,8 +332,15 @@ (and (match_code "const_int") (match_test "s390_N_constraint_str (\"xQH0\", ival)"))) +(define_constraint "NxxDq" + "@internal" + (and (match_code "const_int") + (match_test "s390_contiguous_bitmask_p (ival, 64, NULL, NULL)"))) - +(define_constraint "NxxSq" + "@internal" + (and (match_code "const_int") + (match_test "s390_contiguous_bitmask_p (ival, 32, NULL, NULL)"))) ;; ;; Double-letter constraints starting with O follow. diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 9d619fb..333457d 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -154,6 +154,12 @@ return false; }) +(define_predicate "contiguous_bitmask_operand" + (match_code "const_int") +{ + return s390_contiguous_bitmask_p (INTVAL (op), GET_MODE_BITSIZE (mode), NULL, NULL); +}) + ;; operators -------------------------------------------------------------- ;; Return nonzero if OP is a valid comparison operator diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index d67c0eb..4e22100 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -5286,28 +5286,35 @@ print_operand_address (FILE *file, rtx addr) 'C': print opcode suffix for branch condition. 'D': print opcode suffix for inverse branch condition. 'E': print opcode suffix for branch on index instruction. - 'J': print tls_load/tls_gdcall/tls_ldcall suffix 'G': print the size of the operand in bytes. + 'J': print tls_load/tls_gdcall/tls_ldcall suffix + 'M': print the second word of a TImode operand. + 'N': print the second word of a DImode operand. 'O': print only the displacement of a memory reference. 'R': print only the base register of a memory reference. 'S': print S-type memory reference (base+displacement). - 'N': print the second word of a DImode operand. - 'M': print the second word of a TImode operand. 'Y': print shift count operand. 'b': print integer X as if it's an unsigned byte. 'c': print integer X as if it's an signed byte. - 'x': print integer X as if it's an unsigned halfword. + 'e': "end" of DImode contiguous bitmask X. + 'f': "end" of SImode contiguous bitmask X. 'h': print integer X as if it's a signed halfword. 'i': print the first nonzero HImode part of X. 'j': print the first HImode part unequal to -1 of X. 'k': print the first nonzero SImode part of X. 'm': print the first SImode part unequal to -1 of X. - 'o': print integer X as if it's an unsigned 32bit word. */ + 'o': print integer X as if it's an unsigned 32bit word. + 's': "start" of DImode contiguous bitmask X. + 't': "start" of SImode contiguous bitmask X. + 'x': print integer X as if it's an unsigned halfword. +*/ void print_operand (FILE *file, rtx x, int code) { + HOST_WIDE_INT ival; + switch (code) { case 'C': @@ -5486,30 +5493,57 @@ print_operand (FILE *file, rtx x, int code) break; case CONST_INT: - if (code == 'b') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff); - else if (code == 'c') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xff) ^ 0x80) - 0x80); - else if (code == 'x') - 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 if (code == 'k') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - s390_extract_part (x, SImode, 0)); - else if (code == 'm') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - s390_extract_part (x, SImode, -1)); - else if (code == 'o') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffffffff); - else - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); + ival = INTVAL (x); + switch (code) + { + case 0: + break; + case 'b': + ival &= 0xff; + break; + case 'c': + ival = ((ival & 0xff) ^ 0x80) - 0x80; + break; + case 'x': + ival &= 0xffff; + break; + case 'h': + ival = ((ival & 0xffff) ^ 0x8000) - 0x8000; + break; + case 'i': + ival = s390_extract_part (x, HImode, 0); + break; + case 'j': + ival = s390_extract_part (x, HImode, -1); + break; + case 'k': + ival = s390_extract_part (x, SImode, 0); + break; + case 'm': + ival = s390_extract_part (x, SImode, -1); + break; + case 'o': + ival &= 0xffffffff; + break; + case 'e': case 'f': + case 's': case 't': + { + int pos, len; + bool ok; + + len = (code == 's' || code == 'e' ? 64 : 32); + ok = s390_contiguous_bitmask_p (ival, len, &pos, &len); + gcc_assert (ok); + if (code == 's' || code == 't') + ival = 64 - pos - len; + else + ival = 64 - 1 - pos; + } + break; + default: + output_operand_lossage ("invalid constant for output modifier '%c'", code); + } + fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival); break; case CONST_DOUBLE: diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index b3d096c..76ec9c4 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -518,6 +518,10 @@ ;; Maximum unsigned integer that fits in MODE. (define_mode_attr max_uint [(HI "65535") (QI "255")]) +;; Start and end field computations for RISBG et al. +(define_mode_attr bfstart [(DI "s") (SI "t")]) +(define_mode_attr bfend [(DI "e") (SI "f")]) + ;; ;;- Compare instructions. ;; @@ -3389,28 +3393,12 @@ (define_insn "*insv<mode>_z10_noshift" [(set (match_operand:GPR 0 "nonimmediate_operand" "=d") (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d") - (match_operand 2 "const_int_operand" "n")) + (match_operand:GPR 2 "contiguous_bitmask_operand" "")) (and:GPR (match_operand:GPR 3 "nonimmediate_operand" "0") - (match_operand 4 "const_int_operand" "n")))) + (match_operand:GPR 4 "const_int_operand" "")))) (clobber (reg:CC CC_REGNUM))] - "TARGET_Z10 - && s390_contiguous_bitmask_p (INTVAL (operands[2]), - GET_MODE_BITSIZE (<MODE>mode), NULL, NULL) - && INTVAL (operands[2]) == ~(INTVAL (operands[4]))" - -{ - int start; - int size; - - s390_contiguous_bitmask_p (INTVAL (operands[2]), - GET_MODE_BITSIZE (<MODE>mode), &start, &size); - - operands[5] = GEN_INT (64 - start - size); /* start bit position */ - operands[6] = GEN_INT (64 - 1 - start); /* end bit position */ - operands[7] = const0_rtx; /* left shift count */ - - return "risbg\t%0,%1,%b5,%b6,%b7"; -} + "TARGET_Z10 && INTVAL (operands[2]) == ~INTVAL (operands[4])" + "risbg\t%0,%1,%<bfstart>2,%<bfend>2,0" [(set_attr "op_type" "RIE") (set_attr "z10prop" "z10_super_E1")]) @@ -3418,25 +3406,11 @@ (define_insn "*insv<mode>_or_z10_noshift" [(set (match_operand:GPR 0 "nonimmediate_operand" "=d") (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d") - (match_operand 2 "const_int_operand" "n")) + (match_operand:GPR 2 "contiguous_bitmask_operand" "")) (match_operand:GPR 3 "nonimmediate_operand" "0"))) (clobber (reg:CC CC_REGNUM))] - "TARGET_Z10 - && s390_contiguous_bitmask_p (INTVAL (operands[2]), - GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)" -{ - int start; - int size; - - s390_contiguous_bitmask_p (INTVAL (operands[2]), - GET_MODE_BITSIZE (<MODE>mode), &start, &size); - - operands[4] = GEN_INT (64 - start - size); /* start bit position */ - operands[5] = GEN_INT (64 - 1 - start); /* end bit position */ - operands[6] = const0_rtx; /* left shift count */ - - return "rosbg\t%0,%1,%b4,%b5,%b6"; -} + "TARGET_Z10" + "rosbg\t%0,%1,%<bfstart>2,%<bfend>2,0" [(set_attr "op_type" "RIE")]) (define_insn "*insv<mode>_mem_reg" -- 1.7.7.6