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:
parent
6addef4d27
commit
38d3690bda
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user