From 6b924d4afcab8d4284910483d16dcf803a24f657 Mon Sep 17 00:00:00 2001 From: Matheus Ferst Date: Wed, 29 Jun 2022 13:29:04 -0300 Subject: [PATCH] target/ppc: implement cdtbcd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the Convert Declets To Binary Coded Decimal instruction. Since libdecnumber doesn't expose the methods for direct conversion (decDigitsFromDPD, DPD2BCD, etc), a positive decimal32 with zero exponent is used as an intermediate value to convert the declets. Reviewed-by: Richard Henderson Signed-off-by: Matheus Ferst Signed-off-by: VĂ­ctor Colombo Message-Id: <20220629162904.105060-12-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/dfp_helper.c | 26 ++++++++++++++++++++++ target/ppc/helper.h | 1 + target/ppc/insn32.decode | 1 + target/ppc/translate/fixedpoint-impl.c.inc | 7 ++++++ 4 files changed, 35 insertions(+) diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index db9e994c8c..5ba74b2124 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -1392,6 +1392,32 @@ DFP_HELPER_SHIFT(DSCLIQ, 128, 1) DFP_HELPER_SHIFT(DSCRI, 64, 0) DFP_HELPER_SHIFT(DSCRIQ, 128, 0) +target_ulong helper_CDTBCD(target_ulong s) +{ + uint64_t res = 0; + uint32_t dec32, declets; + uint8_t bcd[6]; + int i, w, sh; + decNumber a; + + for (w = 1; w >= 0; w--) { + res <<= 32; + declets = extract64(s, 32 * w, 20); + if (declets) { + /* decimal32 with zero exponent and word "w" declets */ + dec32 = (0x225ULL << 20) | declets; + decimal32ToNumber((decimal32 *)&dec32, &a); + decNumberGetBCD(&a, bcd); + for (i = 0; i < a.digits; i++) { + sh = 4 * (a.digits - 1 - i); + res |= (uint64_t)bcd[i] << sh; + } + } + } + + return res; +} + target_ulong helper_CBCDTD(target_ulong s) { uint64_t res = 0; diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 583c8dd0c2..ed0641a234 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -54,6 +54,7 @@ DEF_HELPER_3(sraw, tl, env, tl, tl) DEF_HELPER_FLAGS_2(CFUGED, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(PDEPD, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(PEXTD, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(CDTBCD, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(CBCDTD, TCG_CALL_NO_RWG_SE, tl, tl) #if defined(TARGET_PPC64) DEF_HELPER_FLAGS_2(cmpeqb, TCG_CALL_NO_RWG_SE, i32, tl, tl) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index 65bcaf657f..f7653ef9d5 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -317,6 +317,7 @@ PEXTD 011111 ..... ..... ..... 0010111100 - @X ## BCD Assist ADDG6S 011111 ..... ..... ..... - 001001010 - @X +CDTBCD 011111 ..... ..... ----- 0100011010 - @X_sa CBCDTD 011111 ..... ..... ----- 0100111010 - @X_sa ### Float-Point Load Instructions diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc index 892c9d2568..cb0097bedb 100644 --- a/target/ppc/translate/fixedpoint-impl.c.inc +++ b/target/ppc/translate/fixedpoint-impl.c.inc @@ -530,6 +530,13 @@ static bool trans_ADDG6S(DisasContext *ctx, arg_X *a) return true; } +static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a) +{ + REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206); + gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]); + return true; +} + static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a) { REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);