s390x/tcg: Implement VECTOR ELEMENT SHIFT
We can use all the fancy new vector helpers implemented by Richard. One important thing to take care of is always to properly mask of unused bits from the shift count. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com>
This commit is contained in:
parent
5c4b0ab460
commit
5f164905b2
|
@ -1151,6 +1151,15 @@
|
|||
F(0xe733, VERLL, VRS_a, V, la2, 0, 0, 0, verll, 0, IF_VEC)
|
||||
/* VECTOR ELEMENT ROTATE AND INSERT UNDER MASK */
|
||||
F(0xe772, VERIM, VRI_d, V, 0, 0, 0, 0, verim, 0, IF_VEC)
|
||||
/* VECTOR ELEMENT SHIFT LEFT */
|
||||
F(0xe770, VESLV, VRR_c, V, 0, 0, 0, 0, vesv, 0, IF_VEC)
|
||||
F(0xe730, VESL, VRS_a, V, la2, 0, 0, 0, ves, 0, IF_VEC)
|
||||
/* VECTOR ELEMENT SHIFT RIGHT ARITHMETIC */
|
||||
F(0xe77a, VESRAV, VRR_c, V, 0, 0, 0, 0, vesv, 0, IF_VEC)
|
||||
F(0xe73a, VESRA, VRS_a, V, la2, 0, 0, 0, ves, 0, IF_VEC)
|
||||
/* VECTOR ELEMENT SHIFT RIGHT LOGICAL */
|
||||
F(0xe778, VESRLV, VRR_c, V, 0, 0, 0, 0, vesv, 0, IF_VEC)
|
||||
F(0xe738, VESRL, VRS_a, V, la2, 0, 0, 0, ves, 0, IF_VEC)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* COMPARE AND SWAP AND PURGE */
|
||||
|
|
|
@ -218,6 +218,12 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr,
|
|||
#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_2i(fn, es, v1, v2, c) \
|
||||
tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
|
||||
c, 16, 16)
|
||||
#define gen_gvec_fn_2s(fn, es, v1, v2, s) \
|
||||
tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
|
||||
s, 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)
|
||||
|
@ -1956,3 +1962,81 @@ static DisasJumpType op_verim(DisasContext *s, DisasOps *o)
|
|||
get_field(s->fields, v3), i4, &g[es]);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
static DisasJumpType op_vesv(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
const uint8_t es = get_field(s->fields, m4);
|
||||
const uint8_t v1 = get_field(s->fields, v1);
|
||||
const uint8_t v2 = get_field(s->fields, v2);
|
||||
const uint8_t v3 = get_field(s->fields, v3);
|
||||
|
||||
if (es > ES_64) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return DISAS_NORETURN;
|
||||
}
|
||||
|
||||
switch (s->fields->op2) {
|
||||
case 0x70:
|
||||
gen_gvec_fn_3(shlv, es, v1, v2, v3);
|
||||
break;
|
||||
case 0x7a:
|
||||
gen_gvec_fn_3(sarv, es, v1, v2, v3);
|
||||
break;
|
||||
case 0x78:
|
||||
gen_gvec_fn_3(shrv, es, v1, v2, v3);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
static DisasJumpType op_ves(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
const uint8_t es = get_field(s->fields, m4);
|
||||
const uint8_t d2 = get_field(s->fields, d2) &
|
||||
(NUM_VEC_ELEMENT_BITS(es) - 1);
|
||||
const uint8_t v1 = get_field(s->fields, v1);
|
||||
const uint8_t v3 = get_field(s->fields, v3);
|
||||
TCGv_i32 shift;
|
||||
|
||||
if (es > ES_64) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return DISAS_NORETURN;
|
||||
}
|
||||
|
||||
if (likely(!get_field(s->fields, b2))) {
|
||||
switch (s->fields->op2) {
|
||||
case 0x30:
|
||||
gen_gvec_fn_2i(shli, es, v1, v3, d2);
|
||||
break;
|
||||
case 0x3a:
|
||||
gen_gvec_fn_2i(sari, es, v1, v3, d2);
|
||||
break;
|
||||
case 0x38:
|
||||
gen_gvec_fn_2i(shri, es, v1, v3, d2);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
shift = tcg_temp_new_i32();
|
||||
tcg_gen_extrl_i64_i32(shift, o->addr1);
|
||||
tcg_gen_andi_i32(shift, shift, NUM_VEC_ELEMENT_BITS(es) - 1);
|
||||
switch (s->fields->op2) {
|
||||
case 0x30:
|
||||
gen_gvec_fn_2s(shls, es, v1, v3, shift);
|
||||
break;
|
||||
case 0x3a:
|
||||
gen_gvec_fn_2s(sars, es, v1, v3, shift);
|
||||
break;
|
||||
case 0x38:
|
||||
gen_gvec_fn_2s(shrs, es, v1, v3, shift);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
tcg_temp_free_i32(shift);
|
||||
}
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue