diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index add174b7938153a4a4e01a40c95843ef38a6f034..07868ff082ae1b5252f039db10e2045453e99721 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -1094,6 +1094,8 @@ F(0xe7b4, VGFM, VRR_c, V, 0, 0, 0, 0, vgfm, 0, IF_VEC) /* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */ F(0xe7bc, VGFMA, VRR_d, V, 0, 0, 0, 0, vgfma, 0, IF_VEC) +/* VECTOR LOAD COMPLEMENT */ + F(0xe7de, VLC, VRR_a, V, 0, 0, 0, 0, vlc, 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 1db5d6d152c6649e3caae7897b7e6cadc1bd2c80..2fc06c7cf3ef952ccba24e559fe53d237a057a59 100644 --- a/target/s390x/translate_vx.inc.c +++ b/target/s390x/translate_vx.inc.c @@ -209,6 +209,9 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr, 16) #define gen_gvec_dup64i(v1, c) \ tcg_gen_gvec_dup64i(vec_full_reg_offset(v1), 16, 16, c) +#define gen_gvec_fn_2(fn, es, v1, v2) \ + tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ + 16, 16) #define gen_gvec_fn_3(fn, es, v1, v2, v3) \ tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ vec_full_reg_offset(v3), 16, 16) @@ -1521,3 +1524,16 @@ static DisasJumpType op_vgfma(DisasContext *s, DisasOps *o) get_field(s->fields, v3), get_field(s->fields, v4), &g[es]); return DISAS_NEXT; } + +static DisasJumpType op_vlc(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m3); + + if (es > ES_64) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + gen_gvec_fn_2(neg, es, get_field(s->fields, v1), get_field(s->fields, v2)); + return DISAS_NEXT; +}