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 <tommu...@gmail.com> --- 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