Commit 6fa05db6 by Adrian Straetling Committed by Ulrich Weigand

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
parent a1b23b2f
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> 2005-10-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* cfgexpand.c (discover_nonconstant_array_refs_r, * cfgexpand.c (discover_nonconstant_array_refs_r,
......
...@@ -74,6 +74,7 @@ extern void s390_expand_movmem (rtx, rtx, rtx); ...@@ -74,6 +74,7 @@ extern void s390_expand_movmem (rtx, rtx, rtx);
extern void s390_expand_setmem (rtx, rtx, rtx); extern void s390_expand_setmem (rtx, rtx, rtx);
extern void s390_expand_cmpmem (rtx, 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_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_return_addr_rtx (int, rtx);
extern rtx s390_back_chain_rtx (void); extern rtx s390_back_chain_rtx (void);
extern rtx s390_emit_call (rtx, rtx, rtx, rtx); 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, ...@@ -3815,6 +3815,101 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
return false; 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. /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */ We need to emit DTP-relative relocations. */
......
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
[; Miscellaneous [; Miscellaneous
(UNSPEC_ROUND 1) (UNSPEC_ROUND 1)
(UNSPEC_CMPINT 2) (UNSPEC_CMPINT 2)
(UNSPEC_SETHIGH 10) (UNSPEC_ICM 10)
; GOT/PLT and lt-relative accesses ; GOT/PLT and lt-relative accesses
(UNSPEC_LTREL_OFFSET 100) (UNSPEC_LTREL_OFFSET 100)
...@@ -352,10 +352,6 @@ ...@@ -352,10 +352,6 @@
;; and "cfdbr" in SImode. ;; and "cfdbr" in SImode.
(define_mode_attr gf [(DI "g") (SI "f")]) (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 ;; ICM mask required to load MODE value into the lowest subreg
;; of a SImode register. ;; of a SImode register.
(define_mode_attr icm_lo [(HI "3") (QI "1")]) (define_mode_attr icm_lo [(HI "3") (QI "1")])
...@@ -2464,73 +2460,180 @@ ...@@ -2464,73 +2460,180 @@
;;- Conversion instructions. ;;- Conversion instructions.
;; ;;
(define_insn "*sethighpartsi"
(define_insn "*sethigh<mode>si"
[(set (match_operand:SI 0 "register_operand" "=d,d") [(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))] (clobber (reg:CC CC_REGNUM))]
"" ""
"@ "@
icm\t%0,<icm_hi>,%S1 icm\t%0,%2,%S1
icmy\t%0,<icm_hi>,%S1" icmy\t%0,%2,%S1"
[(set_attr "op_type" "RS,RSY")]) [(set_attr "op_type" "RS,RSY")])
(define_insn "*sethighqidi_64" (define_insn "*sethighpartdi_64"
[(set (match_operand:DI 0 "register_operand" "=d") [(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))] (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT" "TARGET_64BIT"
"icmh\t%0,8,%S1" "icmh\t%0,%2,%S1"
[(set_attr "op_type" "RSY")]) [(set_attr "op_type" "RSY")])
(define_insn "*sethighqidi_31" (define_insn "*sethighpartdi_31"
[(set (match_operand:DI 0 "register_operand" "=d,d") [(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))] (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT" "!TARGET_64BIT"
"@ "@
icm\t%0,8,%S1 icm\t%0,%2,%S1
icmy\t%0,8,%S1" icmy\t%0,%2,%S1"
[(set_attr "op_type" "RS,RSY")]) [(set_attr "op_type" "RS,RSY")])
(define_insn_and_split "*extractqi" (define_insn_and_split "*extzv<mode>"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:GPR 0 "register_operand" "=d")
(zero_extract:SI (match_operand:QI 1 "s_operand" "Q") (zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
(match_operand 2 "const_int_operand" "n") (match_operand 2 "const_int_operand" "n")
(const_int 0))) (const_int 0)))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT "INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8" && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(parallel [(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))]) (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])); int bitsize = INTVAL (operands[2]);
operands[1] = change_address (operands[1], QImode, 0); 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" (define_insn_and_split "*extv<mode>"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:GPR 0 "register_operand" "=d")
(zero_extract:SI (match_operand:QI 1 "s_operand" "Q") (sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
(match_operand 2 "const_int_operand" "n") (match_operand 2 "const_int_operand" "n")
(const_int 0))) (const_int 0)))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT "INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16" && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(parallel [(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))]) (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])); int bitsize = INTVAL (operands[2]);
operands[1] = change_address (operands[1], HImode, 0); 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). ; extendsidi2 instruction pattern(s).
; ;
...@@ -2626,12 +2729,15 @@ ...@@ -2626,12 +2729,15 @@
"#" "#"
"&& reload_completed" "&& reload_completed"
[(parallel [(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))]) (clobber (reg:CC CC_REGNUM))])
(parallel (parallel
[(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56))) [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
(clobber (reg:CC CC_REGNUM))])] (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). ; extend(hi|qi)si2 instruction pattern(s).
...@@ -2696,12 +2802,15 @@ ...@@ -2696,12 +2802,15 @@
"#" "#"
"&& reload_completed" "&& reload_completed"
[(parallel [(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))]) (clobber (reg:CC CC_REGNUM))])
(parallel (parallel
[(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24))) [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
(clobber (reg:CC CC_REGNUM))])] (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). ; extendqihi2 instruction pattern(s).
......
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