target/s390x: Emulate CVDG

CVDG is the same as CVD, except that it converts 64 bits into 128,
rather than 32 into 64. Create a new helper, which uses Int128
wrappers.

Reported-by: Ido Plat <Ido.Plat@ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-ID: <20240205205830.6425-2-iii@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Ilya Leoshkevich 2024-02-05 21:54:53 +01:00 committed by Thomas Huth
parent 6a41a62171
commit a6e55a82e9
4 changed files with 31 additions and 0 deletions

View File

@ -89,6 +89,7 @@ DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(sqxb, TCG_CALL_NO_WG, i128, env, i128) DEF_HELPER_FLAGS_2(sqxb, TCG_CALL_NO_WG, i128, env, i128)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
DEF_HELPER_FLAGS_1(cvdg, TCG_CALL_NO_RWG_SE, i128, s64)
DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32)
DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32)

View File

@ -296,6 +296,7 @@
/* CONVERT TO DECIMAL */ /* CONVERT TO DECIMAL */
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0) C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0) C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
C(0xe32e, CVDG, RXY_a, Z, r1_o, a2, 0, 0, cvdg, 0)
/* CONVERT TO FIXED */ /* CONVERT TO FIXED */
F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP) F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP)
F(0xb399, CFDBR, RRF_e, Z, 0, f2, new, r1_32, cfdb, 0, IF_BFP) F(0xb399, CFDBR, RRF_e, Z, 0, f2, new, r1_32, cfdb, 0, IF_BFP)

View File

@ -118,6 +118,27 @@ uint64_t HELPER(cvd)(int32_t reg)
return dec; return dec;
} }
Int128 HELPER(cvdg)(int64_t reg)
{
/* positive 0 */
Int128 dec = int128_make64(0x0c);
Int128 bin = int128_makes64(reg);
Int128 base = int128_make64(10);
int shift;
if (!int128_nonneg(bin)) {
bin = int128_neg(bin);
dec = int128_make64(0x0d);
}
for (shift = 4; (shift < 128) && int128_nz(bin); shift += 4) {
dec = int128_or(dec, int128_lshift(int128_remu(bin, base), shift));
bin = int128_divu(bin, base);
}
return dec;
}
uint64_t HELPER(popcnt)(uint64_t val) uint64_t HELPER(popcnt)(uint64_t val)
{ {
/* Note that we don't fold past bytes. */ /* Note that we don't fold past bytes. */

View File

@ -2233,6 +2233,14 @@ static DisasJumpType op_cvd(DisasContext *s, DisasOps *o)
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_cvdg(DisasContext *s, DisasOps *o)
{
TCGv_i128 t = tcg_temp_new_i128();
gen_helper_cvdg(t, o->in1);
tcg_gen_qemu_st_i128(t, o->in2, get_mem_index(s), MO_TE | MO_128);
return DISAS_NEXT;
}
static DisasJumpType op_ct(DisasContext *s, DisasOps *o) static DisasJumpType op_ct(DisasContext *s, DisasOps *o)
{ {
int m3 = get_field(s, m3); int m3 = get_field(s, m3);