qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [V2 PATCH 34/37] target-ppc: Introduce DFP Encode BCD to DP


From: Tom Musta
Subject: [Qemu-devel] [V2 PATCH 34/37] target-ppc: Introduce DFP Encode BCD to DPD
Date: Mon, 21 Apr 2014 15:55:18 -0500

Add emulation of the PowerPC Decimal Floating Point Encode Binary
Coded Decimal to Densely Packed Decimal instructions denbcd[q][.].

Signed-off-by: Tom Musta <address@hidden>
---
 target-ppc/dfp_helper.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/helper.h     |    2 +
 target-ppc/translate.c  |    4 ++
 3 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c
index 795a302..2d3491b 100644
--- a/target-ppc/dfp_helper.c
+++ b/target-ppc/dfp_helper.c
@@ -1046,3 +1046,75 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t 
*b, uint32_t sp) \
 
 DFP_HELPER_DEDPD(ddedpd, 64)
 DFP_HELPER_DEDPD(ddedpdq, 128)
+
+static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n)
+{
+    return *t >> ((n << 2) & 63) & 15;
+}
+
+static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n)
+{
+    return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15;
+}
+
+#define DFP_HELPER_ENBCD(op, size)                                           \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s)     \
+{                                                                            \
+    struct PPC_DFP dfp;                                                      \
+    uint8_t digits[32];                                                      \
+    int n = 0, offset = 0, sgn = 0, nonzero = 0;                             \
+                                                                             \
+    dfp_prepare_decimal##size(&dfp, 0, b, env);                              \
+                                                                             \
+    decNumberZero(&dfp.t);                                                   \
+                                                                             \
+    if (s) {                                                                 \
+        uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++);     \
+        switch (sgnNibble) {                                                 \
+        case 0xD:                                                            \
+        case 0xB:                                                            \
+            sgn = 1;                                                         \
+            break;                                                           \
+        case 0xC:                                                            \
+        case 0xF:                                                            \
+        case 0xA:                                                            \
+        case 0xE:                                                            \
+            sgn = 0;                                                         \
+            break;                                                           \
+        default:                                                             \
+            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
+            return;                                                          \
+        }                                                                    \
+        }                                                                    \
+                                                                             \
+    while (offset < (size)/4) {                                              \
+        n++;                                                                 \
+        digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++);    \
+        if (digits[(size)/4-n] > 10) {                                       \
+            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
+            return;                                                          \
+        } else {                                                             \
+            nonzero |= (digits[(size)/4-n] > 0);                             \
+        }                                                                    \
+    }                                                                        \
+                                                                             \
+    if (nonzero) {                                                           \
+        decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n);                     \
+    }                                                                        \
+                                                                             \
+    if (s && sgn)  {                                                         \
+        dfp.t.bits |= DECNEG;                                                \
+    }                                                                        \
+    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,              \
+                              &dfp.context);                                 \
+    dfp_set_FPRF_from_FRT(&dfp);                                             \
+    if ((size) == 64) {                                                      \
+        t[0] = dfp.t64[0];                                                   \
+    } else if ((size) == 128) {                                              \
+        t[0] = dfp.t64[HI_IDX];                                              \
+        t[1] = dfp.t64[LO_IDX];                                              \
+    }                                                                        \
+}
+
+DFP_HELPER_ENBCD(denbcd, 64)
+DFP_HELPER_ENBCD(denbcdq, 128)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 0d5acf5..98c8276 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -658,4 +658,6 @@ DEF_HELPER_3(dctfix, void, env, fprp, fprp)
 DEF_HELPER_3(dctfixq, void, env, fprp, fprp)
 DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32)
 DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32)
+DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32)
+DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32)
 #include "exec/def-helper.h"
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 395a048..6a2b51c 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -8396,6 +8396,8 @@ GEN_DFP_T_B_Rc(dctfix)
 GEN_DFP_T_B_Rc(dctfixq)
 GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
 GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
+GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
+GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
 /***                           SPE extension                               ***/
 /* Register moves */
 
@@ -11363,6 +11365,8 @@ GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
 GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
 GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
 GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
+GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
+GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
 #undef GEN_SPE
 #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
     GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, 
PPC_NONE)
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]