s390.c (s390_expand_insv): New.
2005-10-19 Adrian Straetling <straetling@de.ibm.com> * config/s390/s390.c (s390_expand_insv): New. * config/s390/s390-protos.h (s390_expand_insv): Declare. * config/s390/s390.md ("UNSPEC_SETHIGH"): Rename to "UNSPEC_ICM". ("icm_hi"): Remove mode attribute. ("*sethigh<mode><mode>"): Rewrite to "sethighpart<mode>". Adjust all uses. ("*extracthi", "*extractqi"): Remove. (extv<mode>", "*extzv<mode>"): New. ("insv", "*insv<mode>_mem_reg", "*insvdi_mem_reghigh", "*insv<mode>_reg_imm", "*insv<mode>_reg_extimm"): New. From-SVN: r105625
This commit is contained in:
parent
a1b23b2f7c
commit
6fa05db65c
4 changed files with 261 additions and 43 deletions
|
@ -1,3 +1,16 @@
|
|||
2005-10-19 Adrian Straetling <straetling@de.ibm.com>
|
||||
|
||||
* config/s390/s390.c (s390_expand_insv): New.
|
||||
* config/s390/s390-protos.h (s390_expand_insv): Declare.
|
||||
* config/s390/s390.md ("UNSPEC_SETHIGH"): Rename to "UNSPEC_ICM".
|
||||
("icm_hi"): Remove mode attribute.
|
||||
("*sethigh<mode><mode>"): Rewrite to "sethighpart<mode>".
|
||||
Adjust all uses.
|
||||
("*extracthi", "*extractqi"): Remove.
|
||||
(extv<mode>", "*extzv<mode>"): New.
|
||||
("insv", "*insv<mode>_mem_reg", "*insvdi_mem_reghigh",
|
||||
"*insv<mode>_reg_imm", "*insv<mode>_reg_extimm"): New.
|
||||
|
||||
2005-10-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* cfgexpand.c (discover_nonconstant_array_refs_r,
|
||||
|
|
|
@ -74,6 +74,7 @@ extern void s390_expand_movmem (rtx, rtx, rtx);
|
|||
extern void s390_expand_setmem (rtx, rtx, rtx);
|
||||
extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
|
||||
extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
|
||||
extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
|
||||
extern rtx s390_return_addr_rtx (int, rtx);
|
||||
extern rtx s390_back_chain_rtx (void);
|
||||
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
|
||||
|
|
|
@ -3815,6 +3815,101 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Expand code for the insv template. Return true if successful, false else. */
|
||||
|
||||
bool
|
||||
s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
|
||||
{
|
||||
int bitsize = INTVAL (op1);
|
||||
int bitpos = INTVAL (op2);
|
||||
|
||||
/* We need byte alignement. */
|
||||
if (bitsize % BITS_PER_UNIT)
|
||||
return false;
|
||||
|
||||
if (bitpos == 0
|
||||
&& memory_operand (dest, VOIDmode)
|
||||
&& (register_operand (src, word_mode)
|
||||
|| const_int_operand (src, VOIDmode)))
|
||||
{
|
||||
/* Emit standard pattern if possible. */
|
||||
enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
|
||||
if (GET_MODE_BITSIZE (mode) == bitsize)
|
||||
emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
|
||||
|
||||
/* (set (ze (mem)) (const_int)). */
|
||||
else if (const_int_operand (src, VOIDmode))
|
||||
{
|
||||
int size = bitsize / BITS_PER_UNIT;
|
||||
rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
|
||||
GET_MODE_SIZE (word_mode) - size);
|
||||
|
||||
dest = adjust_address (dest, BLKmode, 0);
|
||||
set_mem_size (dest, GEN_INT (size));
|
||||
s390_expand_movmem (dest, src_mem, GEN_INT (size));
|
||||
}
|
||||
|
||||
/* (set (ze (mem)) (reg)). */
|
||||
else if (register_operand (src, word_mode))
|
||||
{
|
||||
if (bitsize <= GET_MODE_BITSIZE (SImode))
|
||||
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 size = stcmh_width / BITS_PER_UNIT;
|
||||
|
||||
emit_move_insn (adjust_address (dest, SImode, size),
|
||||
gen_lowpart (SImode, src));
|
||||
set_mem_size (dest, GEN_INT (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))));
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (set (ze (reg)) (const_int)). */
|
||||
if (TARGET_ZARCH
|
||||
&& register_operand (dest, word_mode)
|
||||
&& (bitpos % 16) == 0
|
||||
&& (bitsize % 16) == 0
|
||||
&& const_int_operand (src, VOIDmode))
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (src);
|
||||
int regpos = bitpos + bitsize;
|
||||
|
||||
while (regpos > bitpos)
|
||||
{
|
||||
enum machine_mode putmode;
|
||||
int putsize;
|
||||
|
||||
if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
|
||||
putmode = SImode;
|
||||
else
|
||||
putmode = HImode;
|
||||
|
||||
putsize = GET_MODE_BITSIZE (putmode);
|
||||
regpos -= putsize;
|
||||
emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
|
||||
GEN_INT (putsize),
|
||||
GEN_INT (regpos)),
|
||||
gen_int_mode (val, putmode));
|
||||
val >>= putsize;
|
||||
}
|
||||
gcc_assert (regpos == bitpos);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
|
||||
We need to emit DTP-relative relocations. */
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
[; Miscellaneous
|
||||
(UNSPEC_ROUND 1)
|
||||
(UNSPEC_CMPINT 2)
|
||||
(UNSPEC_SETHIGH 10)
|
||||
(UNSPEC_ICM 10)
|
||||
|
||||
; GOT/PLT and lt-relative accesses
|
||||
(UNSPEC_LTREL_OFFSET 100)
|
||||
|
@ -352,10 +352,6 @@
|
|||
;; and "cfdbr" in SImode.
|
||||
(define_mode_attr gf [(DI "g") (SI "f")])
|
||||
|
||||
;; ICM mask required to load MODE value into the highest subreg
|
||||
;; of a SImode register.
|
||||
(define_mode_attr icm_hi [(HI "12") (QI "8")])
|
||||
|
||||
;; ICM mask required to load MODE value into the lowest subreg
|
||||
;; of a SImode register.
|
||||
(define_mode_attr icm_lo [(HI "3") (QI "1")])
|
||||
|
@ -2464,73 +2460,180 @@
|
|||
;;- Conversion instructions.
|
||||
;;
|
||||
|
||||
|
||||
(define_insn "*sethigh<mode>si"
|
||||
(define_insn "*sethighpartsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d")
|
||||
(unspec:SI [(match_operand:HQI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
|
||||
(unspec:SI [(match_operand:BLK 1 "s_operand" "Q,S")
|
||||
(match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
""
|
||||
"@
|
||||
icm\t%0,<icm_hi>,%S1
|
||||
icmy\t%0,<icm_hi>,%S1"
|
||||
icm\t%0,%2,%S1
|
||||
icmy\t%0,%2,%S1"
|
||||
[(set_attr "op_type" "RS,RSY")])
|
||||
|
||||
(define_insn "*sethighqidi_64"
|
||||
(define_insn "*sethighpartdi_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(unspec:DI [(match_operand:QI 1 "s_operand" "QS")] UNSPEC_SETHIGH))
|
||||
(unspec:DI [(match_operand:BLK 1 "s_operand" "QS")
|
||||
(match_operand 2 "const_int_operand" "n")] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"TARGET_64BIT"
|
||||
"icmh\t%0,8,%S1"
|
||||
"icmh\t%0,%2,%S1"
|
||||
[(set_attr "op_type" "RSY")])
|
||||
|
||||
(define_insn "*sethighqidi_31"
|
||||
(define_insn "*sethighpartdi_31"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d,d")
|
||||
(unspec:DI [(match_operand:QI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
|
||||
(unspec:DI [(match_operand:BLK 1 "s_operand" "Q,S")
|
||||
(match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
icm\t%0,8,%S1
|
||||
icmy\t%0,8,%S1"
|
||||
icm\t%0,%2,%S1
|
||||
icmy\t%0,%2,%S1"
|
||||
[(set_attr "op_type" "RS,RSY")])
|
||||
|
||||
(define_insn_and_split "*extractqi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
|
||||
(match_operand 2 "const_int_operand" "n")
|
||||
(const_int 0)))
|
||||
(define_insn_and_split "*extzv<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=d")
|
||||
(zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
|
||||
(match_operand 2 "const_int_operand" "n")
|
||||
(const_int 0)))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"!TARGET_64BIT
|
||||
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
|
||||
"INTVAL (operands[2]) > 0
|
||||
&& INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel
|
||||
[(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
|
||||
[(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))])
|
||||
(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
|
||||
(set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
|
||||
{
|
||||
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
|
||||
operands[1] = change_address (operands[1], QImode, 0);
|
||||
int bitsize = INTVAL (operands[2]);
|
||||
int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
|
||||
int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
|
||||
|
||||
operands[1] = adjust_address (operands[1], BLKmode, 0);
|
||||
set_mem_size (operands[1], GEN_INT (size));
|
||||
operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
|
||||
operands[3] = GEN_INT (mask);
|
||||
})
|
||||
|
||||
(define_insn_and_split "*extracthi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
|
||||
(match_operand 2 "const_int_operand" "n")
|
||||
(const_int 0)))
|
||||
(define_insn_and_split "*extv<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=d")
|
||||
(sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
|
||||
(match_operand 2 "const_int_operand" "n")
|
||||
(const_int 0)))
|
||||
(clobber (reg:CC CC_REGNUM))]
|
||||
"!TARGET_64BIT
|
||||
&& INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
|
||||
"INTVAL (operands[2]) > 0
|
||||
&& INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel
|
||||
[(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
|
||||
[(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))])
|
||||
(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
|
||||
(parallel
|
||||
[(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
|
||||
(clobber (reg:CC CC_REGNUM))])]
|
||||
{
|
||||
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
|
||||
operands[1] = change_address (operands[1], HImode, 0);
|
||||
int bitsize = INTVAL (operands[2]);
|
||||
int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
|
||||
int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
|
||||
|
||||
operands[1] = adjust_address (operands[1], BLKmode, 0);
|
||||
set_mem_size (operands[1], GEN_INT (size));
|
||||
operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
|
||||
operands[3] = GEN_INT (mask);
|
||||
})
|
||||
|
||||
;
|
||||
; insv instruction patterns
|
||||
;
|
||||
|
||||
(define_expand "insv"
|
||||
[(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
|
||||
(match_operand 1 "const_int_operand" "")
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(match_operand 3 "general_operand" ""))]
|
||||
""
|
||||
{
|
||||
if (s390_expand_insv (operands[0], operands[1], operands[2], operands[3]))
|
||||
DONE;
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_insn "*insv<mode>_mem_reg"
|
||||
[(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
|
||||
(match_operand 1 "const_int_operand" "n,n")
|
||||
(const_int 0))
|
||||
(match_operand:P 2 "register_operand" "d,d"))]
|
||||
"INTVAL (operands[1]) > 0
|
||||
&& INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
|
||||
&& INTVAL (operands[1]) % BITS_PER_UNIT == 0"
|
||||
{
|
||||
int size = INTVAL (operands[1]) / BITS_PER_UNIT;
|
||||
|
||||
operands[1] = GEN_INT ((1ul << size) - 1);
|
||||
return (which_alternative == 0) ? "stcm\t%2,%1,%S0"
|
||||
: "stcmy\t%2,%1,%S0";
|
||||
}
|
||||
[(set_attr "op_type" "RS,RSY")])
|
||||
|
||||
(define_insn "*insvdi_mem_reghigh"
|
||||
[(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "+QS")
|
||||
(match_operand 1 "const_int_operand" "n")
|
||||
(const_int 0))
|
||||
(lshiftrt:DI (match_operand:DI 2 "register_operand" "d")
|
||||
(const_int 32)))]
|
||||
"TARGET_64BIT
|
||||
&& INTVAL (operands[1]) > 0
|
||||
&& INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
|
||||
&& INTVAL (operands[1]) % BITS_PER_UNIT == 0"
|
||||
{
|
||||
int size = INTVAL (operands[1]) / BITS_PER_UNIT;
|
||||
|
||||
operands[1] = GEN_INT ((1ul << size) - 1);
|
||||
return "stcmh\t%2,%1,%S0";
|
||||
}
|
||||
[(set_attr "op_type" "RSY")])
|
||||
|
||||
(define_insn "*insv<mode>_reg_imm"
|
||||
[(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
|
||||
(const_int 16)
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(match_operand:P 2 "const_int_operand" "K"))]
|
||||
"TARGET_ZARCH
|
||||
&& INTVAL (operands[1]) >= 0
|
||||
&& INTVAL (operands[1]) < BITS_PER_WORD
|
||||
&& INTVAL (operands[1]) % 16 == 0"
|
||||
{
|
||||
switch (BITS_PER_WORD - INTVAL (operands[1]))
|
||||
{
|
||||
case 64: return "iihh\t%0,%x2"; break;
|
||||
case 48: return "iihl\t%0,%x2"; break;
|
||||
case 32: return "iilh\t%0,%x2"; break;
|
||||
case 16: return "iill\t%0,%x2"; break;
|
||||
default: gcc_unreachable();
|
||||
}
|
||||
}
|
||||
[(set_attr "op_type" "RI")])
|
||||
|
||||
(define_insn "*insv<mode>_reg_extimm"
|
||||
[(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
|
||||
(const_int 32)
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(match_operand:P 2 "const_int_operand" "Os"))]
|
||||
"TARGET_EXTIMM
|
||||
&& INTVAL (operands[1]) >= 0
|
||||
&& INTVAL (operands[1]) < BITS_PER_WORD
|
||||
&& INTVAL (operands[1]) % 32 == 0"
|
||||
{
|
||||
switch (BITS_PER_WORD - INTVAL (operands[1]))
|
||||
{
|
||||
case 64: return "iihf\t%0,%o2"; break;
|
||||
case 32: return "iilf\t%0,%o2"; break;
|
||||
default: gcc_unreachable();
|
||||
}
|
||||
}
|
||||
[(set_attr "op_type" "RIL")])
|
||||
|
||||
;
|
||||
; extendsidi2 instruction pattern(s).
|
||||
;
|
||||
|
@ -2626,12 +2729,15 @@
|
|||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel
|
||||
[(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_SETHIGH))
|
||||
[(set (match_dup 0) (unspec:DI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))])
|
||||
(parallel
|
||||
[(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
|
||||
(clobber (reg:CC CC_REGNUM))])]
|
||||
"")
|
||||
{
|
||||
operands[1] = adjust_address (operands[1], BLKmode, 0);
|
||||
set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
|
||||
})
|
||||
|
||||
;
|
||||
; extend(hi|qi)si2 instruction pattern(s).
|
||||
|
@ -2696,12 +2802,15 @@
|
|||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel
|
||||
[(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
|
||||
[(set (match_dup 0) (unspec:SI [(match_dup 1) (const_int 8)] UNSPEC_ICM))
|
||||
(clobber (reg:CC CC_REGNUM))])
|
||||
(parallel
|
||||
[(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
|
||||
(clobber (reg:CC CC_REGNUM))])]
|
||||
"")
|
||||
{
|
||||
operands[1] = adjust_address (operands[1], BLKmode, 0);
|
||||
set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
|
||||
})
|
||||
|
||||
;
|
||||
; extendqihi2 instruction pattern(s).
|
||||
|
|
Loading…
Add table
Reference in a new issue