diff options
author | David Hildenbrand | 2019-04-11 11:39:23 +0200 |
---|---|---|
committer | David Hildenbrand | 2019-05-17 10:54:13 +0200 |
commit | 0abddd6cbf43ed68060a3f8d07d5520340944347 (patch) | |
tree | 48f2cf45a47e982b49ba38ed6e5172ec50dd9527 | |
parent | s390x/tcg: Implement VECTOR SHIFT LEFT (BY BYTE) (diff) | |
download | qemu-0abddd6cbf43ed68060a3f8d07d5520340944347.tar.gz qemu-0abddd6cbf43ed68060a3f8d07d5520340944347.tar.xz qemu-0abddd6cbf43ed68060a3f8d07d5520340944347.zip |
s390x/tcg: Implement VECTOR SHIFT LEFT DOUBLE BY BYTE
Inline expansion courtesy of Richard H.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
-rw-r--r-- | target/s390x/insn-data.def | 2 | ||||
-rw-r--r-- | target/s390x/translate_vx.inc.c | 29 |
2 files changed, 31 insertions, 0 deletions
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 2621e433cd..76aec5a21f 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -1164,6 +1164,8 @@ F(0xe774, VSL, VRR_c, V, 0, 0, 0, 0, vsl, 0, IF_VEC) /* VECTOR SHIFT LEFT BY BYTE */ F(0xe775, VSLB, VRR_c, V, 0, 0, 0, 0, vsl, 0, IF_VEC) +/* VECTOR SHIFT LEFT DOUBLE BY BYTE */ + F(0xe777, VSLDB, VRI_d, V, 0, 0, 0, 0, vsldb, 0, IF_VEC) #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c index 734c022b36..43f67e3f82 100644 --- a/target/s390x/translate_vx.inc.c +++ b/target/s390x/translate_vx.inc.c @@ -2060,3 +2060,32 @@ static DisasJumpType op_vsl(DisasContext *s, DisasOps *o) tcg_temp_free_i64(shift); return DISAS_NEXT; } + +static DisasJumpType op_vsldb(DisasContext *s, DisasOps *o) +{ + const uint8_t i4 = get_field(s->fields, i4) & 0xf; + const int left_shift = (i4 & 7) * 8; + const int right_shift = 64 - left_shift; + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + + if ((i4 & 8) == 0) { + read_vec_element_i64(t0, get_field(s->fields, v2), 0, ES_64); + read_vec_element_i64(t1, get_field(s->fields, v2), 1, ES_64); + read_vec_element_i64(t2, get_field(s->fields, v3), 0, ES_64); + } else { + read_vec_element_i64(t0, get_field(s->fields, v2), 1, ES_64); + read_vec_element_i64(t1, get_field(s->fields, v3), 0, ES_64); + read_vec_element_i64(t2, get_field(s->fields, v3), 1, ES_64); + } + tcg_gen_extract2_i64(t0, t1, t0, right_shift); + tcg_gen_extract2_i64(t1, t2, t1, right_shift); + write_vec_element_i64(t0, get_field(s->fields, v1), 0, ES_64); + write_vec_element_i64(t1, get_field(s->fields, v1), 1, ES_64); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); + return DISAS_NEXT; +} |