qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC 11/12] target-ppc: Introduce DFP Post Processor Utilit


From: Tom Musta
Subject: [Qemu-devel] [RFC 11/12] target-ppc: Introduce DFP Post Processor Utilities
Date: Thu, 13 Mar 2014 10:13:07 -0500

This patch adds post-processing utilities to the PowerPC Decimal Floating
Point (DFP) helper code.  Post-processors are small routines that execute
after a preliminary DFP result is computed.  They are used, among other
things, to compute status bits.

This patch defines a function type for post processors as well as a
generic routine to run a list (array) of post-processors.  It also
adds several post processors that will be used in subsequent
instructions.

NOTE: This is not the complete set of post processors; it is the minimal
set required to demonstrate the two instructions implemented in this
patch series.

Signed-off-by: Tom Musta <address@hidden>
---
 target-ppc/dfp_helper.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 140 insertions(+), 0 deletions(-)

diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c
index 3c5988a..a3381ef 100644
--- a/target-ppc/dfp_helper.c
+++ b/target-ppc/dfp_helper.c
@@ -103,9 +103,149 @@ static void ppc_dfp_prepare_decimal128_fra_frb(struct 
PPC_DFP *dfp, uint64_t *a,
     decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b);
 }
 
+#define FP_FX       (1ull << FPSCR_FX)
+#define FP_FEX      (1ull << FPSCR_FEX)
+#define FP_OX       (1ull << FPSCR_OX)
+#define FP_OE       (1ull << FPSCR_OE)
+#define FP_UX       (1ull << FPSCR_UX)
+#define FP_UE       (1ull << FPSCR_UE)
+#define FP_XX       (1ull << FPSCR_XX)
+#define FP_XE       (1ull << FPSCR_XE)
+#define FP_VX       (1ull << FPSCR_VX)
+#define FP_VXSNAN   (1ull << FPSCR_VXSNAN)
+#define FP_VXISI    (1ull << FPSCR_VXISI)
+#define FP_VE       (1ull << FPSCR_VE)
+#define FP_FI       (1ull << FPSCR_FI)
+
+static void ppc_dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
+                uint64_t enabled)
+{
+    dfp->env->fpscr |= (flag | FP_FX);
+    if (dfp->env->fpscr & enabled) {
+        dfp->env->fpscr |= FP_FEX;
+    }
+}
+
+typedef void (*PPC_DFP_PostProc)(struct PPC_DFP *);
+
+static void ppc_dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
+                decContext *context)
+{
+    uint64_t fprf = 0;
+
+    /* construct FPRF */
+    switch (decNumberClass(&dfp->t, context)) {
+    case DEC_CLASS_SNAN:
+        fprf = 0x01;
+        break;
+    case DEC_CLASS_QNAN:
+        fprf = 0x11;
+        break;
+    case DEC_CLASS_NEG_INF:
+        fprf = 0x09;
+        break;
+    case DEC_CLASS_NEG_NORMAL:
+        fprf = 0x08;
+        break;
+    case DEC_CLASS_NEG_SUBNORMAL:
+        fprf = 0x18;
+        break;
+    case DEC_CLASS_NEG_ZERO:
+        fprf = 0x12;
+        break;
+    case DEC_CLASS_POS_ZERO:
+        fprf = 0x02;
+        break;
+    case DEC_CLASS_POS_SUBNORMAL:
+        fprf = 0x14;
+        break;
+    case DEC_CLASS_POS_NORMAL:
+        fprf = 0x04;
+        break;
+    case DEC_CLASS_POS_INF:
+        fprf = 0x05;
+        break;
+    default:
+        assert(0); /* should never get here */
+    }
+    dfp->env->fpscr &= ~(0x1F << 12);
+    dfp->env->fpscr |= (fprf << 12);
+}
+
+static void ppc_dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
+{
+    ppc_dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
+}
+
+static void ppc_dfp_check_for_OX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Overflow) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
+    }
+}
+
+static void ppc_dfp_check_for_UX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Underflow) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
+    }
+}
+
+static void ppc_dfp_check_for_XX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Inexact) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
+    }
+}
+
+static void ppc_dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Invalid_operation) {
+        if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
+            ppc_dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
+        }
+    }
+}
+
+static void ppc_dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
+{
+    if (dfp->context.status & DEC_Invalid_operation) {
+        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
+            int same = decNumberClass(&dfp->a, &dfp->context) ==
+                       decNumberClass(&dfp->b, &dfp->context);
+            if ((same && testForSameSign) || (!same && !testForSameSign)) {
+                ppc_dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
+            }
+        }
+    }
+}
+
+static void ppc_dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
+{
+    ppc_dfp_check_for_VXISI(dfp, 0);
+}
+
+static void ppc_dfp_run_post_processors(struct PPC_DFP *dfp,
+                PPC_DFP_PostProc post_processors[], const size_t n)
+{
+    int i;
+
+    for (i = 0; i < n; i++) {
+        post_processors[i](dfp);
+    }
+}
+
+
 void *_TmpAvoidDefinedButNotUsedWarnings_[] = {
     (void *)ppc_dfp_prepare_decimal64_fra_frb,
     (void *)ppc_dfp_prepare_decimal128_fra_frb,
+    (void *)ppc_dfp_run_post_processors,
+    (void *)ppc_dfp_set_FPRF_from_FRT,
+    (void *)ppc_dfp_check_for_OX,
+    (void *)ppc_dfp_check_for_UX,
+    (void *)ppc_dfp_check_for_XX,
+    (void *)ppc_dfp_check_for_VXSNAN,
+    (void *)ppc_dfp_check_for_VXISI_add,
 };
 
 
-- 
1.7.1




reply via email to

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