summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c71
-rw-r--r--gcc/config/s390/s390.md31
4 files changed, 84 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f6cee36729b..6fc9d8f25ed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,16 @@
2005-07-07 Adrian Straetling <straetling@de.ibm.com>
+
+ * config/s390/s390-protos.h (s390_expand_clrmem): Delete.
+ (s390_expand_setmem): New.
+ * config/s390/s390.c: Likewise.
+ (print_shift_count_operand): Truncate to 12 bits instead of 6.
+ Adapt comments.
+ * config/s390/s390.md: ("setmem<mode>"): Accept character as
+ general_operand. Call new function "s390_expand_setmem".
+ ("clrmem_long", "*clrmem_long"): Rewrite to ...
+ ("setmem_long", "*setmem_long"): ... this.
+
+2005-07-07 Adrian Straetling <straetling@de.ibm.com>
* config/s390/s390.c: (optimization_options): Enable
TARGET_MVCLE at -Os.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 87cf98ed469..7d63c7503e3 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -69,7 +69,7 @@ extern void s390_expand_plus_operand (rtx, rtx, rtx);
extern void emit_symbolic_move (rtx *);
extern void s390_load_address (rtx, rtx);
extern void s390_expand_movmem (rtx, rtx, rtx);
-extern void s390_expand_clrmem (rtx, rtx);
+extern void s390_expand_setmem (rtx, rtx, rtx);
extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern rtx s390_return_addr_rtx (int, rtx);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 07022a2a463..3573db59e41 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3225,25 +3225,49 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
}
}
-/* Emit code to clear LEN bytes at DST. */
+/* Emit code to set LEN bytes at DST to VAL.
+ Make use of clrmem if VAL is zero. */
void
-s390_expand_clrmem (rtx dst, rtx len)
+s390_expand_setmem (rtx dst, rtx len, rtx val)
{
- if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
+ gcc_assert (GET_CODE (len) != CONST_INT || INTVAL (len) > 0);
+ gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
+
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) <= 257)
{
- if (INTVAL (len) > 0)
+ if (val == const0_rtx && INTVAL (len) <= 256)
emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
+ else
+ {
+ /* Initialize memory by storing the first byte. */
+ emit_move_insn (adjust_address (dst, QImode, 0), val);
+
+ if (INTVAL (len) > 1)
+ {
+ /* Initiate 1 byte overlap move.
+ The first byte of DST is propagated through DSTP1.
+ Prepare a movmem for: DST+1 = DST (length = LEN - 1).
+ DST is set to size 1 so the rest of the memory location
+ does not count as source operand. */
+ rtx dstp1 = adjust_address (dst, VOIDmode, 1);
+ set_mem_size (dst, const1_rtx);
+
+ emit_insn (gen_movmem_short (dstp1, dst,
+ GEN_INT (INTVAL (len) - 2)));
+ }
+ }
}
else if (TARGET_MVCLE)
{
- emit_insn (gen_clrmem_long (dst, convert_to_mode (Pmode, len, 1)));
+ val = force_not_mem (convert_modes (Pmode, QImode, val, 1));
+ emit_insn (gen_setmem_long (dst, convert_to_mode (Pmode, len, 1), val));
}
else
{
- rtx dst_addr, src_addr, count, blocks, temp;
+ rtx dst_addr, src_addr, count, blocks, temp, dstp1 = NULL_RTX;
rtx loop_start_label = gen_label_rtx ();
rtx loop_end_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
@@ -3265,7 +3289,22 @@ s390_expand_clrmem (rtx dst, rtx len)
emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
dst = change_address (dst, VOIDmode, dst_addr);
- temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ if (val == const0_rtx)
+ temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ else
+ {
+ dstp1 = adjust_address (dst, VOIDmode, 1);
+ set_mem_size (dst, const1_rtx);
+
+ /* Initialize memory by storing the first byte. */
+ emit_move_insn (adjust_address (dst, QImode, 0), val);
+
+ /* If count is 1 we are done. */
+ emit_cmp_and_jump_insns (count, const1_rtx,
+ EQ, NULL_RTX, mode, 1, end_label);
+
+ temp = expand_binop (mode, add_optab, count, GEN_INT (-2), count, 1, 0);
+ }
if (temp != count)
emit_move_insn (count, temp);
@@ -3278,7 +3317,10 @@ s390_expand_clrmem (rtx dst, rtx len)
emit_label (loop_start_label);
- emit_insn (gen_clrmem_short (dst, GEN_INT (255)));
+ if (val == const0_rtx)
+ emit_insn (gen_clrmem_short (dst, GEN_INT (255)));
+ else
+ emit_insn (gen_movmem_short (dstp1, dst, GEN_INT (255)));
s390_load_address (dst_addr,
gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
@@ -3292,7 +3334,10 @@ s390_expand_clrmem (rtx dst, rtx len)
emit_jump (loop_start_label);
emit_label (loop_end_label);
- emit_insn (gen_clrmem_short (dst, convert_to_mode (Pmode, count, 1)));
+ if (val == const0_rtx)
+ emit_insn (gen_clrmem_short (dst, convert_to_mode (Pmode, count, 1)));
+ else
+ emit_insn (gen_movmem_short (dstp1, dst, convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
}
}
@@ -3637,7 +3682,9 @@ s390_delegitimize_address (rtx orig_x)
return orig_x;
}
-/* Output shift count operand OP to stdio stream FILE. */
+/* Output operand OP to stdio stream FILE.
+ OP is an address (register + offset) which is not used to address data;
+ instead the rightmost bits are interpreted as the value. */
static void
print_shift_count_operand (FILE *file, rtx op)
@@ -3667,8 +3714,8 @@ print_shift_count_operand (FILE *file, rtx op)
gcc_assert (REGNO_REG_CLASS (REGNO (op)) == ADDR_REGS);
}
- /* Shift counts are truncated to the low six bits anyway. */
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & 63);
+ /* Offsets are constricted to twelve bits. */
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & ((1 << 12) - 1));
if (op)
fprintf (file, "(%s)", reg_names[REGNO (op)]);
}
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 8a3e1a41810..6d8c107fa52 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1924,18 +1924,11 @@
(define_expand "setmem<mode>"
[(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand 2 "const_int_operand" ""))
+ (match_operand:QI 2 "general_operand" ""))
(use (match_operand:GPR 1 "general_operand" ""))
(match_operand 3 "" "")]
""
-{
- /* If value to set is not zero, use the library routine. */
- if (operands[2] != const0_rtx)
- FAIL;
-
- s390_expand_clrmem (operands[0], operands[1]);
- DONE;
-})
+ "s390_expand_setmem (operands[0], operands[1], operands[2]); DONE;")
; Clear a block that is up to 256 bytes in length.
; The block length is taken as (operands[1] % 256) + 1.
@@ -2010,15 +2003,15 @@
(clobber (reg:CC CC_REGNUM))])]
"operands[3] = gen_label_rtx ();")
-; Clear a block of arbitrary length.
+; Initialize a block of arbitrary length with (operands[2] % 256).
-(define_expand "clrmem_long"
+(define_expand "setmem_long"
[(parallel
[(clobber (match_dup 1))
(set (match_operand:BLK 0 "memory_operand" "")
- (const_int 0))
+ (match_operand 2 "shift_count_operand" ""))
(use (match_operand 1 "general_operand" ""))
- (use (match_dup 2))
+ (use (match_dup 3))
(clobber (reg:CC CC_REGNUM))])]
""
{
@@ -2036,18 +2029,18 @@
operands[0] = replace_equiv_address_nv (operands[0], addr0);
operands[1] = reg0;
- operands[2] = reg1;
+ operands[3] = reg1;
})
-(define_insn "*clrmem_long"
+(define_insn "*setmem_long"
[(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
- (const_int 0))
- (use (match_dup 2))
+ (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
+ (match_operand 2 "shift_count_operand" "Y"))
+ (use (match_dup 3))
(use (match_operand:<DBL> 1 "register_operand" "d"))
(clobber (reg:CC CC_REGNUM))]
""
- "mvcle\t%0,%1,0\;jo\t.-4"
+ "mvcle\t%0,%1,%Y2\;jo\t.-4"
[(set_attr "length" "8")
(set_attr "type" "vs")])