target/ppc: implement cbcdtd

Implements the Convert Binary Coded Decimal To Declets instruction.
Since libdecnumber doesn't expose the methods for direct conversion
(decDigitsToDPD, BCD2DPD, etc.), the BCD values are converted to
decimal32 format, from which the declets are extracted.

Where the behavior is undefined, we try to match the result observed in
a POWER9 DD2.3.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br>
Signed-off-by: Víctor Colombo <victor.colombo@eldorado.org.br>
Message-Id: <20220629162904.105060-11-victor.colombo@eldorado.org.br>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
Matheus Ferst 2022-06-29 13:29:03 -03:00 committed by Daniel Henrique Barboza
parent 6addef4d27
commit 38d3690bda
4 changed files with 51 additions and 0 deletions

View File

@ -1391,3 +1391,42 @@ DFP_HELPER_SHIFT(DSCLI, 64, 1)
DFP_HELPER_SHIFT(DSCLIQ, 128, 1)
DFP_HELPER_SHIFT(DSCRI, 64, 0)
DFP_HELPER_SHIFT(DSCRIQ, 128, 0)
target_ulong helper_CBCDTD(target_ulong s)
{
uint64_t res = 0;
uint32_t dec32;
uint8_t bcd[6];
int w, i, offs;
decNumber a;
decContext context;
decContextDefault(&context, DEC_INIT_DECIMAL32);
for (w = 1; w >= 0; w--) {
res <<= 32;
decNumberZero(&a);
/* Extract each BCD field of word "w" */
for (i = 5; i >= 0; i--) {
offs = 4 * (5 - i) + 32 * w;
bcd[i] = extract64(s, offs, 4);
if (bcd[i] > 9) {
/*
* If the field value is greater than 9, the results are
* undefined. We could use a fixed value like 0 or 9, but
* an and with 9 seems to better match the hardware behavior.
*/
bcd[i] &= 9;
}
}
/* Create a decNumber with the BCD values and convert to decimal32 */
decNumberSetBCD(&a, bcd, 6);
decimal32FromNumber((decimal32 *)&dec32, &a, &context);
/* Extract the two declets from the decimal32 value */
res |= dec32 & 0xfffff;
}
return res;
}

View File

@ -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(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)
DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)

View File

@ -87,6 +87,9 @@
&X_rc rt ra rb rc:bool
@X_rc ...... rt:5 ra:5 rb:5 .......... rc:1 &X_rc
&X_sa rs ra
@X_sa ...... rs:5 ra:5 ..... .......... . &X_sa
%x_frtp 22:4 !function=times_2
%x_frap 17:4 !function=times_2
%x_frbp 12:4 !function=times_2
@ -314,6 +317,7 @@ PEXTD 011111 ..... ..... ..... 0010111100 - @X
## BCD Assist
ADDG6S 011111 ..... ..... ..... - 001001010 - @X
CBCDTD 011111 ..... ..... ----- 0100111010 - @X_sa
### Float-Point Load Instructions

View File

@ -529,3 +529,10 @@ static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
return true;
}
static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
{
REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
return true;
}