aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/dfp_helper.c
diff options
context:
space:
mode:
authorMatheus Ferst <matheus.ferst@eldorado.org.br>2022-06-29 13:29:03 -0300
committerDaniel Henrique Barboza <danielhb413@gmail.com>2022-07-06 10:22:38 -0300
commit38d3690bda3fe217ea72903859907916a5429c6e (patch)
treea28e2139e1c66d39bcaef4b59547747359da0933 /target/ppc/dfp_helper.c
parent6addef4d272684ba624c9fcaf66bc67e5fc4a93f (diff)
downloadqemu-38d3690bda3fe217ea72903859907916a5429c6e.zip
qemu-38d3690bda3fe217ea72903859907916a5429c6e.tar.gz
qemu-38d3690bda3fe217ea72903859907916a5429c6e.tar.bz2
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>
Diffstat (limited to 'target/ppc/dfp_helper.c')
-rw-r--r--target/ppc/dfp_helper.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index 0d01ac3..db9e994 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -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;
+}