@ -327,6 +327,14 @@ static void gen_addi2_i64(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 al, TCGv_i64 ah,
tcg_temp_free_i64(bh);
}
static DisasJumpType op_vbperm(DisasContext *s, DisasOps *o)
{
gen_gvec_3_ool(get_field(s, v1), get_field(s, v2), get_field(s, v3), 0,
gen_helper_gvec_vbperm);
return DISAS_NEXT;
}
static DisasJumpType op_vge(DisasContext *s, DisasOps *o)
{
const uint8_t es = s->insn->data;
@ -1771,6 +1779,56 @@ static DisasJumpType op_vm(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
static DisasJumpType op_vmsl(DisasContext *s, DisasOps *o)
{
TCGv_i64 l1, h1, l2, h2;
if (get_field(s, m4) != ES_64) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
l1 = tcg_temp_new_i64();
h1 = tcg_temp_new_i64();
l2 = tcg_temp_new_i64();
h2 = tcg_temp_new_i64();
/* Multipy both even elements from v2 and v3 */
read_vec_element_i64(l1, get_field(s, v2), 0, ES_64);
read_vec_element_i64(h1, get_field(s, v3), 0, ES_64);
tcg_gen_mulu2_i64(l1, h1, l1, h1);
/* Shift result left by one (x2) if requested */
if (extract32(get_field(s, m6), 3, 1)) {
tcg_gen_add2_i64(l1, h1, l1, h1, l1, h1);
}
/* Multipy both odd elements from v2 and v3 */
read_vec_element_i64(l2, get_field(s, v2), 1, ES_64);
read_vec_element_i64(h2, get_field(s, v3), 1, ES_64);
tcg_gen_mulu2_i64(l2, h2, l2, h2);
/* Shift result left by one (x2) if requested */
if (extract32(get_field(s, m6), 2, 1)) {
tcg_gen_add2_i64(l2, h2, l2, h2, l2, h2);
}
/* Add both intermediate results */
tcg_gen_add2_i64(l1, h1, l1, h1, l2, h2);
/* Add whole v4 */
read_vec_element_i64(h2, get_field(s, v4), 0, ES_64);
read_vec_element_i64(l2, get_field(s, v4), 1, ES_64);
tcg_gen_add2_i64(l1, h1, l1, h1, l2, h2);
/* Store final result into v1. */
write_vec_element_i64(h1, get_field(s, v1), 0, ES_64);
write_vec_element_i64(l1, get_field(s, v1), 1, ES_64);
tcg_temp_free_i64(l1);
tcg_temp_free_i64(h1);
tcg_temp_free_i64(l2);
tcg_temp_free_i64(h2);
return DISAS_NEXT;
}
static DisasJumpType op_vnn(DisasContext *s, DisasOps *o)
{
gen_gvec_fn_3(nand, ES_8, get_field(s, v1),
@ -2443,32 +2501,96 @@ static DisasJumpType op_vfa(DisasContext *s, DisasOps *o)
{
const uint8_t fpf = get_field(s, m4);
const uint8_t m5 = get_field(s, m5);
const bool se = extract32(m5, 3, 1);
gen_helper_gvec_3_ptr *fn;
if (fpf != FPF_LONG || extract32(m5, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_helper_gvec_3_ptr *fn = NULL;
switch (s->fields.op2) {
case 0xe3:
fn = se ? gen_helper_gvec_vfa64s : gen_helper_gvec_vfa64;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfa32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfa64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfa128;
}
break;
default:
break;
}
break;
case 0xe5:
fn = se ? gen_helper_gvec_vfd64s : gen_helper_gvec_vfd64;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfd32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfd64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfd128;
}
break;
default:
break;
}
break;
case 0xe7:
fn = se ? gen_helper_gvec_vfm64s : gen_helper_gvec_vfm64;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfm32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfm64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfm128;
}
break;
default:
break;
}
break;
case 0xe2:
fn = se ? gen_helper_gvec_vfs64s : gen_helper_gvec_vfs64;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfs32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfs64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfs128;
}
break;
default:
break;
}
break;
default:
g_assert_not_reached();
}
if (!fn || extract32(m5, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_gvec_3_ptr(get_field(s, v1), get_field(s, v2),
get_field(s, v3), cpu_env, 0, fn);
get_field(s, v3), cpu_env, m5 , fn);
return DISAS_NEXT;
}
@ -2476,19 +2598,41 @@ static DisasJumpType op_wfc(DisasContext *s, DisasOps *o)
{
const uint8_t fpf = get_field(s, m3);
const uint8_t m4 = get_field(s, m4);
gen_helper_gvec_2_ptr *fn = NULL;
if (fpf != FPF_LONG || m4) {
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_wfk32;
if (s->fields.op2 == 0xcb) {
fn = gen_helper_gvec_wfc32;
}
}
break;
case FPF_LONG:
fn = gen_helper_gvec_wfk64;
if (s->fields.op2 == 0xcb) {
fn = gen_helper_gvec_wfc64;
}
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_wfk128;
if (s->fields.op2 == 0xcb) {
fn = gen_helper_gvec_wfc128;
}
}
break;
default:
break;
};
if (!fn || m4) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (s->fields.op2 == 0xcb) {
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2),
cpu_env, 0, gen_helper_gvec_wfc64);
} else {
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2),
cpu_env, 0, gen_helper_gvec_wfk64);
}
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env, 0, fn);
set_cc_static(s);
return DISAS_NEXT;
}
@ -2498,46 +2642,68 @@ static DisasJumpType op_vfc(DisasContext *s, DisasOps *o)
const uint8_t fpf = get_field(s, m4);
const uint8_t m5 = get_field(s, m5);
const uint8_t m6 = get_field(s, m6);
const bool se = extract32(m5, 3, 1);
const bool cs = extract32(m6, 0, 1);
gen_helper_gvec_3_ptr *fn;
const bool sq = extract32(m5, 2, 1);
gen_helper_gvec_3_ptr *fn = NULL;
if (fpf != FPF_LONG || extract32(m5, 0, 3) || extract32(m6, 1, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (cs) {
switch (s->fields.op2) {
case 0xe8:
fn = se ? gen_helper_gvec_vfce64s_cc : gen_helper_gvec_vfce64_cc;
switch (s->fields.op2) {
case 0xe8:
switch (fpf) {
case FPF_SHORT:
fn = cs ? gen_helper_gvec_vfce32_cc : gen_helper_gvec_vfce32;
break;
case 0xeb :
fn = se ? gen_helper_gvec_vfch64s_cc : gen_helper_gvec_vfch64_cc ;
case FPF_LONG:
fn = cs ? gen_helper_gvec_vfce64_cc : gen_helper_gvec_vfce64;
break;
case 0xea :
fn = se ? gen_helper_gvec_vfche64s_cc : gen_helper_gvec_vfche64_cc ;
case FPF_EXT :
fn = cs ? gen_helper_gvec_vfce128_cc : gen_helper_gvec_vfce128 ;
break;
default:
g_assert_not_reached() ;
break ;
}
} else {
switch (s->fields.op2) {
case 0xe8:
fn = se ? gen_helper_gvec_vfce64s : gen_helper_gvec_vfce64;
break;
case 0xeb:
switch (fpf) {
case FPF_SHORT:
fn = cs ? gen_helper_gvec_vfch32_cc : gen_helper_gvec_vfch32;
break;
case 0xeb :
fn = se ? gen_helper_gvec_vfch64s : gen_helper_gvec_vfch64;
case FPF_LONG :
fn = cs ? gen_helper_gvec_vfch64_cc : gen_helper_gvec_vfch64;
break;
case 0xea :
fn = se ? gen_helper_gvec_vfche64s : gen_helper_gvec_vfche64 ;
case FPF_EXT :
fn = cs ? gen_helper_gvec_vfch128_cc : gen_helper_gvec_vfch128 ;
break;
default:
g_assert_not_reached();
break;
}
break;
case 0xea:
switch (fpf) {
case FPF_SHORT:
fn = cs ? gen_helper_gvec_vfche32_cc : gen_helper_gvec_vfche32;
break;
case FPF_LONG:
fn = cs ? gen_helper_gvec_vfche64_cc : gen_helper_gvec_vfche64;
break;
case FPF_EXT:
fn = cs ? gen_helper_gvec_vfche128_cc : gen_helper_gvec_vfche128;
break;
default:
break;
}
break;
default:
g_assert_not_reached();
}
gen_gvec_3_ptr(get_field(s, v1), get_field(s, v2),
get_field(s, v3), cpu_env, 0, fn);
if (!fn || extract32(m5, 0, 2) || extract32(m6, 1, 3) ||
(!s390_has_feat(S390_FEAT_VECTOR_ENH) & & (fpf != FPF_LONG || sq))) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_gvec_3_ptr(get_field(s, v1), get_field(s, v2), get_field(s, v3),
cpu_env, m5, fn);
if (cs) {
set_cc_static(s);
}
@ -2549,36 +2715,72 @@ static DisasJumpType op_vcdg(DisasContext *s, DisasOps *o)
const uint8_t fpf = get_field(s, m3);
const uint8_t m4 = get_field(s, m4);
const uint8_t erm = get_field(s, m5);
const bool se = extract32(m4, 3, 1);
gen_helper_gvec_2_ptr *fn;
gen_helper_gvec_2_ptr *fn = NULL;
if (fpf != FPF_LONG || extract32(m4, 0, 2) || erm > 7 || erm == 2) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
switch (s->fields.op2) {
case 0xc3:
fn = se ? gen_helper_gvec_vcdg64s : gen_helper_gvec_vcdg64;
if (fpf == FPF_LONG) {
fn = gen_helper_gvec_vcdg64;
}
break;
case 0xc1:
fn = se ? gen_helper_gvec_vcdlg64s : gen_helper_gvec_vcdlg64;
if (fpf == FPF_LONG) {
fn = gen_helper_gvec_vcdlg64;
}
break;
case 0xc2:
fn = se ? gen_helper_gvec_vcgd64s : gen_helper_gvec_vcgd64;
if (fpf == FPF_LONG) {
fn = gen_helper_gvec_vcgd64;
}
break;
case 0xc0:
fn = se ? gen_helper_gvec_vclgd64s : gen_helper_gvec_vclgd64;
if (fpf == FPF_LONG) {
fn = gen_helper_gvec_vclgd64;
}
break;
case 0xc7:
fn = se ? gen_helper_gvec_vfi64s : gen_helper_gvec_vfi64;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfi32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfi64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfi128;
}
break;
default:
break;
}
break;
case 0xc5:
fn = se ? gen_helper_gvec_vflr64s : gen_helper_gvec_vflr64;
switch (fpf) {
case FPF_LONG:
fn = gen_helper_gvec_vflr64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vflr128;
}
break;
default:
break;
}
break;
default:
g_assert_not_reached();
}
if (!fn || extract32(m4, 0, 2) || erm > 7 || erm == 2) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env,
deposit32(m4, 4, 4, erm), fn);
return DISAS_NEXT;
@ -2588,18 +2790,71 @@ static DisasJumpType op_vfll(DisasContext *s, DisasOps *o)
{
const uint8_t fpf = get_field(s, m3);
const uint8_t m4 = get_field(s, m4);
gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vfll32 ;
gen_helper_gvec_2_ptr *fn = NULL ;
if (fpf != FPF_SHORT || extract32(m4, 0, 3)) {
switch (fpf) {
case FPF_SHORT:
fn = gen_helper_gvec_vfll32;
break;
case FPF_LONG:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfll64;
}
break;
default:
break;
}
if (!fn || extract32(m4, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (extract32(m4, 3, 1)) {
fn = gen_helper_gvec_vfll32s;
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env, m4, fn);
return DISAS_NEXT;
}
static DisasJumpType op_vfmax(DisasContext *s, DisasOps *o)
{
const uint8_t fpf = get_field(s, m4);
const uint8_t m6 = get_field(s, m6);
const uint8_t m5 = get_field(s, m5);
gen_helper_gvec_3_ptr *fn;
if (m6 == 5 || m6 == 6 || m6 == 7 || m6 > 13) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env,
0, fn);
switch (fpf) {
case FPF_SHORT:
if (s->fields.op2 == 0xef) {
fn = gen_helper_gvec_vfmax32;
} else {
fn = gen_helper_gvec_vfmin32;
}
break;
case FPF_LONG:
if (s->fields.op2 == 0xef) {
fn = gen_helper_gvec_vfmax64;
} else {
fn = gen_helper_gvec_vfmin64;
}
break;
case FPF_EXT:
if (s->fields.op2 == 0xef) {
fn = gen_helper_gvec_vfmax128;
} else {
fn = gen_helper_gvec_vfmin128;
}
break;
default:
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
gen_gvec_3_ptr(get_field(s, v1), get_field(s, v2), get_field(s, v3),
cpu_env, deposit32(m5, 4, 4, m6), fn);
return DISAS_NEXT;
}
@ -2607,22 +2862,88 @@ static DisasJumpType op_vfma(DisasContext *s, DisasOps *o)
{
const uint8_t m5 = get_field(s, m5);
const uint8_t fpf = get_field(s, m6);
const bool se = extract32(m5, 3, 1);
gen_helper_gvec_4_ptr *fn;
gen_helper_gvec_4_ptr *fn = NULL;
if (fpf != FPF_LONG || extract32(m5, 0, 3)) {
switch (s->fields.op2) {
case 0x8f:
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfma32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfma64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfma128;
}
break;
default:
break;
}
break;
case 0x8e:
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfms32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfms64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfms128;
}
break;
default:
break;
}
break;
case 0x9f:
switch (fpf) {
case FPF_SHORT:
fn = gen_helper_gvec_vfnma32;
break;
case FPF_LONG:
fn = gen_helper_gvec_vfnma64;
break;
case FPF_EXT:
fn = gen_helper_gvec_vfnma128;
break;
default:
break;
}
break;
case 0x9e:
switch (fpf) {
case FPF_SHORT:
fn = gen_helper_gvec_vfnms32;
break;
case FPF_LONG:
fn = gen_helper_gvec_vfnms64;
break;
case FPF_EXT:
fn = gen_helper_gvec_vfnms128;
break;
default:
break;
}
break;
default:
g_assert_not_reached();
}
if (!fn || extract32(m5, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (s->fields.op2 == 0x8f) {
fn = se ? gen_helper_gvec_vfma64s : gen_helper_gvec_vfma64;
} else {
fn = se ? gen_helper_gvec_vfms64s : gen_helper_gvec_vfms64;
}
gen_gvec_4_ptr(get_field(s, v1), get_field(s, v2),
get_field(s, v3), get_field(s, v4), cpu_env,
0, fn);
get_field(s, v3), get_field(s, v4), cpu_env, m5, fn);
return DISAS_NEXT;
}
@ -2633,48 +2954,88 @@ static DisasJumpType op_vfpso(DisasContext *s, DisasOps *o)
const uint8_t fpf = get_field(s, m3);
const uint8_t m4 = get_field(s, m4);
const uint8_t m5 = get_field(s, m5);
const bool se = extract32(m4, 3, 1);
TCGv_i64 tmp;
if (fpf != FPF_LONG || extract32(m4, 0, 3) || m5 > 2) {
if ((fpf != FPF_LONG & & !s390_has_feat(S390_FEAT_VECTOR_ENH)) ||
extract32(m4, 0, 3) || m5 > 2) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (extract32(m4, 3, 1)) {
tmp = tcg_temp_new_i64();
read_vec_element_i64(tmp, v2, 0, ES_64);
switch (m5) {
case 0:
/* sign bit is inverted (complement) */
tcg_gen_xori_i64(tmp, tmp, 1ull < < 63 ) ;
break;
case 1:
/* sign bit is set to one (negative) */
tcg_gen_ori_i64(tmp, tmp, 1ull < < 63 ) ;
break;
case 2:
/* sign bit is set to zero (positive) */
tcg_gen_andi_i64(tmp, tmp, (1ull < < 63 ) - 1 ) ;
break;
switch (fpf) {
case FPF_SHORT:
if (!se) {
switch (m5) {
case 0:
/* sign bit is inverted (complement) */
gen_gvec_fn_2i(xori, ES_32, v1, v2, 1ull < < 31 ) ;
break;
case 1:
/* sign bit is set to one (negative) */
gen_gvec_fn_2i(ori, ES_32, v1, v2, 1ull < < 31 ) ;
break;
case 2:
/* sign bit is set to zero (positive) */
gen_gvec_fn_2i(andi, ES_32, v1, v2, (1ull < < 31 ) - 1 ) ;
break;
}
return DISAS_NEXT;
}
write_vec_element_i64(tmp, v1, 0, ES_64);
tcg_temp_free_i64(tmp);
} else {
switch (m5) {
case 0:
/* sign bit is inverted (complement) */
gen_gvec_fn_2i(xori, ES_64, v1, v2, 1ull < < 63 ) ;
break;
case 1:
/* sign bit is set to one (negative) */
gen_gvec_fn_2i(ori, ES_64, v1, v2, 1ull < < 63 ) ;
break;
case 2:
/* sign bit is set to zero (positive) */
gen_gvec_fn_2i(andi, ES_64, v1, v2, (1ull < < 63 ) - 1 ) ;
break;
break;
case FPF_LONG:
if (!se) {
switch (m5) {
case 0:
/* sign bit is inverted (complement) */
gen_gvec_fn_2i(xori, ES_64, v1, v2, 1ull < < 63 ) ;
break;
case 1:
/* sign bit is set to one (negative) */
gen_gvec_fn_2i(ori, ES_64, v1, v2, 1ull < < 63 ) ;
break;
case 2:
/* sign bit is set to zero (positive) */
gen_gvec_fn_2i(andi, ES_64, v1, v2, (1ull < < 63 ) - 1 ) ;
break;
}
return DISAS_NEXT;
}
break;
case FPF_EXT:
/* Only a single element. */
break;
default:
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
/* With a single element, we are only interested in bit 0. */
tmp = tcg_temp_new_i64();
read_vec_element_i64(tmp, v2, 0, ES_64);
switch (m5) {
case 0:
/* sign bit is inverted (complement) */
tcg_gen_xori_i64(tmp, tmp, 1ull < < 63 ) ;
break;
case 1:
/* sign bit is set to one (negative) */
tcg_gen_ori_i64(tmp, tmp, 1ull < < 63 ) ;
break;
case 2:
/* sign bit is set to zero (positive) */
tcg_gen_andi_i64(tmp, tmp, (1ull < < 63 ) - 1 ) ;
break;
}
write_vec_element_i64(tmp, v1, 0, ES_64);
if (fpf == FPF_EXT) {
read_vec_element_i64(tmp, v2, 1, ES_64);
write_vec_element_i64(tmp, v1, 1, ES_64);
}
tcg_temp_free_i64(tmp);
return DISAS_NEXT;
}
@ -2682,18 +3043,32 @@ static DisasJumpType op_vfsq(DisasContext *s, DisasOps *o)
{
const uint8_t fpf = get_field(s, m3);
const uint8_t m4 = get_field(s, m4);
gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vfsq64 ;
gen_helper_gvec_2_ptr *fn = NULL ;
if (fpf != FPF_LONG || extract32(m4, 0, 3)) {
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfsq32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vfsq64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vfsq128;
}
break;
default:
break;
}
if (!fn || extract32(m4, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (extract32(m4, 3, 1)) {
fn = gen_helper_gvec_vfsq64s;
}
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env,
0, fn);
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env, m4, fn);
return DISAS_NEXT;
}
@ -2702,17 +3077,33 @@ static DisasJumpType op_vftci(DisasContext *s, DisasOps *o)
const uint16_t i3 = get_field(s, i3);
const uint8_t fpf = get_field(s, m4);
const uint8_t m5 = get_field(s, m5);
gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vftci64;
gen_helper_gvec_2_ptr *fn = NULL;
switch (fpf) {
case FPF_SHORT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vftci32;
}
break;
case FPF_LONG:
fn = gen_helper_gvec_vftci64;
break;
case FPF_EXT:
if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
fn = gen_helper_gvec_vftci128;
}
break;
default:
break;
}
if (fpf != FPF_LONG || extract32(m5, 0, 3)) {
if (!fn || extract32(m5, 0, 3)) {
gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
if (extract32(m5, 3, 1)) {
fn = gen_helper_gvec_vftci64s;
}
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env, i3, fn);
gen_gvec_2_ptr(get_field(s, v1), get_field(s, v2), cpu_env,
deposit32(m5, 4, 12, i3), fn);
set_cc_static(s);
return DISAS_NEXT;
}