mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-19 10:54:04 +08:00
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
This commit is contained in:
parent
2a4ecff3cb
commit
a41c6c533d
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
/* Load up the address+length pairs. */
|
||||
|
||||
emit_move_insn (gen_highpart (SImode, reg0), addr);
|
||||
emit_move_insn (gen_lowpart (SImode, reg0), len);
|
||||
|
||||
emit_move_insn (gen_lowpart (SImode, reg1), const0_rtx);
|
||||
|
||||
/* CLear! */
|
||||
emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0));
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
; Clear memory with length less than 256 bytes
|
||||
|
||||
(define_insn "clrstrsico"
|
||||
[(set (match_operand:BLK 0 "s_operand" "=Q")
|
||||
(const_int 0))
|
||||
(use (match_operand 1 "immediate_operand" "I"))
|
||||
(clobber (reg:CC 33))]
|
||||
""
|
||||
"xc\\t%O0(%1,%R0),%0"
|
||||
[(set_attr "op_type" "RS")
|
||||
(set_attr "type" "cs")
|
||||
(set_attr "atype" "mem")])
|
||||
"s390_expand_clrstr (operands[0], operands[1]); DONE;")
|
||||
|
||||
; Clear memory with length greater 256 bytes or lenght not constant
|
||||
; Clear a block that is up to 256 bytes in length.
|
||||
; The block length is taken as (operands[2] % 256) + 1.
|
||||
|
||||
(define_insn "clrstrsi_64"
|
||||
(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\";
|
||||
|
||||
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")])
|
||||
|
||||
(define_insn "clrstr_short_31"
|
||||
[(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
|
||||
(const_int 0))
|
||||
(use (match_operand:SI 1 "nonmemory_operand" "n,a"))
|
||||
(clobber (match_scratch:SI 2 "=X,&a"))
|
||||
(clobber (reg:CC 33))]
|
||||
"!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 a block of arbitrary length.
|
||||
|
||||
(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;
|
||||
|
||||
/* 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) {
|
||||
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);
|
||||
|
||||
emit_move_insn (gen_highpart (DImode, reg1), addr1);
|
||||
emit_move_insn (gen_lowpart (DImode, reg1), len);
|
||||
|
||||
/* Compare! */
|
||||
emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
|
||||
emit_insn (gen_cmpint_di (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
;
|
||||
; cmpstrsi instruction pattern(s).
|
||||
;
|
||||
[(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;")
|
||||
|
||||
(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 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr0, addr1;
|
||||
[(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;")
|
||||
|
||||
/* 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);
|
||||
; Compare a block that is up to 256 bytes in length.
|
||||
; The block length is taken as (operands[2] % 256) + 1.
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
/* Compare! */
|
||||
if (TARGET_64BIT)
|
||||
emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
|
||||
else
|
||||
emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1));
|
||||
|
||||
emit_insn (gen_cmpint_si (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
; Compare a block that is less than 256 bytes in length.
|
||||
|
||||
(define_insn "cmpstr_const"
|
||||
(define_insn "cmpstr_short_64"
|
||||
[(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: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)
|
||||
{
|
||||
case 0:
|
||||
return \"clc\\t%O0(%b2+1,%R0),%1\";
|
||||
|
||||
; Compare a block that is larger than 255 bytes in length.
|
||||
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)\";
|
||||
|
||||
(define_insn "cmpstr_64"
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}"
|
||||
[(set_attr "op_type" "SS,NN")
|
||||
(set_attr "type" "cs,cs")
|
||||
(set_attr "atype" "mem,mem")
|
||||
(set_attr "length" "*,14")])
|
||||
|
||||
(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"
|
||||
"*
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return \"clc\\t%O0(%b2+1,%R0),%1\";
|
||||
|
||||
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)\";
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}"
|
||||
[(set_attr "op_type" "SS,NN")
|
||||
(set_attr "type" "cs,cs")
|
||||
(set_attr "atype" "mem,mem")
|
||||
(set_attr "length" "*,14")])
|
||||
|
||||
; Compare a block of arbitrary length.
|
||||
|
||||
(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" "")
|
||||
|
Loading…
Reference in New Issue
Block a user