diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2002-09-16 14:13:12 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2002-09-16 14:13:12 +0000 |
commit | a41c6c533d4b1081fdb453cfa8fa5526af764151 (patch) | |
tree | a83ab7a7dbef43d5e69a4f7b11903ad532081100 /gcc | |
parent | 2a4ecff3cb06cb624dbe48b5d42f60e85dd9506b (diff) | |
download | gcc-a41c6c533d4b1081fdb453cfa8fa5526af764151.zip gcc-a41c6c533d4b1081fdb453cfa8fa5526af764151.tar.gz gcc-a41c6c533d4b1081fdb453cfa8fa5526af764151.tar.bz2 |
s390.c: (legitimize_la_operand): Remove, replace by ...
* config/s390/s390.c: (legitimize_la_operand): Remove, replace by ...
(s390_load_address): ... this new function.
(s390_decompose_address): Allow the argument pointer and all
virtual registers as 'pointer' registers.
(s390_expand_plus_operand): Use s390_load_address.
config/s390/s390.md (movti, movdi, movdf splitters): Likewise.
("force_la_31"): New insn pattern.
config/s390/s390-protos.h (legitimize_la_operand): Remove.
(s390_load_address): Add prototype.
* config/s390/s390.c: Include "optabs.h".
(s390_expand_movstr, s390_expand_clrstr, s390_expand_cmpstr): New.
config/s390/s390-protos.h (s390_expand_movstr, s390_expand_clrstr,
s390_expand_cmpstr): Add prototypes.
config/s390/s390.md ("movstrdi", "movstrsi"): Call s390_expand_movstr.
("movstrdi_short"): Rename to "movstr_short_64". Change predicates
for operands 0 and 1 to "memory_operand". Add type attribute.
("movstrsi_short"): Rename to "movstr_short_31". Change predicates
for operands 0 and 1 to "memory_operand". Add type attribute.
("movstrdi_long", "movstrsi_long"): Remove.
("movstrdi_64"): Rename to "movstr_long_64". Add type attribute.
("movstrsi_31"): Rename to "movstr_long_31". Add type attribute.
("clrstrdi", "clrstrsi"): Call s390_expand_clrstr.
("clrstrsico"): Remove, replace by ...
("clrstr_short_64", "clrstr_short_31"): ... these new patterns.
("clrstrsi_64"): Rename to "clrstr_long_64".
("clrstrsi_31"): Rename to "clrstr_long_31".
("cmpstrdi", "cmpstrsi"): Call s390_expand_cmpstr.
("cmpstr_const"): Remove, replace by ...
("cmpstr_short_64", "cmpstr_short_31"): ... these new patterns.
("cmpstr_64"): Rename to "cmpstr_long_64".
("cmpstr_31"): Rename to "cmpstr_long_31".
From-SVN: r57191
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 5 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 349 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 634 |
4 files changed, 553 insertions, 470 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad15fdf..b961107 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2002-09-16 Ulrich Weigand <uweigand@de.ibm.com> + + * config/s390/s390.c: (legitimize_la_operand): Remove, replace by ... + (s390_load_address): ... this new function. + (s390_decompose_address): Allow the argument pointer and all + virtual registers as 'pointer' registers. + (s390_expand_plus_operand): Use s390_load_address. + config/s390/s390.md (movti, movdi, movdf splitters): Likewise. + ("force_la_31"): New insn pattern. + config/s390/s390-protos.h (legitimize_la_operand): Remove. + (s390_load_address): Add prototype. + + * config/s390/s390.c: Include "optabs.h". + (s390_expand_movstr, s390_expand_clrstr, s390_expand_cmpstr): New. + config/s390/s390-protos.h (s390_expand_movstr, s390_expand_clrstr, + s390_expand_cmpstr): Add prototypes. + config/s390/s390.md ("movstrdi", "movstrsi"): Call s390_expand_movstr. + ("movstrdi_short"): Rename to "movstr_short_64". Change predicates + for operands 0 and 1 to "memory_operand". Add type attribute. + ("movstrsi_short"): Rename to "movstr_short_31". Change predicates + for operands 0 and 1 to "memory_operand". Add type attribute. + ("movstrdi_long", "movstrsi_long"): Remove. + ("movstrdi_64"): Rename to "movstr_long_64". Add type attribute. + ("movstrsi_31"): Rename to "movstr_long_31". Add type attribute. + ("clrstrdi", "clrstrsi"): Call s390_expand_clrstr. + ("clrstrsico"): Remove, replace by ... + ("clrstr_short_64", "clrstr_short_31"): ... these new patterns. + ("clrstrsi_64"): Rename to "clrstr_long_64". + ("clrstrsi_31"): Rename to "clrstr_long_31". + ("cmpstrdi", "cmpstrsi"): Call s390_expand_cmpstr. + ("cmpstr_const"): Remove, replace by ... + ("cmpstr_short_64", "cmpstr_short_31"): ... these new patterns. + ("cmpstr_64"): Rename to "cmpstr_long_64". + ("cmpstr_31"): Rename to "cmpstr_long_31". + 2002-09-16 Kazu Hirata <kazu@cs.umass.edu> * ABOUT-NLS: Follow spelling conventions. diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index c44ffb3..c66207a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -49,7 +49,6 @@ extern enum machine_mode s390_tm_ccmode PARAMS ((rtx, rtx, int)); extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx)); extern int legitimate_la_operand_p PARAMS ((rtx)); -extern rtx legitimize_la_operand PARAMS ((rtx)); extern int legitimate_pic_operand_p PARAMS ((rtx)); extern int legitimate_constant_p PARAMS ((rtx)); extern int legitimate_reload_constant_p PARAMS ((rtx)); @@ -61,6 +60,10 @@ extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, extern int s390_plus_operand PARAMS ((rtx, enum machine_mode)); extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx)); extern void emit_pic_move PARAMS ((rtx *, enum machine_mode)); +extern void s390_load_address PARAMS ((rtx, rtx)); +extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx)); +extern void s390_expand_clrstr PARAMS ((rtx, rtx)); +extern void s390_expand_cmpstr PARAMS ((rtx, rtx, rtx, rtx)); extern void s390_output_symbolic_const PARAMS ((FILE *, rtx)); extern void print_operand_address PARAMS ((FILE *, rtx)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 26c4dd2..549f317 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */ #include "target-def.h" #include "debug.h" #include "langhooks.h" +#include "optabs.h" static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int)); static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int)); @@ -1458,8 +1459,7 @@ s390_expand_plus_operand (target, src, scratch) /* Emit the LOAD ADDRESS pattern. Note that reload of PLUS is only ever performed on addresses, so we can mark the sum as legitimate for LA in any case. */ - src = legitimize_la_operand (src); - emit_insn (gen_rtx_SET (VOIDmode, target, src)); + s390_load_address (target, src); } @@ -1548,6 +1548,9 @@ s390_decompose_address (addr, out) || ((reload_completed || reload_in_progress) && frame_pointer_needed && REGNO (base) == HARD_FRAME_POINTER_REGNUM) + || REGNO (base) == ARG_POINTER_REGNUM + || (REGNO (base) >= FIRST_VIRTUAL_REGISTER + && REGNO (base) <= LAST_VIRTUAL_REGISTER) || (flag_pic && REGNO (base) == PIC_OFFSET_TABLE_REGNUM)) pointer = TRUE; @@ -1573,6 +1576,9 @@ s390_decompose_address (addr, out) || ((reload_completed || reload_in_progress) && frame_pointer_needed && REGNO (indx) == HARD_FRAME_POINTER_REGNUM) + || REGNO (indx) == ARG_POINTER_REGNUM + || (REGNO (indx) >= FIRST_VIRTUAL_REGISTER + && REGNO (indx) <= LAST_VIRTUAL_REGISTER) || (flag_pic && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM)) pointer = TRUE; @@ -1737,30 +1743,19 @@ legitimate_la_operand_p (op) return FALSE; } -/* Return a modified variant of OP that is guaranteed to - be accepted by legitimate_la_operand_p. */ +/* Emit a forced load-address operation to load SRC into DST. + This will use the LOAD ADDRESS instruction even in situations + where legitimate_la_operand_p (SRC) returns false. */ -rtx -legitimize_la_operand (op) - register rtx op; +void +s390_load_address (dst, src) + rtx dst; + rtx src; { - struct s390_address addr; - if (!s390_decompose_address (op, &addr)) - abort (); - - if (TARGET_64BIT || addr.pointer) - return op; - - if (!addr.base) - abort (); - - op = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr.base), 101); - if (addr.indx) - op = gen_rtx_PLUS (Pmode, op, addr.indx); - if (addr.disp) - op = gen_rtx_PLUS (Pmode, op, addr.disp); - - return op; + if (TARGET_64BIT) + emit_move_insn (dst, src); + else + emit_insn (gen_force_la_31 (dst, src)); } /* Return a legitimate reference for ORIG (an address) using the @@ -2148,6 +2143,312 @@ legitimize_address (x, oldx, mode) return x; } +/* Emit code to move LEN bytes from DST to SRC. */ + +void +s390_expand_movstr (dst, src, len) + rtx dst; + rtx src; + rtx len; +{ + rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) = + TARGET_64BIT ? gen_movstr_short_64 : gen_movstr_short_31; + rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) = + TARGET_64BIT ? gen_movstr_long_64 : gen_movstr_long_31; + + + if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256) + { + if (INTVAL (len) > 0) + emit_insn ((*gen_short) (dst, src, GEN_INT (INTVAL (len) - 1))); + } + + else if (TARGET_MVCLE) + { + enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode; + enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode; + rtx reg0 = gen_reg_rtx (double_mode); + rtx reg1 = gen_reg_rtx (double_mode); + + emit_move_insn (gen_highpart (single_mode, reg0), + force_operand (XEXP (dst, 0), NULL_RTX)); + emit_move_insn (gen_highpart (single_mode, reg1), + force_operand (XEXP (src, 0), NULL_RTX)); + + convert_move (gen_lowpart (single_mode, reg0), len, 1); + convert_move (gen_lowpart (single_mode, reg1), len, 1); + + emit_insn ((*gen_long) (reg0, reg1, reg0, reg1)); + } + + else + { + rtx dst_addr, src_addr, count, blocks, temp; + rtx end_label = gen_label_rtx (); + enum machine_mode mode; + tree type; + + mode = GET_MODE (len); + if (mode == VOIDmode) + mode = word_mode; + + type = (*lang_hooks.types.type_for_mode) (mode, 1); + if (!type) + abort (); + + dst_addr = gen_reg_rtx (Pmode); + src_addr = gen_reg_rtx (Pmode); + count = gen_reg_rtx (mode); + blocks = gen_reg_rtx (mode); + + convert_move (count, len, 1); + emit_cmp_and_jump_insns (count, const0_rtx, + EQ, NULL_RTX, mode, 1, end_label); + + emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX)); + emit_move_insn (src_addr, force_operand (XEXP (src, 0), NULL_RTX)); + dst = change_address (dst, VOIDmode, dst_addr); + src = change_address (src, VOIDmode, src_addr); + + temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0); + if (temp != count) + emit_move_insn (count, temp); + + temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_start_loop (1); + expand_exit_loop_top_cond (0, build (NE_EXPR, type, + make_tree (type, blocks), + make_tree (type, const0_rtx))); + + emit_insn ((*gen_short) (dst, src, GEN_INT (255))); + s390_load_address (dst_addr, + gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256))); + s390_load_address (src_addr, + gen_rtx_PLUS (Pmode, src_addr, GEN_INT (256))); + + temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_end_loop (); + + emit_insn ((*gen_short) (dst, src, convert_to_mode (word_mode, count, 1))); + emit_label (end_label); + } +} + +/* Emit code to clear LEN bytes at DST. */ + +void +s390_expand_clrstr (dst, len) + rtx dst; + rtx len; +{ + rtx (*gen_short) PARAMS ((rtx, rtx)) = + TARGET_64BIT ? gen_clrstr_short_64 : gen_clrstr_short_31; + rtx (*gen_long) PARAMS ((rtx, rtx, rtx)) = + TARGET_64BIT ? gen_clrstr_long_64 : gen_clrstr_long_31; + + + if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256) + { + if (INTVAL (len) > 0) + emit_insn ((*gen_short) (dst, GEN_INT (INTVAL (len) - 1))); + } + + else if (TARGET_MVCLE) + { + enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode; + enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode; + rtx reg0 = gen_reg_rtx (double_mode); + rtx reg1 = gen_reg_rtx (double_mode); + + emit_move_insn (gen_highpart (single_mode, reg0), + force_operand (XEXP (dst, 0), NULL_RTX)); + convert_move (gen_lowpart (single_mode, reg0), len, 1); + + emit_move_insn (gen_highpart (single_mode, reg1), const0_rtx); + emit_move_insn (gen_lowpart (single_mode, reg1), const0_rtx); + + emit_insn ((*gen_long) (reg0, reg1, reg0)); + } + + else + { + rtx dst_addr, src_addr, count, blocks, temp; + rtx end_label = gen_label_rtx (); + enum machine_mode mode; + tree type; + + mode = GET_MODE (len); + if (mode == VOIDmode) + mode = word_mode; + + type = (*lang_hooks.types.type_for_mode) (mode, 1); + if (!type) + abort (); + + dst_addr = gen_reg_rtx (Pmode); + src_addr = gen_reg_rtx (Pmode); + count = gen_reg_rtx (mode); + blocks = gen_reg_rtx (mode); + + convert_move (count, len, 1); + emit_cmp_and_jump_insns (count, const0_rtx, + EQ, NULL_RTX, mode, 1, end_label); + + 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 (temp != count) + emit_move_insn (count, temp); + + temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_start_loop (1); + expand_exit_loop_top_cond (0, build (NE_EXPR, type, + make_tree (type, blocks), + make_tree (type, const0_rtx))); + + emit_insn ((*gen_short) (dst, GEN_INT (255))); + s390_load_address (dst_addr, + gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256))); + + temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_end_loop (); + + emit_insn ((*gen_short) (dst, convert_to_mode (word_mode, count, 1))); + emit_label (end_label); + } +} + +/* Emit code to compare LEN bytes at OP0 with those at OP1, + and return the result in TARGET. */ + +void +s390_expand_cmpstr (target, op0, op1, len) + rtx target; + rtx op0; + rtx op1; + rtx len; +{ + rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) = + TARGET_64BIT ? gen_cmpstr_short_64 : gen_cmpstr_short_31; + rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) = + TARGET_64BIT ? gen_cmpstr_long_64 : gen_cmpstr_long_31; + rtx (*gen_result) PARAMS ((rtx)) = + GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si; + + op0 = protect_from_queue (op0, 0); + op1 = protect_from_queue (op1, 0); + len = protect_from_queue (len, 0); + + if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256) + { + if (INTVAL (len) > 0) + { + emit_insn ((*gen_short) (op0, op1, GEN_INT (INTVAL (len) - 1))); + emit_insn ((*gen_result) (target)); + } + else + emit_move_insn (target, const0_rtx); + } + + else if (TARGET_MVCLE) + { + enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode; + enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode; + rtx reg0 = gen_reg_rtx (double_mode); + rtx reg1 = gen_reg_rtx (double_mode); + + emit_move_insn (gen_highpart (single_mode, reg0), + force_operand (XEXP (op0, 0), NULL_RTX)); + emit_move_insn (gen_highpart (single_mode, reg1), + force_operand (XEXP (op1, 0), NULL_RTX)); + + convert_move (gen_lowpart (single_mode, reg0), len, 1); + convert_move (gen_lowpart (single_mode, reg1), len, 1); + + emit_insn ((*gen_long) (reg0, reg1, reg0, reg1)); + emit_insn ((*gen_result) (target)); + } + + else + { + rtx addr0, addr1, count, blocks, temp; + rtx end_label = gen_label_rtx (); + enum machine_mode mode; + tree type; + + mode = GET_MODE (len); + if (mode == VOIDmode) + mode = word_mode; + + type = (*lang_hooks.types.type_for_mode) (mode, 1); + if (!type) + abort (); + + addr0 = gen_reg_rtx (Pmode); + addr1 = gen_reg_rtx (Pmode); + count = gen_reg_rtx (mode); + blocks = gen_reg_rtx (mode); + + convert_move (count, len, 1); + emit_cmp_and_jump_insns (count, const0_rtx, + EQ, NULL_RTX, mode, 1, end_label); + + emit_move_insn (addr0, force_operand (XEXP (op0, 0), NULL_RTX)); + emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX)); + op0 = change_address (op0, VOIDmode, addr0); + op1 = change_address (op1, VOIDmode, addr1); + + temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0); + if (temp != count) + emit_move_insn (count, temp); + + temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_start_loop (1); + expand_exit_loop_top_cond (0, build (NE_EXPR, type, + make_tree (type, blocks), + make_tree (type, const0_rtx))); + + emit_insn ((*gen_short) (op0, op1, GEN_INT (255))); + temp = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCSmode, 33), const0_rtx); + temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp, + gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx); + temp = gen_rtx_SET (VOIDmode, pc_rtx, temp); + emit_jump_insn (temp); + + s390_load_address (addr0, + gen_rtx_PLUS (Pmode, addr0, GEN_INT (256))); + s390_load_address (addr1, + gen_rtx_PLUS (Pmode, addr1, GEN_INT (256))); + + temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0); + if (temp != blocks) + emit_move_insn (blocks, temp); + + expand_end_loop (); + + emit_insn ((*gen_short) (op0, op1, convert_to_mode (word_mode, count, 1))); + emit_label (end_label); + + emit_insn ((*gen_result) (target)); + } +} + /* In the name of slightly smaller debug output, and to cater to general assembler losage, recognize various UNSPEC sequences and turn them back into a direct symbol reference. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 418165c..1007584 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -832,10 +832,13 @@ (match_operand:TI 1 "memory_operand" ""))] "TARGET_64BIT && reload_completed && !s_operand (operands[1], VOIDmode)" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 0) (mem:TI (match_dup 2)))] - "operands[2] = operand_subword (operands[0], 1, 0, TImode); - operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") + [(set (match_dup 0) (match_dup 1))] + " +{ + rtx addr = operand_subword (operands[0], 1, 0, TImode); + s390_load_address (addr, XEXP (operands[1], 0)); + operands[1] = replace_equiv_address (operands[1], addr); +}") ; ; movdi instruction pattern(s). @@ -981,10 +984,13 @@ && !fp_operand (operands[0], VOIDmode) && !fp_operand (operands[1], VOIDmode) && !s_operand (operands[1], VOIDmode)" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 0) (mem:DI (match_dup 2)))] - "operands[2] = operand_subword (operands[0], 1, 0, DImode); - operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") + [(set (match_dup 0) (match_dup 1))] + " +{ + rtx addr = operand_subword (operands[0], 1, 0, DImode); + s390_load_address (addr, XEXP (operands[1], 0)); + operands[1] = replace_equiv_address (operands[1], addr); +}") ; ; movsi instruction pattern(s). @@ -1254,10 +1260,13 @@ && !fp_operand (operands[0], VOIDmode) && !fp_operand (operands[1], VOIDmode) && !s_operand (operands[1], VOIDmode)" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 0) (mem:DI (match_dup 2)))] - "operands[2] = operand_subword (operands[0], 1, 0, DFmode); - operands[3] = legitimize_la_operand (XEXP (operands[1], 0));") + [(set (match_dup 0) (match_dup 1))] + " +{ + rtx addr = operand_subword (operands[0], 1, 0, DFmode); + s390_load_address (addr, XEXP (operands[1], 0)); + operands[1] = replace_equiv_address (operands[1], addr); +}") ; ; movsf instruction pattern(s). @@ -1503,172 +1512,31 @@ ;; ; -; movstrdi instruction pattern(s). +; movstrM instruction pattern(s). ; (define_expand "movstrdi" - [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:DI 2 "general_operand" "")) - (match_operand 3 "" "")] - "TARGET_64BIT" - " -{ - rtx addr0, addr1; - - addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX); - addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX); - - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256) - { - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); - operands[2] = GEN_INT (INTVAL (operands[2]) - 1); - - emit_insn (gen_movstrdi_short (operands[0], operands[1], operands[2])); - DONE; - } - else - { - if (TARGET_MVCLE) - { - /* implementation suggested by Richard Henderson <rth@cygnus.com> */ - rtx reg0 = gen_reg_rtx (TImode); - rtx reg1 = gen_reg_rtx (TImode); - rtx len = operands[2]; - - if (! CONSTANT_P (len)) - len = force_reg (DImode, len); - - /* Load up the address+length pairs. */ - - emit_move_insn (gen_highpart (DImode, reg0), addr0); - emit_move_insn (gen_lowpart (DImode, reg0), len); - - emit_move_insn (gen_highpart (DImode, reg1), addr1); - emit_move_insn (gen_lowpart (DImode, reg1), len); - - /* MOVE */ - emit_insn (gen_movstrdi_64 (reg0, reg1, reg0, reg1)); - DONE; - } - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - rtx reg0, reg1, len, blocks; - - reg0 = gen_reg_rtx (DImode); - reg1 = gen_reg_rtx (DImode); - len = gen_reg_rtx (DImode); - blocks = gen_reg_rtx (DImode); - - emit_move_insn (len, operands[2]); - emit_insn (gen_cmpdi (len, const0_rtx)); - emit_jump_insn (gen_beq (label1)); - emit_move_insn (reg0, addr0); - emit_move_insn (reg1, addr1); - emit_insn (gen_adddi3 (len, len, constm1_rtx)); - emit_insn (gen_ashrdi3 (blocks, len, GEN_INT (8))); - emit_insn (gen_cmpdi (blocks, const0_rtx)); - emit_jump_insn (gen_beq (label2)); - emit_insn (gen_movstrdi_long (reg0, reg1, reg0, reg1, blocks, blocks)); - emit_label (label2); - operands[0] = change_address (operands[0], VOIDmode, reg0); - operands[1] = change_address (operands[1], VOIDmode, reg1); - emit_insn (gen_movstrdi_short (operands[0], operands[1], len)); - emit_label (label1); - DONE; - } - } -}") - -; -; movstrsi instruction pattern(s). -; + [(set (match_operand:BLK 0 "memory_operand" "") + (match_operand:BLK 1 "memory_operand" "")) + (use (match_operand:DI 2 "general_operand" "")) + (match_operand 3 "" "")] + "TARGET_64BIT" + "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;") (define_expand "movstrsi" - [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:SI 2 "general_operand" "")) - (match_operand 3 "" "")] - "!TARGET_64BIT" - " -{ - rtx addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX); - rtx addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX); - - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256) - { - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); - operands[2] = GEN_INT (INTVAL (operands[2]) - 1); - - emit_insn (gen_movstrsi_short (operands[0], operands[1], operands[2])); - DONE; - } - else - { - if (TARGET_MVCLE) - { - /* implementation suggested by Richard Henderson <rth@cygnus.com> */ - rtx reg0 = gen_reg_rtx (DImode); - rtx reg1 = gen_reg_rtx (DImode); - rtx len = operands[2]; - - - if (! CONSTANT_P (len)) - len = force_reg (SImode, len); - - /* Load up the address+length pairs. */ - - emit_move_insn (gen_highpart (SImode, reg0), addr0); - emit_move_insn (gen_lowpart (SImode, reg0), len); - - emit_move_insn (gen_highpart (SImode, reg1), addr1); - emit_move_insn (gen_lowpart (SImode, reg1), len); - - /* MOVE */ - emit_insn (gen_movstrsi_31 (reg0, reg1, reg0, reg1)); - DONE; - } - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - rtx reg0, reg1, len, blocks; - - reg0 = gen_reg_rtx (SImode); - reg1 = gen_reg_rtx (SImode); - len = gen_reg_rtx (SImode); - blocks = gen_reg_rtx (SImode); - - emit_move_insn (len, operands[2]); - emit_insn (gen_cmpsi (len, const0_rtx)); - emit_jump_insn (gen_beq (label1)); - emit_move_insn (reg0, addr0); - emit_move_insn (reg1, addr1); - emit_insn (gen_addsi3 (len, len, constm1_rtx)); - emit_insn (gen_ashrsi3 (blocks, len, GEN_INT (8))); - emit_insn (gen_cmpsi (blocks, const0_rtx)); - emit_jump_insn (gen_beq (label2)); - emit_insn (gen_movstrsi_long (reg0, reg1, reg0, reg1, blocks, blocks)); - emit_label (label2); - operands[0] = change_address (operands[0], VOIDmode, reg0); - operands[1] = change_address (operands[1], VOIDmode, reg1); - emit_insn (gen_movstrsi_short (operands[0], operands[1], len)); - emit_label (label1); - DONE; - } - } -}") + [(set (match_operand:BLK 0 "memory_operand" "") + (match_operand:BLK 1 "memory_operand" "")) + (use (match_operand:SI 2 "general_operand" "")) + (match_operand 3 "" "")] + "" + "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;") ; Move a block that is up to 256 bytes in length. ; The block length is taken as (operands[2] % 256) + 1. -(define_insn "movstrdi_short" - [(set (match_operand:BLK 0 "s_operand" "=Q,Q") - (match_operand:BLK 1 "s_operand" "Q,Q")) +(define_insn "movstr_short_64" + [(set (match_operand:BLK 0 "memory_operand" "=Q,Q") + (match_operand:BLK 1 "memory_operand" "Q,Q")) (use (match_operand:DI 2 "nonmemory_operand" "n,a")) (clobber (match_scratch:DI 3 "=X,&a"))] "TARGET_64BIT" @@ -1689,12 +1557,13 @@ } }" [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") (set_attr "atype" "mem,mem") (set_attr "length" "*,14")]) -(define_insn "movstrsi_short" - [(set (match_operand:BLK 0 "s_operand" "=Q,Q") - (match_operand:BLK 1 "s_operand" "Q,Q")) +(define_insn "movstr_short_31" + [(set (match_operand:BLK 0 "memory_operand" "=Q,Q") + (match_operand:BLK 1 "memory_operand" "Q,Q")) (use (match_operand:SI 2 "nonmemory_operand" "n,a")) (clobber (match_scratch:SI 3 "=X,&a"))] "!TARGET_64BIT" @@ -1715,64 +1584,13 @@ } }" [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") (set_attr "atype" "mem,mem") (set_attr "length" "*,14")]) -; Move a block that is a multiple of 256 bytes in length +; Move a block of arbitrary length. -(define_insn "movstrdi_long" - [(set (match_operand:DI 4 "register_operand" "=d") - (const_int 0)) - (set (match_operand:DI 0 "register_operand" "=a") - (plus:DI (match_operand:DI 2 "register_operand" "0") - (ashift:DI (match_operand:DI 5 "register_operand" "4") - (const_int 8)))) - (set (match_operand:DI 1 "register_operand" "=a") - (plus:DI (match_operand:DI 3 "register_operand" "1") - (ashift:DI (match_dup 5) (const_int 8)))) - (set (mem:BLK (match_dup 2)) - (mem:BLK (match_dup 3))) - (use (match_dup 5))] - "TARGET_64BIT" - "* -{ - output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands); - output_asm_insn (\"la\\t%0,256(%0)\", operands); - output_asm_insn (\"la\\t%1,256(%1)\", operands); - return \"brct\\t%4,.-14\"; -}" - [(set_attr "op_type" "NN") - (set_attr "atype" "mem") - (set_attr "length" "18")]) - -(define_insn "movstrsi_long" - [(set (match_operand:SI 4 "register_operand" "=d") - (const_int 0)) - (set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 2 "register_operand" "0") - (ashift:SI (match_operand:SI 5 "register_operand" "4") - (const_int 8)))) - (set (match_operand:SI 1 "register_operand" "=a") - (plus:SI (match_operand:SI 3 "register_operand" "1") - (ashift:SI (match_dup 5) (const_int 8)))) - (set (mem:BLK (match_dup 2)) - (mem:BLK (match_dup 3))) - (use (match_dup 5))] - "!TARGET_64BIT" - "* -{ - output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands); - output_asm_insn (\"la\\t%0,256(%0)\", operands); - output_asm_insn (\"la\\t%1,256(%1)\", operands); - return \"brct\\t%4,.-14\"; -}" - [(set_attr "op_type" "NN") - (set_attr "atype" "mem") - (set_attr "length" "18")]) - -; Move a block that is larger than 255 bytes in length. - -(define_insn "movstrdi_64" +(define_insn "movstr_long_64" [(set (match_operand:TI 0 "register_operand" "=d") (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0") (lshiftrt:TI (match_dup 2) (const_int 64))) @@ -1787,10 +1605,11 @@ "TARGET_64BIT" "mvcle\\t%0,%1,0\;jo\\t.-4" [(set_attr "op_type" "NN") + (set_attr "type" "vs") (set_attr "atype" "mem") (set_attr "length" "8")]) -(define_insn "movstrsi_31" +(define_insn "movstr_long_31" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0") (lshiftrt:DI (match_dup 2) (const_int 32))) @@ -1804,112 +1623,93 @@ (clobber (reg:CC 33))] "!TARGET_64BIT" "mvcle\\t%0,%1,0\;jo\\t.-4" - [(set_attr "op_type" "NN") - (set_attr "atype" "mem") - (set_attr "length" "8")]) + [(set_attr "op_type" "NN") + (set_attr "type" "vs") + (set_attr "atype" "mem") + (set_attr "length" "8")]) ; -; clrstrdi instruction pattern(s). +; clrstrM instruction pattern(s). ; (define_expand "clrstrdi" - [(set (match_operand:BLK 0 "general_operand" "") + [(set (match_operand:BLK 0 "memory_operand" "") (const_int 0)) (use (match_operand:DI 1 "general_operand" "")) (match_operand 2 "" "")] "TARGET_64BIT" - " -{ - rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX); - - operands[0] = change_address (operands[0], VOIDmode, addr); - - if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256) - { - emit_insn (gen_clrstrsico (operands[0], operands[1])); - DONE; - } - else - { - rtx reg0 = gen_reg_rtx (TImode); - rtx reg1 = gen_reg_rtx (TImode); - rtx len = operands[1]; - - if (! CONSTANT_P (len)) - len = force_reg (DImode, len); - - /* Load up the address+length pairs. */ - - emit_move_insn (gen_highpart (DImode, reg0), addr); - emit_move_insn (gen_lowpart (DImode, reg0), len); - - emit_move_insn (gen_lowpart (DImode, reg1), const0_rtx); - - /* Clear! */ - emit_insn (gen_clrstrsi_64 (reg0, reg1, reg0)); - DONE; - } -}") - -; -; clrstrsi instruction pattern(s). -; + "s390_expand_clrstr (operands[0], operands[1]); DONE;") (define_expand "clrstrsi" - [(set (match_operand:BLK 0 "general_operand" "") + [(set (match_operand:BLK 0 "memory_operand" "") (const_int 0)) (use (match_operand:SI 1 "general_operand" "")) (match_operand 2 "" "")] - "!TARGET_64BIT" - " -{ - rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX); - - operands[0] = change_address (operands[0], VOIDmode, addr); - - if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256) - { - emit_insn (gen_clrstrsico (operands[0], operands[1])); - DONE; - } - else - { - rtx reg0 = gen_reg_rtx (DImode); - rtx reg1 = gen_reg_rtx (DImode); - rtx len = operands[1]; - - if (! CONSTANT_P (len)) - len = force_reg (SImode, len); + "" + "s390_expand_clrstr (operands[0], operands[1]); DONE;") - /* Load up the address+length pairs. */ +; Clear a block that is up to 256 bytes in length. +; The block length is taken as (operands[2] % 256) + 1. - emit_move_insn (gen_highpart (SImode, reg0), addr); - emit_move_insn (gen_lowpart (SImode, reg0), len); +(define_insn "clrstr_short_64" + [(set (match_operand:BLK 0 "memory_operand" "=Q,Q") + (const_int 0)) + (use (match_operand:DI 1 "nonmemory_operand" "n,a")) + (clobber (match_scratch:DI 2 "=X,&a")) + (clobber (reg:CC 33))] + "TARGET_64BIT" + "* +{ + switch (which_alternative) + { + case 0: + return \"xc\\t%O0(%b1+1,%R0),%0\"; - emit_move_insn (gen_lowpart (SImode, reg1), const0_rtx); - - /* CLear! */ - emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0)); - DONE; - } -}") + case 1: + output_asm_insn (\"bras\\t%2,.+10\", operands); + output_asm_insn (\"xc\\t%O0(1,%R0),%0\", operands); + return \"ex\\t%1,0(%2)\"; -; Clear memory with length less than 256 bytes + default: + abort (); + } +}" + [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") + (set_attr "atype" "mem,mem") + (set_attr "length" "*,14")]) -(define_insn "clrstrsico" - [(set (match_operand:BLK 0 "s_operand" "=Q") +(define_insn "clrstr_short_31" + [(set (match_operand:BLK 0 "memory_operand" "=Q,Q") (const_int 0)) - (use (match_operand 1 "immediate_operand" "I")) + (use (match_operand:SI 1 "nonmemory_operand" "n,a")) + (clobber (match_scratch:SI 2 "=X,&a")) (clobber (reg:CC 33))] - "" - "xc\\t%O0(%1,%R0),%0" - [(set_attr "op_type" "RS") - (set_attr "type" "cs") - (set_attr "atype" "mem")]) + "!TARGET_64BIT" + "* +{ + switch (which_alternative) + { + case 0: + return \"xc\\t%O0(%b1+1,%R0),%0\"; + + case 1: + output_asm_insn (\"bras\\t%2,.+10\", operands); + output_asm_insn (\"xc\\t%O0(1,%R0),%0\", operands); + return \"ex\\t%1,0(%2)\"; + + default: + abort (); + } +}" + [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") + (set_attr "atype" "mem,mem") + (set_attr "length" "*,14")]) -; Clear memory with length greater 256 bytes or lenght not constant +; Clear a block of arbitrary length. -(define_insn "clrstrsi_64" +(define_insn "clrstr_long_64" [(set (match_operand:TI 0 "register_operand" "=d") (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0") (lshiftrt:TI (match_dup 2) (const_int 64))) @@ -1925,7 +1725,7 @@ (set_attr "type" "vs") (set_attr "length" "8")]) -(define_insn "clrstrsi_31" +(define_insn "clrstr_long_31" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0") (lshiftrt:DI (match_dup 2) (const_int 32))) @@ -1942,157 +1742,91 @@ (set_attr "length" "8")]) ; -; cmpstrdi instruction pattern(s). +; cmpstrM instruction pattern(s). ; (define_expand "cmpstrdi" - [(set (match_operand:DI 0 "register_operand" "") - (compare:DI (match_operand:BLK 1 "general_operand" "") - (match_operand:BLK 2 "general_operand" "") ) ) - (use (match_operand:DI 3 "general_operand" "")) - (use (match_operand:DI 4 "" ""))] - "TARGET_64BIT" - " -{ - rtx addr0, addr1; + [(set (match_operand:DI 0 "register_operand" "") + (compare:DI (match_operand:BLK 1 "memory_operand" "") + (match_operand:BLK 2 "memory_operand" "") ) ) + (use (match_operand:DI 3 "general_operand" "")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "s390_expand_cmpstr (operands[0], operands[1], + operands[2], operands[3]); DONE;") - /* for pre/post increment */ - operands[1] = protect_from_queue (operands[1], 0); - operands[2] = protect_from_queue (operands[2], 0); - operands[3] = protect_from_queue (operands[3], 0); +(define_expand "cmpstrsi" + [(set (match_operand:SI 0 "register_operand" "") + (compare:SI (match_operand:BLK 1 "memory_operand" "") + (match_operand:BLK 2 "memory_operand" "") ) ) + (use (match_operand:SI 3 "general_operand" "")) + (use (match_operand:SI 4 "" ""))] + "" + "s390_expand_cmpstr (operands[0], operands[1], + operands[2], operands[3]); DONE;") - addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX); - addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX); +; Compare a block that is up to 256 bytes in length. +; The block length is taken as (operands[2] % 256) + 1. - if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256) +(define_insn "cmpstr_short_64" + [(set (reg:CCS 33) + (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") + (match_operand:BLK 1 "memory_operand" "Q,Q"))) + (use (match_operand:DI 2 "nonmemory_operand" "n,a")) + (clobber (match_scratch:DI 3 "=X,&a"))] + "TARGET_64BIT" + "* +{ + switch (which_alternative) { - if (INTVAL (operands[3]) == 0) { - emit_move_insn (operands[0], operands[3]); - DONE; - } - - operands[1] = change_address (operands[1], VOIDmode, addr0); - operands[2] = change_address (operands[2], VOIDmode, addr1); - - emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3])); - emit_insn (gen_cmpint_di (operands[0])); - DONE; - } - else - { - /* implementation suggested by Richard Henderson <rth@cygnus.com> */ - rtx reg0 = gen_reg_rtx (TImode); - rtx reg1 = gen_reg_rtx (TImode); - rtx len = operands[3]; - - if (! CONSTANT_P (len)) - len = force_reg (DImode, len); - - /* Load up the address+length pairs. */ - emit_move_insn (gen_highpart (DImode, reg0), addr0); - emit_move_insn (gen_lowpart (DImode, reg0), len); + case 0: + return \"clc\\t%O0(%b2+1,%R0),%1\"; - emit_move_insn (gen_highpart (DImode, reg1), addr1); - emit_move_insn (gen_lowpart (DImode, reg1), len); + case 1: + output_asm_insn (\"bras\\t%3,.+10\", operands); + output_asm_insn (\"clc\\t%O0(1,%R0),%1\", operands); + return \"ex\\t%2,0(%3)\"; - /* Compare! */ - emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1)); - emit_insn (gen_cmpint_di (operands[0])); - DONE; + default: + abort (); } -}") - -; -; cmpstrsi instruction pattern(s). -; +}" + [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") + (set_attr "atype" "mem,mem") + (set_attr "length" "*,14")]) -(define_expand "cmpstrsi" - [(set (match_operand:SI 0 "register_operand" "") - (compare:SI (match_operand:BLK 1 "general_operand" "") - (match_operand:BLK 2 "general_operand" "") ) ) - (use (match_operand:SI 3 "general_operand" "")) - (use (match_operand:SI 4 "" ""))] - "" - " +(define_insn "cmpstr_short_31" + [(set (reg:CCS 33) + (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") + (match_operand:BLK 1 "memory_operand" "Q,Q"))) + (use (match_operand:SI 2 "nonmemory_operand" "n,a")) + (clobber (match_scratch:SI 3 "=X,&a"))] + "!TARGET_64BIT" + "* { - rtx addr0, addr1; - - /* for pre/post increment */ - operands[1] = protect_from_queue (operands[1], 0); - operands[2] = protect_from_queue (operands[2], 0); - operands[3] = protect_from_queue (operands[3], 0); - - addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX); - addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX); - - if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256) + switch (which_alternative) { - if (INTVAL (operands[3]) == 0) { - emit_move_insn (operands[0], operands[3]); - DONE; - } - - operands[1] = change_address (operands[1], VOIDmode, addr0); - operands[2] = change_address (operands[2], VOIDmode, addr1); - - emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3])); - emit_insn (gen_cmpint_si (operands[0])); - DONE; - } - else - { - /* implementation suggested by Richard Henderson <rth@cygnus.com> */ - rtx reg0, reg1; - rtx len = operands[3]; - - if (TARGET_64BIT) - { - reg0 = gen_reg_rtx (TImode); - reg1 = gen_reg_rtx (TImode); - } - else - { - reg0 = gen_reg_rtx (DImode); - reg1 = gen_reg_rtx (DImode); - } - - if (! CONSTANT_P (len)) - len = force_reg (Pmode, len); - - /* Load up the address+length pairs. */ - emit_move_insn (gen_highpart (Pmode, reg0), addr0); - emit_move_insn (gen_lowpart (Pmode, reg0), len); - - emit_move_insn (gen_highpart (Pmode, reg1), addr1); - emit_move_insn (gen_lowpart (Pmode, reg1), len); + case 0: + return \"clc\\t%O0(%b2+1,%R0),%1\"; - /* Compare! */ - if (TARGET_64BIT) - emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1)); - else - emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1)); + case 1: + output_asm_insn (\"bras\\t%3,.+10\", operands); + output_asm_insn (\"clc\\t%O0(1,%R0),%1\", operands); + return \"ex\\t%2,0(%3)\"; - emit_insn (gen_cmpint_si (operands[0])); - DONE; + default: + abort (); } -}") - -; Compare a block that is less than 256 bytes in length. - -(define_insn "cmpstr_const" - [(set (reg:CCS 33) - (compare:CCS (match_operand:BLK 0 "s_operand" "Q") - (match_operand:BLK 1 "s_operand" "Q"))) - (use (match_operand 2 "immediate_operand" "I"))] - "(unsigned) INTVAL (operands[2]) < 256" - "clc\\t%O0(%c2,%R0),%1" - [(set_attr "op_type" "SS") - (set_attr "atype" "mem") - (set_attr "type" "cs")]) +}" + [(set_attr "op_type" "SS,NN") + (set_attr "type" "cs,cs") + (set_attr "atype" "mem,mem") + (set_attr "length" "*,14")]) -; Compare a block that is larger than 255 bytes in length. +; Compare a block of arbitrary length. -(define_insn "cmpstr_64" +(define_insn "cmpstr_long_64" [(clobber (match_operand:TI 0 "register_operand" "=d")) (clobber (match_operand:TI 1 "register_operand" "=d")) (set (reg:CCS 33) @@ -2106,7 +1840,7 @@ (set_attr "atype" "mem") (set_attr "type" "vs")]) -(define_insn "cmpstr_31" +(define_insn "cmpstr_long_31" [(clobber (match_operand:DI 0 "register_operand" "=d")) (clobber (match_operand:DI 1 "register_operand" "=d")) (set (reg:CCS 33) @@ -3372,6 +3106,16 @@ (set_attr "atype" "mem") (set_attr "type" "la")]) +(define_insn "force_la_31" + [(set (match_operand:SI 0 "register_operand" "=d") + (match_operand:QI 1 "address_operand" "p")) + (use (const_int 0))] + "!TARGET_64BIT" + "la\\t%0,%a1" + [(set_attr "op_type" "RX") + (set_attr "atype" "mem") + (set_attr "type" "la")]) + (define_expand "reload_insi" [(parallel [(match_operand:SI 0 "register_operand" "=a") (match_operand:SI 1 "s390_plus_operand" "") |