Commit a41c6c53 by Ulrich Weigand Committed by Ulrich Weigand

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
parent 2a4ecff3
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> 2002-09-16 Kazu Hirata <kazu@cs.umass.edu>
* ABOUT-NLS: Follow spelling conventions. * ABOUT-NLS: Follow spelling conventions.
......
...@@ -49,7 +49,6 @@ extern enum machine_mode s390_tm_ccmode PARAMS ((rtx, rtx, int)); ...@@ -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 enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
extern int symbolic_reference_mentioned_p PARAMS ((rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx));
extern int legitimate_la_operand_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_pic_operand_p PARAMS ((rtx));
extern int legitimate_constant_p PARAMS ((rtx)); extern int legitimate_constant_p PARAMS ((rtx));
extern int legitimate_reload_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, ...@@ -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 int s390_plus_operand PARAMS ((rtx, enum machine_mode));
extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx)); extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
extern void emit_pic_move PARAMS ((rtx *, enum machine_mode)); 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 s390_output_symbolic_const PARAMS ((FILE *, rtx));
extern void print_operand_address PARAMS ((FILE *, rtx)); extern void print_operand_address PARAMS ((FILE *, rtx));
......
...@@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */
#include "target-def.h" #include "target-def.h"
#include "debug.h" #include "debug.h"
#include "langhooks.h" #include "langhooks.h"
#include "optabs.h"
static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int)); static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int));
static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int)); static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int));
...@@ -1458,8 +1459,7 @@ s390_expand_plus_operand (target, src, scratch) ...@@ -1458,8 +1459,7 @@ s390_expand_plus_operand (target, src, scratch)
/* Emit the LOAD ADDRESS pattern. Note that reload of PLUS /* Emit the LOAD ADDRESS pattern. Note that reload of PLUS
is only ever performed on addresses, so we can mark the is only ever performed on addresses, so we can mark the
sum as legitimate for LA in any case. */ sum as legitimate for LA in any case. */
src = legitimize_la_operand (src); s390_load_address (target, src);
emit_insn (gen_rtx_SET (VOIDmode, target, src));
} }
...@@ -1548,6 +1548,9 @@ s390_decompose_address (addr, out) ...@@ -1548,6 +1548,9 @@ s390_decompose_address (addr, out)
|| ((reload_completed || reload_in_progress) || ((reload_completed || reload_in_progress)
&& frame_pointer_needed && frame_pointer_needed
&& REGNO (base) == HARD_FRAME_POINTER_REGNUM) && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
|| REGNO (base) == ARG_POINTER_REGNUM
|| (REGNO (base) >= FIRST_VIRTUAL_REGISTER
&& REGNO (base) <= LAST_VIRTUAL_REGISTER)
|| (flag_pic || (flag_pic
&& REGNO (base) == PIC_OFFSET_TABLE_REGNUM)) && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE; pointer = TRUE;
...@@ -1573,6 +1576,9 @@ s390_decompose_address (addr, out) ...@@ -1573,6 +1576,9 @@ s390_decompose_address (addr, out)
|| ((reload_completed || reload_in_progress) || ((reload_completed || reload_in_progress)
&& frame_pointer_needed && frame_pointer_needed
&& REGNO (indx) == HARD_FRAME_POINTER_REGNUM) && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
|| REGNO (indx) == ARG_POINTER_REGNUM
|| (REGNO (indx) >= FIRST_VIRTUAL_REGISTER
&& REGNO (indx) <= LAST_VIRTUAL_REGISTER)
|| (flag_pic || (flag_pic
&& REGNO (indx) == PIC_OFFSET_TABLE_REGNUM)) && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE; pointer = TRUE;
...@@ -1737,30 +1743,19 @@ legitimate_la_operand_p (op) ...@@ -1737,30 +1743,19 @@ legitimate_la_operand_p (op)
return FALSE; return FALSE;
} }
/* Return a modified variant of OP that is guaranteed to /* Emit a forced load-address operation to load SRC into DST.
be accepted by legitimate_la_operand_p. */ This will use the LOAD ADDRESS instruction even in situations
where legitimate_la_operand_p (SRC) returns false. */
rtx void
legitimize_la_operand (op) s390_load_address (dst, src)
register rtx op; rtx dst;
rtx src;
{ {
struct s390_address addr; if (TARGET_64BIT)
if (!s390_decompose_address (op, &addr)) emit_move_insn (dst, src);
abort (); else
emit_insn (gen_force_la_31 (dst, src));
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;
} }
/* Return a legitimate reference for ORIG (an address) using the /* Return a legitimate reference for ORIG (an address) using the
...@@ -2148,6 +2143,312 @@ legitimize_address (x, oldx, mode) ...@@ -2148,6 +2143,312 @@ legitimize_address (x, oldx, mode)
return x; 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 /* In the name of slightly smaller debug output, and to cater to
general assembler losage, recognize various UNSPEC sequences general assembler losage, recognize various UNSPEC sequences
and turn them back into a direct symbol reference. */ and turn them back into a direct symbol reference. */
......
...@@ -832,10 +832,13 @@ ...@@ -832,10 +832,13 @@
(match_operand:TI 1 "memory_operand" ""))] (match_operand:TI 1 "memory_operand" ""))]
"TARGET_64BIT && reload_completed "TARGET_64BIT && reload_completed
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 2) (match_dup 3)) [(set (match_dup 0) (match_dup 1))]
(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));") 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). ; movdi instruction pattern(s).
...@@ -981,10 +984,13 @@ ...@@ -981,10 +984,13 @@
&& !fp_operand (operands[0], VOIDmode) && !fp_operand (operands[0], VOIDmode)
&& !fp_operand (operands[1], VOIDmode) && !fp_operand (operands[1], VOIDmode)
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 2) (match_dup 3)) [(set (match_dup 0) (match_dup 1))]
(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));") 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). ; movsi instruction pattern(s).
...@@ -1254,10 +1260,13 @@ ...@@ -1254,10 +1260,13 @@
&& !fp_operand (operands[0], VOIDmode) && !fp_operand (operands[0], VOIDmode)
&& !fp_operand (operands[1], VOIDmode) && !fp_operand (operands[1], VOIDmode)
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 2) (match_dup 3)) [(set (match_dup 0) (match_dup 1))]
(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));") 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). ; movsf instruction pattern(s).
...@@ -1503,172 +1512,31 @@ ...@@ -1503,172 +1512,31 @@
;; ;;
; ;
; movstrdi instruction pattern(s). ; movstrM instruction pattern(s).
; ;
(define_expand "movstrdi" (define_expand "movstrdi"
[(set (match_operand:BLK 0 "general_operand" "") [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "general_operand" "")) (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:DI 2 "general_operand" "")) (use (match_operand:DI 2 "general_operand" ""))
(match_operand 3 "" "")] (match_operand 3 "" "")]
"TARGET_64BIT" "TARGET_64BIT"
" "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
{
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).
;
(define_expand "movstrsi" (define_expand "movstrsi"
[(set (match_operand:BLK 0 "general_operand" "") [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "general_operand" "")) (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "general_operand" "")) (use (match_operand:SI 2 "general_operand" ""))
(match_operand 3 "" "")] (match_operand 3 "" "")]
"!TARGET_64BIT" ""
" "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
{
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;
}
}
}")
; Move a block that is up to 256 bytes in length. ; Move a block that is up to 256 bytes in length.
; The block length is taken as (operands[2] % 256) + 1. ; The block length is taken as (operands[2] % 256) + 1.
(define_insn "movstrdi_short" (define_insn "movstr_short_64"
[(set (match_operand:BLK 0 "s_operand" "=Q,Q") [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 1 "s_operand" "Q,Q")) (match_operand:BLK 1 "memory_operand" "Q,Q"))
(use (match_operand:DI 2 "nonmemory_operand" "n,a")) (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:DI 3 "=X,&a"))] (clobber (match_scratch:DI 3 "=X,&a"))]
"TARGET_64BIT" "TARGET_64BIT"
...@@ -1689,12 +1557,13 @@ ...@@ -1689,12 +1557,13 @@
} }
}" }"
[(set_attr "op_type" "SS,NN") [(set_attr "op_type" "SS,NN")
(set_attr "type" "cs,cs")
(set_attr "atype" "mem,mem") (set_attr "atype" "mem,mem")
(set_attr "length" "*,14")]) (set_attr "length" "*,14")])
(define_insn "movstrsi_short" (define_insn "movstr_short_31"
[(set (match_operand:BLK 0 "s_operand" "=Q,Q") [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 1 "s_operand" "Q,Q")) (match_operand:BLK 1 "memory_operand" "Q,Q"))
(use (match_operand:SI 2 "nonmemory_operand" "n,a")) (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:SI 3 "=X,&a"))] (clobber (match_scratch:SI 3 "=X,&a"))]
"!TARGET_64BIT" "!TARGET_64BIT"
...@@ -1715,64 +1584,13 @@ ...@@ -1715,64 +1584,13 @@
} }
}" }"
[(set_attr "op_type" "SS,NN") [(set_attr "op_type" "SS,NN")
(set_attr "type" "cs,cs")
(set_attr "atype" "mem,mem") (set_attr "atype" "mem,mem")
(set_attr "length" "*,14")]) (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" (define_insn "movstr_long_64"
[(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"
[(set (match_operand:TI 0 "register_operand" "=d") [(set (match_operand:TI 0 "register_operand" "=d")
(ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0") (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
(lshiftrt:TI (match_dup 2) (const_int 64))) (lshiftrt:TI (match_dup 2) (const_int 64)))
...@@ -1787,10 +1605,11 @@ ...@@ -1787,10 +1605,11 @@
"TARGET_64BIT" "TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4" "mvcle\\t%0,%1,0\;jo\\t.-4"
[(set_attr "op_type" "NN") [(set_attr "op_type" "NN")
(set_attr "type" "vs")
(set_attr "atype" "mem") (set_attr "atype" "mem")
(set_attr "length" "8")]) (set_attr "length" "8")])
(define_insn "movstrsi_31" (define_insn "movstr_long_31"
[(set (match_operand:DI 0 "register_operand" "=d") [(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0") (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
(lshiftrt:DI (match_dup 2) (const_int 32))) (lshiftrt:DI (match_dup 2) (const_int 32)))
...@@ -1804,112 +1623,93 @@ ...@@ -1804,112 +1623,93 @@
(clobber (reg:CC 33))] (clobber (reg:CC 33))]
"!TARGET_64BIT" "!TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4" "mvcle\\t%0,%1,0\;jo\\t.-4"
[(set_attr "op_type" "NN") [(set_attr "op_type" "NN")
(set_attr "atype" "mem") (set_attr "type" "vs")
(set_attr "length" "8")]) (set_attr "atype" "mem")
(set_attr "length" "8")])
; ;
; clrstrdi instruction pattern(s). ; clrstrM instruction pattern(s).
; ;
(define_expand "clrstrdi" (define_expand "clrstrdi"
[(set (match_operand:BLK 0 "general_operand" "") [(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0)) (const_int 0))
(use (match_operand:DI 1 "general_operand" "")) (use (match_operand:DI 1 "general_operand" ""))
(match_operand 2 "" "")] (match_operand 2 "" "")]
"TARGET_64BIT" "TARGET_64BIT"
" "s390_expand_clrstr (operands[0], operands[1]); DONE;")
{
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).
;
(define_expand "clrstrsi" (define_expand "clrstrsi"
[(set (match_operand:BLK 0 "general_operand" "") [(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0)) (const_int 0))
(use (match_operand:SI 1 "general_operand" "")) (use (match_operand:SI 1 "general_operand" ""))
(match_operand 2 "" "")] (match_operand 2 "" "")]
"!TARGET_64BIT" ""
" "s390_expand_clrstr (operands[0], operands[1]); DONE;")
{
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);
/* 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); (define_insn "clrstr_short_64"
emit_move_insn (gen_lowpart (SImode, reg0), len); [(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); case 1:
output_asm_insn (\"bras\\t%2,.+10\", operands);
/* CLear! */ output_asm_insn (\"xc\\t%O0(1,%R0),%0\", operands);
emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0)); return \"ex\\t%1,0(%2)\";
DONE;
}
}")
; 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" (define_insn "clrstr_short_31"
[(set (match_operand:BLK 0 "s_operand" "=Q") [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
(const_int 0)) (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))] (clobber (reg:CC 33))]
"" "!TARGET_64BIT"
"xc\\t%O0(%1,%R0),%0" "*
[(set_attr "op_type" "RS") {
(set_attr "type" "cs") switch (which_alternative)
(set_attr "atype" "mem")]) {
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") [(set (match_operand:TI 0 "register_operand" "=d")
(ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0") (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
(lshiftrt:TI (match_dup 2) (const_int 64))) (lshiftrt:TI (match_dup 2) (const_int 64)))
...@@ -1925,7 +1725,7 @@ ...@@ -1925,7 +1725,7 @@
(set_attr "type" "vs") (set_attr "type" "vs")
(set_attr "length" "8")]) (set_attr "length" "8")])
(define_insn "clrstrsi_31" (define_insn "clrstr_long_31"
[(set (match_operand:DI 0 "register_operand" "=d") [(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0") (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
(lshiftrt:DI (match_dup 2) (const_int 32))) (lshiftrt:DI (match_dup 2) (const_int 32)))
...@@ -1942,157 +1742,91 @@ ...@@ -1942,157 +1742,91 @@
(set_attr "length" "8")]) (set_attr "length" "8")])
; ;
; cmpstrdi instruction pattern(s). ; cmpstrM instruction pattern(s).
; ;
(define_expand "cmpstrdi" (define_expand "cmpstrdi"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(compare:DI (match_operand:BLK 1 "general_operand" "") (compare:DI (match_operand:BLK 1 "memory_operand" "")
(match_operand:BLK 2 "general_operand" "") ) ) (match_operand:BLK 2 "memory_operand" "") ) )
(use (match_operand:DI 3 "general_operand" "")) (use (match_operand:DI 3 "general_operand" ""))
(use (match_operand:DI 4 "" ""))] (use (match_operand:DI 4 "" ""))]
"TARGET_64BIT" "TARGET_64BIT"
" "s390_expand_cmpstr (operands[0], operands[1],
{ operands[2], operands[3]); DONE;")
rtx addr0, addr1;
/* for pre/post increment */ (define_expand "cmpstrsi"
operands[1] = protect_from_queue (operands[1], 0); [(set (match_operand:SI 0 "register_operand" "")
operands[2] = protect_from_queue (operands[2], 0); (compare:SI (match_operand:BLK 1 "memory_operand" "")
operands[3] = protect_from_queue (operands[3], 0); (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); ; Compare a block that is up to 256 bytes in length.
addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX); ; 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) { case 0:
emit_move_insn (operands[0], operands[3]); return \"clc\\t%O0(%b2+1,%R0),%1\";
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);
emit_move_insn (gen_highpart (DImode, reg1), addr1); case 1:
emit_move_insn (gen_lowpart (DImode, reg1), len); 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! */ default:
emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1)); abort ();
emit_insn (gen_cmpint_di (operands[0]));
DONE;
} }
}") }"
[(set_attr "op_type" "SS,NN")
; (set_attr "type" "cs,cs")
; cmpstrsi instruction pattern(s). (set_attr "atype" "mem,mem")
; (set_attr "length" "*,14")])
(define_expand "cmpstrsi" (define_insn "cmpstr_short_31"
[(set (match_operand:SI 0 "register_operand" "") [(set (reg:CCS 33)
(compare:SI (match_operand:BLK 1 "general_operand" "") (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 2 "general_operand" "") ) ) (match_operand:BLK 1 "memory_operand" "Q,Q")))
(use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
(use (match_operand:SI 4 "" ""))] (clobber (match_scratch:SI 3 "=X,&a"))]
"" "!TARGET_64BIT"
" "*
{ {
rtx addr0, addr1; switch (which_alternative)
/* 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)
{ {
if (INTVAL (operands[3]) == 0) { case 0:
emit_move_insn (operands[0], operands[3]); return \"clc\\t%O0(%b2+1,%R0),%1\";
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);
/* Compare! */ case 1:
if (TARGET_64BIT) output_asm_insn (\"bras\\t%3,.+10\", operands);
emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1)); output_asm_insn (\"clc\\t%O0(1,%R0),%1\", operands);
else return \"ex\\t%2,0(%3)\";
emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1));
emit_insn (gen_cmpint_si (operands[0])); default:
DONE; abort ();
} }
}") }"
[(set_attr "op_type" "SS,NN")
; Compare a block that is less than 256 bytes in length. (set_attr "type" "cs,cs")
(set_attr "atype" "mem,mem")
(define_insn "cmpstr_const" (set_attr "length" "*,14")])
[(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")])
; 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 0 "register_operand" "=d"))
(clobber (match_operand:TI 1 "register_operand" "=d")) (clobber (match_operand:TI 1 "register_operand" "=d"))
(set (reg:CCS 33) (set (reg:CCS 33)
...@@ -2106,7 +1840,7 @@ ...@@ -2106,7 +1840,7 @@
(set_attr "atype" "mem") (set_attr "atype" "mem")
(set_attr "type" "vs")]) (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 0 "register_operand" "=d"))
(clobber (match_operand:DI 1 "register_operand" "=d")) (clobber (match_operand:DI 1 "register_operand" "=d"))
(set (reg:CCS 33) (set (reg:CCS 33)
...@@ -3372,6 +3106,16 @@ ...@@ -3372,6 +3106,16 @@
(set_attr "atype" "mem") (set_attr "atype" "mem")
(set_attr "type" "la")]) (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" (define_expand "reload_insi"
[(parallel [(match_operand:SI 0 "register_operand" "=a") [(parallel [(match_operand:SI 0 "register_operand" "=a")
(match_operand:SI 1 "s390_plus_operand" "") (match_operand:SI 1 "s390_plus_operand" "")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment