aboutsummaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-08-22 11:43:06 -0700
committerRichard Henderson <rth@twiddle.net>2013-01-05 12:18:39 -0800
commitaf9e5a04ea63b7ebbe7af2bb3553dc0e8a158d12 (patch)
tree3ef028a268a30d9af25c12a3edd052534637a1be /target-s390x
parenteb66e6a96904e50a9d0d1a76aecfe8675f4d8673 (diff)
target-s390: Convert MVC
The code that was in gen_op_mvc was a bit confused wrt what lengths it wanted to handle. I also disbelieve that the inline memset is worthwhile. Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/insn-data.def1
-rw-r--r--target-s390x/translate.c177
2 files changed, 10 insertions, 168 deletions
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4d7f862e29..a8056a87c9 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -286,6 +286,7 @@
C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0)
/* MOVE */
+ C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0)
C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
C(0xe54c, MVHI, SIL, GIE, la1, i2, 0, m1_32, mov2, 0)
C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 38eeeadf7f..294cb92fe2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1012,170 +1012,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
-{
- TCGv_i64 tmp, tmp2;
- int i;
- int l_memset = gen_new_label();
- int l_out = gen_new_label();
- TCGv_i64 dest = tcg_temp_local_new_i64();
- TCGv_i64 src = tcg_temp_local_new_i64();
- TCGv_i32 vl;
-
- /* Find out if we should use the inline version of mvc */
- switch (l) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 11:
- case 15:
- /* use inline */
- break;
- default:
- /* Fall back to helper */
- vl = tcg_const_i32(l);
- potential_page_fault(s);
- gen_helper_mvc(cpu_env, vl, s1, s2);
- tcg_temp_free_i32(vl);
- return;
- }
-
- tcg_gen_mov_i64(dest, s1);
- tcg_gen_mov_i64(src, s2);
-
- if (!(s->tb->flags & FLAG_MASK_64)) {
- /* XXX what if we overflow while moving? */
- tcg_gen_andi_i64(dest, dest, 0x7fffffffUL);
- tcg_gen_andi_i64(src, src, 0x7fffffffUL);
- }
-
- tmp = tcg_temp_new_i64();
- tcg_gen_addi_i64(tmp, src, 1);
- tcg_gen_brcond_i64(TCG_COND_EQ, dest, tmp, l_memset);
- tcg_temp_free_i64(tmp);
-
- switch (l) {
- case 0:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 1:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld16u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st16(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 3:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 4:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
- tcg_gen_addi_i64(src, src, 4);
- tcg_gen_qemu_ld8u(tmp2, src, get_mem_index(s));
- tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 4);
- tcg_gen_qemu_st8(tmp2, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- case 7:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- default:
- /* The inline version can become too big for too uneven numbers, only
- use it on known good lengths */
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_const_i64(8);
- for (i = 0; (i + 7) <= l; i += 8) {
- tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
- tcg_gen_add_i64(src, src, tmp2);
- tcg_gen_add_i64(dest, dest, tmp2);
- }
-
- tcg_temp_free_i64(tmp2);
- tmp2 = tcg_const_i64(1);
-
- for (; i <= l; i++) {
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
- tcg_gen_add_i64(src, src, tmp2);
- tcg_gen_add_i64(dest, dest, tmp2);
- }
-
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
- break;
- }
-
- tcg_gen_br(l_out);
-
- gen_set_label(l_memset);
- /* memset case (dest == (src + 1)) */
-
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
- /* fill tmp with the byte */
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_shli_i64(tmp2, tmp, 8);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_gen_shli_i64(tmp2, tmp, 16);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_gen_shli_i64(tmp2, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_temp_free_i64(tmp2);
-
- tmp2 = tcg_const_i64(8);
-
- for (i = 0; (i + 7) <= l; i += 8) {
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 8);
- }
-
- tcg_temp_free_i64(tmp2);
- tmp2 = tcg_const_i64(1);
-
- for (; i <= l; i++) {
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 1);
- }
-
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
-
- gen_set_label(l_out);
-
- tcg_temp_free(dest);
- tcg_temp_free(src);
-}
-
static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
{
TCGv_i64 tmp;
@@ -2365,7 +2201,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */
@@ -2381,9 +2216,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tmp = get_address(s, 0, b1, d1);
tmp2 = get_address(s, 0, b2, d2);
switch (opc) {
- case 0xd2:
- gen_op_mvc(s, (insn >> 32) & 0xff, tmp, tmp2);
- break;
case 0xd4:
potential_page_fault(s);
gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
@@ -3322,6 +3154,15 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ return NO_EXIT;
+}
+
static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));