aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.c
diff options
context:
space:
mode:
authorAdrian Straetling <straetling@de.ibm.com>2005-10-19 16:37:10 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2005-10-19 16:37:10 +0000
commit6fa05db65c8202c23d3370feb72fc41472498e82 (patch)
tree077e1a0a0ddd7137851ee644b623a485c87fa8a9 /gcc/config/s390/s390.c
parenta1b23b2f7cef7cd0b8df65ed1936b8ea7ea65696 (diff)
downloadgcc-6fa05db65c8202c23d3370feb72fc41472498e82.zip
gcc-6fa05db65c8202c23d3370feb72fc41472498e82.tar.gz
gcc-6fa05db65c8202c23d3370feb72fc41472498e82.tar.bz2
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
Diffstat (limited to 'gcc/config/s390/s390.c')
-rw-r--r--gcc/config/s390/s390.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 445f4e1..009c178 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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. */