diff mbox

[36/37] target-ppc: Introduce DFP Insert Biased Exponent

Message ID 1397832641-10254-37-git-send-email-tommusta@gmail.com
State New
Headers show

Commit Message

Tom Musta April 18, 2014, 2:50 p.m. UTC
Add emulation of the PowerPC Decimal Floating Point Insert Biased
Exponent instructions diex[q][.].

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 target-ppc/dfp_helper.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/helper.h     |    2 +
 target-ppc/translate.c  |    4 +++
 3 files changed, 74 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c
index 327380e..98ced28 100644
--- a/target-ppc/dfp_helper.c
+++ b/target-ppc/dfp_helper.c
@@ -1162,3 +1162,71 @@  void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)   \
 
 DFP_HELPER_XEX(dxex, 64)
 DFP_HELPER_XEX(dxexq, 128)
+
+static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw)
+{
+    *t &= 0x8003ffffffffffffULL;
+    *t |= (raw << (63-13));
+}
+
+static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw)
+{
+    t[HI_IDX] &= 0x80003fffffffffffULL;
+    t[HI_IDX] |= (raw << (63-17));
+}
+
+#define DFP_HELPER_IEX(op, size)                                          \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
+{                                                                         \
+    struct PPC_DFP dfp;                                                   \
+    uint64_t raw_qnan, raw_snan, raw_inf, max_exp;                        \
+    int bias;                                                             \
+    int64_t exp = *((int64_t *)a);                                        \
+                                                                          \
+    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
+                                                                          \
+    if ((size) == 64) {                                                   \
+        max_exp = 767;                                                    \
+        raw_qnan = 0x1F00;                                                \
+        raw_snan = 0x1F80;                                                \
+        raw_inf = 0x1E00;                                                 \
+        bias = 398;                                                       \
+    } else if ((size) == 128) {                                           \
+        max_exp = 12287;                                                  \
+        raw_qnan = 0x1f000;                                               \
+        raw_snan = 0x1f800;                                               \
+        raw_inf = 0x1e000;                                                \
+        bias = 6176;                                                      \
+    } else {                                                              \
+        assert(0);                                                        \
+    }                                                                     \
+                                                                          \
+    if (unlikely((exp < 0) || (exp > max_exp))) {                         \
+        dfp.t64[0] = dfp.b64[0];                                          \
+        dfp.t64[1] = dfp.b64[1];                                          \
+        if (exp == -1) {                                                  \
+            dfp_set_raw_exp_##size(dfp.t64, raw_inf);                     \
+        } else if (exp == -3) {                                           \
+            dfp_set_raw_exp_##size(dfp.t64, raw_snan);                    \
+        } else {                                                          \
+            dfp_set_raw_exp_##size(dfp.t64, raw_qnan);                    \
+        }                                                                 \
+    } else {                                                              \
+        dfp.t = dfp.b;                                                    \
+        if (unlikely(decNumberIsSpecial(&dfp.t))) {                       \
+            dfp.t.bits &= ~DECSPECIAL;                                    \
+        }                                                                 \
+        dfp.t.exponent = exp - bias;                                      \
+        decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,       \
+                                  &dfp.context);                          \
+    }                                                                     \
+    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_IEX(diex, 64)
+DFP_HELPER_IEX(diexq, 128)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 77da769..03c86ce 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -662,4 +662,6 @@  DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32)
 DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32)
 DEF_HELPER_3(dxex, void, env, fprp, fprp)
 DEF_HELPER_3(dxexq, void, env, fprp, fprp)
+DEF_HELPER_4(diex, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp)
 #include "exec/def-helper.h"
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index a975505..7307345 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -8400,6 +8400,8 @@  GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
 GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
 GEN_DFP_T_B_Rc(dxex)
 GEN_DFP_T_B_Rc(dxexq)
+GEN_DFP_T_A_B_Rc(diex)
+GEN_DFP_T_A_B_Rc(diexq)
 /***                           SPE extension                               ***/
 /* Register moves */
 
@@ -11371,6 +11373,8 @@  GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
 GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
 GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
 GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
+GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
+GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
 #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)