@@ -4551,7 +4551,8 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
int bitsize = INTVAL (op1);
int bitpos = INTVAL (op2);
enum machine_mode mode = GET_MODE (dest);
- enum machine_mode smode = smallest_mode_for_size (bitsize, MODE_INT);
+ enum machine_mode smode;
+ int smode_bsize, mode_bsize;
rtx op, clobber;
/* Generate INSERT IMMEDIATE (IILL et al). */
@@ -4587,6 +4588,10 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
return true;
}
+ smode = smallest_mode_for_size (bitsize, MODE_INT);
+ smode_bsize = GET_MODE_BITSIZE (smode);
+ mode_bsize = GET_MODE_BITSIZE (mode);
+
/* Generate STORE CHARACTERS UNDER MASK (STCM et al). */
if (bitpos == 0
&& (bitsize % BITS_PER_UNIT) == 0
@@ -4595,7 +4600,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
|| const_int_operand (src, VOIDmode)))
{
/* Emit standard pattern if possible. */
- if (GET_MODE_BITSIZE (smode) == bitsize)
+ if (smode_bsize == bitsize)
{
emit_move_insn (adjust_address (dest, smode, 0),
gen_lowpart (smode, src));
@@ -4608,7 +4613,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
int size = bitsize / BITS_PER_UNIT;
rtx src_mem = adjust_address (force_const_mem (word_mode, src),
BLKmode,
- GET_MODE_SIZE (word_mode) - size);
+ UNITS_PER_WORD - size);
dest = adjust_address (dest, BLKmode, 0);
set_mem_size (dest, size);
@@ -4619,22 +4624,22 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
/* (set (ze (mem)) (reg)). */
else if (register_operand (src, word_mode))
{
- if (bitsize <= GET_MODE_BITSIZE (SImode))
+ if (bitsize <= 32)
emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
const0_rtx), src);
else
{
/* Emit st,stcmh sequence. */
- int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
+ int stcmh_width = bitsize - 32;
int size = stcmh_width / BITS_PER_UNIT;
emit_move_insn (adjust_address (dest, SImode, size),
gen_lowpart (SImode, src));
set_mem_size (dest, size);
- emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
- (stcmh_width), const0_rtx),
- gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
- (GET_MODE_BITSIZE (SImode))));
+ emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
+ GEN_INT (stcmh_width),
+ const0_rtx),
+ gen_rtx_LSHIFTRT (word_mode, src, GEN_INT (32)));
}
return true;
}
@@ -4649,7 +4654,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
&& register_operand (dest, mode))
{
/* Emit a strict_low_part pattern if possible. */
- if (bitpos == 0 && GET_MODE_BITSIZE (smode) == bitsize)
+ if (smode_bsize == bitsize && bitpos == mode_bsize - smode_bsize)
{
op = gen_rtx_STRICT_LOW_PART (VOIDmode, gen_lowpart (smode, dest));
op = gen_rtx_SET (VOIDmode, op, gen_lowpart (smode, src));
@@ -4728,7 +4733,12 @@ init_alignment_context (struct alignment_context *ac, rtx mem,
ac->aligned = (MEM_ALIGN (mem) >= GET_MODE_BITSIZE (SImode));
if (ac->aligned)
- ac->memsi = adjust_address (mem, SImode, 0); /* Memory is aligned. */
+ {
+ ac->memsi = adjust_address (mem, SImode, 0); /* Memory is aligned. */
+ ac->shift = const0_rtx;
+ ac->modemask = GEN_INT (GET_MODE_MASK (mode));
+ ac->modemaski = GEN_INT (~GET_MODE_MASK (mode));
+ }
else
{
/* Alignment is unknown. */
@@ -4755,15 +4765,17 @@ init_alignment_context (struct alignment_context *ac, rtx mem,
ac->shift = expand_simple_binop (SImode, MINUS, ac->shift, byteoffset,
NULL_RTX, 1, OPTAB_DIRECT);
+ /* Shift is the byte count, but we need the bitcount. */
+ ac->shift = expand_simple_binop (SImode, ASHIFT, ac->shift, GEN_INT (3),
+ NULL_RTX, 1, OPTAB_DIRECT);
+
+ /* Calculate masks. */
+ ac->modemask = expand_simple_binop (SImode, ASHIFT,
+ GEN_INT (GET_MODE_MASK (mode)),
+ ac->shift, NULL_RTX, 1, OPTAB_DIRECT);
+ ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask,
+ NULL_RTX, 1);
}
- /* Shift is the byte count, but we need the bitcount. */
- ac->shift = expand_simple_binop (SImode, MULT, ac->shift, GEN_INT (BITS_PER_UNIT),
- NULL_RTX, 1, OPTAB_DIRECT);
- /* Calculate masks. */
- ac->modemask = expand_simple_binop (SImode, ASHIFT,
- GEN_INT (GET_MODE_MASK (mode)), ac->shift,
- NULL_RTX, 1, OPTAB_DIRECT);
- ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
}
/* A subroutine of s390_expand_cs_hqi. Insert INS into VAL. If possible,
@@ -4781,7 +4793,7 @@ s390_two_part_insv (struct alignment_context *ac, rtx *seq1, rtx *seq2,
start_sequence ();
tmp = copy_to_mode_reg (SImode, val);
if (s390_expand_insv (tmp, GEN_INT (GET_MODE_BITSIZE (mode)),
- const0_rtx, ins))
+ GEN_INT (32 - GET_MODE_BITSIZE (mode)), ins))
{
*seq1 = NULL;
*seq2 = get_insns ();