cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

dfp_helper.c (57711B)


      1/*
      2 *  PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU.
      3 *
      4 *  Copyright (c) 2014 IBM Corporation.
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "cpu.h"
     22#include "exec/helper-proto.h"
     23
     24#define DECNUMDIGITS 34
     25#include "libdecnumber/decContext.h"
     26#include "libdecnumber/decNumber.h"
     27#include "libdecnumber/dpd/decimal32.h"
     28#include "libdecnumber/dpd/decimal64.h"
     29#include "libdecnumber/dpd/decimal128.h"
     30
     31
     32static void get_dfp64(ppc_vsr_t *dst, ppc_fprp_t *dfp)
     33{
     34    dst->VsrD(1) = dfp->VsrD(0);
     35}
     36
     37static void get_dfp128(ppc_vsr_t *dst, ppc_fprp_t *dfp)
     38{
     39    dst->VsrD(0) = dfp[0].VsrD(0);
     40    dst->VsrD(1) = dfp[1].VsrD(0);
     41}
     42
     43static void set_dfp64(ppc_fprp_t *dfp, ppc_vsr_t *src)
     44{
     45    dfp->VsrD(0) = src->VsrD(1);
     46}
     47
     48static void set_dfp128(ppc_fprp_t *dfp, ppc_vsr_t *src)
     49{
     50    dfp[0].VsrD(0) = src->VsrD(0);
     51    dfp[1].VsrD(0) = src->VsrD(1);
     52}
     53
     54struct PPC_DFP {
     55    CPUPPCState *env;
     56    ppc_vsr_t vt, va, vb;
     57    decNumber t, a, b;
     58    decContext context;
     59    uint8_t crbf;
     60};
     61
     62static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr)
     63{
     64    enum rounding rnd;
     65
     66    switch ((fpscr & FP_DRN) >> FPSCR_DRN0) {
     67    case 0:
     68        rnd = DEC_ROUND_HALF_EVEN;
     69        break;
     70    case 1:
     71        rnd = DEC_ROUND_DOWN;
     72        break;
     73    case 2:
     74         rnd = DEC_ROUND_CEILING;
     75         break;
     76    case 3:
     77         rnd = DEC_ROUND_FLOOR;
     78         break;
     79    case 4:
     80         rnd = DEC_ROUND_HALF_UP;
     81         break;
     82    case 5:
     83         rnd = DEC_ROUND_HALF_DOWN;
     84         break;
     85    case 6:
     86         rnd = DEC_ROUND_UP;
     87         break;
     88    case 7:
     89         rnd = DEC_ROUND_05UP;
     90         break;
     91    default:
     92        g_assert_not_reached();
     93    }
     94
     95    decContextSetRounding(context, rnd);
     96}
     97
     98static void dfp_set_round_mode_from_immediate(uint8_t r, uint8_t rmc,
     99                                                  struct PPC_DFP *dfp)
    100{
    101    enum rounding rnd;
    102    if (r == 0) {
    103        switch (rmc & 3) {
    104        case 0:
    105            rnd = DEC_ROUND_HALF_EVEN;
    106            break;
    107        case 1:
    108            rnd = DEC_ROUND_DOWN;
    109            break;
    110        case 2:
    111            rnd = DEC_ROUND_HALF_UP;
    112            break;
    113        case 3: /* use FPSCR rounding mode */
    114            return;
    115        default:
    116            assert(0); /* cannot get here */
    117        }
    118    } else { /* r == 1 */
    119        switch (rmc & 3) {
    120        case 0:
    121            rnd = DEC_ROUND_CEILING;
    122            break;
    123        case 1:
    124            rnd = DEC_ROUND_FLOOR;
    125            break;
    126        case 2:
    127            rnd = DEC_ROUND_UP;
    128            break;
    129        case 3:
    130            rnd = DEC_ROUND_HALF_DOWN;
    131            break;
    132        default:
    133            assert(0); /* cannot get here */
    134        }
    135    }
    136    decContextSetRounding(&dfp->context, rnd);
    137}
    138
    139static void dfp_prepare_decimal64(struct PPC_DFP *dfp, ppc_fprp_t *a,
    140                                  ppc_fprp_t *b, CPUPPCState *env)
    141{
    142    decContextDefault(&dfp->context, DEC_INIT_DECIMAL64);
    143    dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
    144    dfp->env = env;
    145
    146    if (a) {
    147        get_dfp64(&dfp->va, a);
    148        decimal64ToNumber((decimal64 *)&dfp->va.VsrD(1), &dfp->a);
    149    } else {
    150        dfp->va.VsrD(1) = 0;
    151        decNumberZero(&dfp->a);
    152    }
    153
    154    if (b) {
    155        get_dfp64(&dfp->vb, b);
    156        decimal64ToNumber((decimal64 *)&dfp->vb.VsrD(1), &dfp->b);
    157    } else {
    158        dfp->vb.VsrD(1) = 0;
    159        decNumberZero(&dfp->b);
    160    }
    161}
    162
    163static void dfp_prepare_decimal128(struct PPC_DFP *dfp, ppc_fprp_t *a,
    164                                   ppc_fprp_t *b, CPUPPCState *env)
    165{
    166    decContextDefault(&dfp->context, DEC_INIT_DECIMAL128);
    167    dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
    168    dfp->env = env;
    169
    170    if (a) {
    171        get_dfp128(&dfp->va, a);
    172        decimal128ToNumber((decimal128 *)&dfp->va, &dfp->a);
    173    } else {
    174        dfp->va.VsrD(0) = dfp->va.VsrD(1) = 0;
    175        decNumberZero(&dfp->a);
    176    }
    177
    178    if (b) {
    179        get_dfp128(&dfp->vb, b);
    180        decimal128ToNumber((decimal128 *)&dfp->vb, &dfp->b);
    181    } else {
    182        dfp->vb.VsrD(0) = dfp->vb.VsrD(1) = 0;
    183        decNumberZero(&dfp->b);
    184    }
    185}
    186
    187static void dfp_finalize_decimal64(struct PPC_DFP *dfp)
    188{
    189    decimal64FromNumber((decimal64 *)&dfp->vt.VsrD(1), &dfp->t, &dfp->context);
    190}
    191
    192static void dfp_finalize_decimal128(struct PPC_DFP *dfp)
    193{
    194    decimal128FromNumber((decimal128 *)&dfp->vt, &dfp->t, &dfp->context);
    195}
    196
    197static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
    198                uint64_t enabled)
    199{
    200    dfp->env->fpscr |= (flag | FP_FX);
    201    if (dfp->env->fpscr & enabled) {
    202        dfp->env->fpscr |= FP_FEX;
    203    }
    204}
    205
    206static void dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
    207                decContext *context)
    208{
    209    uint64_t fprf = 0;
    210
    211    /* construct FPRF */
    212    switch (decNumberClass(&dfp->t, context)) {
    213    case DEC_CLASS_SNAN:
    214        fprf = 0x01;
    215        break;
    216    case DEC_CLASS_QNAN:
    217        fprf = 0x11;
    218        break;
    219    case DEC_CLASS_NEG_INF:
    220        fprf = 0x09;
    221        break;
    222    case DEC_CLASS_NEG_NORMAL:
    223        fprf = 0x08;
    224        break;
    225    case DEC_CLASS_NEG_SUBNORMAL:
    226        fprf = 0x18;
    227        break;
    228    case DEC_CLASS_NEG_ZERO:
    229        fprf = 0x12;
    230        break;
    231    case DEC_CLASS_POS_ZERO:
    232        fprf = 0x02;
    233        break;
    234    case DEC_CLASS_POS_SUBNORMAL:
    235        fprf = 0x14;
    236        break;
    237    case DEC_CLASS_POS_NORMAL:
    238        fprf = 0x04;
    239        break;
    240    case DEC_CLASS_POS_INF:
    241        fprf = 0x05;
    242        break;
    243    default:
    244        assert(0); /* should never get here */
    245    }
    246    dfp->env->fpscr &= ~FP_FPRF;
    247    dfp->env->fpscr |= (fprf << FPSCR_FPRF);
    248}
    249
    250static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
    251{
    252    dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
    253}
    254
    255static void dfp_set_FPRF_from_FRT_short(struct PPC_DFP *dfp)
    256{
    257    decContext shortContext;
    258    decContextDefault(&shortContext, DEC_INIT_DECIMAL32);
    259    dfp_set_FPRF_from_FRT_with_context(dfp, &shortContext);
    260}
    261
    262static void dfp_set_FPRF_from_FRT_long(struct PPC_DFP *dfp)
    263{
    264    decContext longContext;
    265    decContextDefault(&longContext, DEC_INIT_DECIMAL64);
    266    dfp_set_FPRF_from_FRT_with_context(dfp, &longContext);
    267}
    268
    269static void dfp_check_for_OX(struct PPC_DFP *dfp)
    270{
    271    if (dfp->context.status & DEC_Overflow) {
    272        dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
    273    }
    274}
    275
    276static void dfp_check_for_UX(struct PPC_DFP *dfp)
    277{
    278    if (dfp->context.status & DEC_Underflow) {
    279        dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
    280    }
    281}
    282
    283static void dfp_check_for_XX(struct PPC_DFP *dfp)
    284{
    285    if (dfp->context.status & DEC_Inexact) {
    286        dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
    287    }
    288}
    289
    290static void dfp_check_for_ZX(struct PPC_DFP *dfp)
    291{
    292    if (dfp->context.status & DEC_Division_by_zero) {
    293        dfp_set_FPSCR_flag(dfp, FP_ZX, FP_ZE);
    294    }
    295}
    296
    297static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
    298{
    299    if (dfp->context.status & DEC_Invalid_operation) {
    300        if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
    301            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
    302        }
    303    }
    304}
    305
    306static void dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP *dfp)
    307{
    308    if (decNumberIsSNaN(&dfp->t)) {
    309        dfp->t.bits &= ~DECSNAN;
    310        dfp->t.bits |= DECNAN;
    311        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
    312    }
    313}
    314
    315static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
    316{
    317    if (dfp->context.status & DEC_Invalid_operation) {
    318        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
    319            int same = decNumberClass(&dfp->a, &dfp->context) ==
    320                       decNumberClass(&dfp->b, &dfp->context);
    321            if ((same && testForSameSign) || (!same && !testForSameSign)) {
    322                dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
    323            }
    324        }
    325    }
    326}
    327
    328static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
    329{
    330    dfp_check_for_VXISI(dfp, 0);
    331}
    332
    333static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp)
    334{
    335    dfp_check_for_VXISI(dfp, 1);
    336}
    337
    338static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp)
    339{
    340    if (dfp->context.status & DEC_Invalid_operation) {
    341        if ((decNumberIsInfinite(&dfp->a) && decNumberIsZero(&dfp->b)) ||
    342            (decNumberIsInfinite(&dfp->b) && decNumberIsZero(&dfp->a))) {
    343            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIMZ, FP_VE);
    344        }
    345    }
    346}
    347
    348static void dfp_check_for_VXZDZ(struct PPC_DFP *dfp)
    349{
    350    if (dfp->context.status & DEC_Division_undefined) {
    351        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXZDZ, FP_VE);
    352    }
    353}
    354
    355static void dfp_check_for_VXIDI(struct PPC_DFP *dfp)
    356{
    357    if (dfp->context.status & DEC_Invalid_operation) {
    358        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
    359            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIDI, FP_VE);
    360        }
    361    }
    362}
    363
    364static void dfp_check_for_VXVC(struct PPC_DFP *dfp)
    365{
    366    if (decNumberIsNaN(&dfp->a) || decNumberIsNaN(&dfp->b)) {
    367        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXVC, FP_VE);
    368    }
    369}
    370
    371static void dfp_check_for_VXCVI(struct PPC_DFP *dfp)
    372{
    373    if ((dfp->context.status & DEC_Invalid_operation) &&
    374        (!decNumberIsSNaN(&dfp->a)) &&
    375        (!decNumberIsSNaN(&dfp->b))) {
    376        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
    377    }
    378}
    379
    380static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp)
    381{
    382    if (decNumberIsNaN(&dfp->t)) {
    383        dfp->crbf = 1;
    384    } else if (decNumberIsZero(&dfp->t)) {
    385        dfp->crbf = 2;
    386    } else if (decNumberIsNegative(&dfp->t)) {
    387        dfp->crbf = 8;
    388    } else {
    389        dfp->crbf = 4;
    390    }
    391}
    392
    393static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp)
    394{
    395    dfp->env->fpscr &= ~FP_FPCC;
    396    dfp->env->fpscr |= (dfp->crbf << FPSCR_FPCC);
    397}
    398
    399static inline void dfp_makeQNaN(decNumber *dn)
    400{
    401    dn->bits &= ~DECSPECIAL;
    402    dn->bits |= DECNAN;
    403}
    404
    405static inline int dfp_get_digit(decNumber *dn, int n)
    406{
    407    assert(DECDPUN == 3);
    408    int unit = n / DECDPUN;
    409    int dig = n % DECDPUN;
    410    switch (dig) {
    411    case 0:
    412        return dn->lsu[unit] % 10;
    413    case 1:
    414        return (dn->lsu[unit] / 10) % 10;
    415    case 2:
    416        return dn->lsu[unit] / 100;
    417    }
    418    g_assert_not_reached();
    419}
    420
    421#define DFP_HELPER_TAB(op, dnop, postprocs, size)                              \
    422void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a,               \
    423                 ppc_fprp_t *b)                                                \
    424{                                                                              \
    425    struct PPC_DFP dfp;                                                        \
    426    dfp_prepare_decimal##size(&dfp, a, b, env);                                \
    427    dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context);                                \
    428    dfp_finalize_decimal##size(&dfp);                                          \
    429    postprocs(&dfp);                                                           \
    430    set_dfp##size(t, &dfp.vt);                                                 \
    431}
    432
    433static void ADD_PPs(struct PPC_DFP *dfp)
    434{
    435    dfp_set_FPRF_from_FRT(dfp);
    436    dfp_check_for_OX(dfp);
    437    dfp_check_for_UX(dfp);
    438    dfp_check_for_XX(dfp);
    439    dfp_check_for_VXSNAN(dfp);
    440    dfp_check_for_VXISI_add(dfp);
    441}
    442
    443DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64)
    444DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128)
    445
    446static void SUB_PPs(struct PPC_DFP *dfp)
    447{
    448    dfp_set_FPRF_from_FRT(dfp);
    449    dfp_check_for_OX(dfp);
    450    dfp_check_for_UX(dfp);
    451    dfp_check_for_XX(dfp);
    452    dfp_check_for_VXSNAN(dfp);
    453    dfp_check_for_VXISI_subtract(dfp);
    454}
    455
    456DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64)
    457DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128)
    458
    459static void MUL_PPs(struct PPC_DFP *dfp)
    460{
    461    dfp_set_FPRF_from_FRT(dfp);
    462    dfp_check_for_OX(dfp);
    463    dfp_check_for_UX(dfp);
    464    dfp_check_for_XX(dfp);
    465    dfp_check_for_VXSNAN(dfp);
    466    dfp_check_for_VXIMZ(dfp);
    467}
    468
    469DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64)
    470DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128)
    471
    472static void DIV_PPs(struct PPC_DFP *dfp)
    473{
    474    dfp_set_FPRF_from_FRT(dfp);
    475    dfp_check_for_OX(dfp);
    476    dfp_check_for_UX(dfp);
    477    dfp_check_for_ZX(dfp);
    478    dfp_check_for_XX(dfp);
    479    dfp_check_for_VXSNAN(dfp);
    480    dfp_check_for_VXZDZ(dfp);
    481    dfp_check_for_VXIDI(dfp);
    482}
    483
    484DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64)
    485DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128)
    486
    487#define DFP_HELPER_BF_AB(op, dnop, postprocs, size)                            \
    488uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b)           \
    489{                                                                              \
    490    struct PPC_DFP dfp;                                                        \
    491    dfp_prepare_decimal##size(&dfp, a, b, env);                                \
    492    dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context);                                \
    493    dfp_finalize_decimal##size(&dfp);                                          \
    494    postprocs(&dfp);                                                           \
    495    return dfp.crbf;                                                           \
    496}
    497
    498static void CMPU_PPs(struct PPC_DFP *dfp)
    499{
    500    dfp_set_CRBF_from_T(dfp);
    501    dfp_set_FPCC_from_CRBF(dfp);
    502    dfp_check_for_VXSNAN(dfp);
    503}
    504
    505DFP_HELPER_BF_AB(dcmpu, decNumberCompare, CMPU_PPs, 64)
    506DFP_HELPER_BF_AB(dcmpuq, decNumberCompare, CMPU_PPs, 128)
    507
    508static void CMPO_PPs(struct PPC_DFP *dfp)
    509{
    510    dfp_set_CRBF_from_T(dfp);
    511    dfp_set_FPCC_from_CRBF(dfp);
    512    dfp_check_for_VXSNAN(dfp);
    513    dfp_check_for_VXVC(dfp);
    514}
    515
    516DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64)
    517DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128)
    518
    519#define DFP_HELPER_TSTDC(op, size)                                       \
    520uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm)      \
    521{                                                                        \
    522    struct PPC_DFP dfp;                                                  \
    523    int match = 0;                                                       \
    524                                                                         \
    525    dfp_prepare_decimal##size(&dfp, a, 0, env);                          \
    526                                                                         \
    527    match |= (dcm & 0x20) && decNumberIsZero(&dfp.a);                    \
    528    match |= (dcm & 0x10) && decNumberIsSubnormal(&dfp.a, &dfp.context); \
    529    match |= (dcm & 0x08) && decNumberIsNormal(&dfp.a, &dfp.context);    \
    530    match |= (dcm & 0x04) && decNumberIsInfinite(&dfp.a);                \
    531    match |= (dcm & 0x02) && decNumberIsQNaN(&dfp.a);                    \
    532    match |= (dcm & 0x01) && decNumberIsSNaN(&dfp.a);                    \
    533                                                                         \
    534    if (decNumberIsNegative(&dfp.a)) {                                   \
    535        dfp.crbf = match ? 0xA : 0x8;                                    \
    536    } else {                                                             \
    537        dfp.crbf = match ? 0x2 : 0x0;                                    \
    538    }                                                                    \
    539                                                                         \
    540    dfp_set_FPCC_from_CRBF(&dfp);                                        \
    541    return dfp.crbf;                                                     \
    542}
    543
    544DFP_HELPER_TSTDC(dtstdc, 64)
    545DFP_HELPER_TSTDC(dtstdcq, 128)
    546
    547#define DFP_HELPER_TSTDG(op, size)                                       \
    548uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm)      \
    549{                                                                        \
    550    struct PPC_DFP dfp;                                                  \
    551    int minexp, maxexp, nzero_digits, nzero_idx, is_negative, is_zero,   \
    552        is_extreme_exp, is_subnormal, is_normal, leftmost_is_nonzero,    \
    553        match;                                                           \
    554                                                                         \
    555    dfp_prepare_decimal##size(&dfp, a, 0, env);                          \
    556                                                                         \
    557    if ((size) == 64) {                                                  \
    558        minexp = -398;                                                   \
    559        maxexp = 369;                                                    \
    560        nzero_digits = 16;                                               \
    561        nzero_idx = 5;                                                   \
    562    } else if ((size) == 128) {                                          \
    563        minexp = -6176;                                                  \
    564        maxexp = 6111;                                                   \
    565        nzero_digits = 34;                                               \
    566        nzero_idx = 11;                                                  \
    567    }                                                                    \
    568                                                                         \
    569    is_negative = decNumberIsNegative(&dfp.a);                           \
    570    is_zero = decNumberIsZero(&dfp.a);                                   \
    571    is_extreme_exp = (dfp.a.exponent == maxexp) ||                       \
    572                     (dfp.a.exponent == minexp);                         \
    573    is_subnormal = decNumberIsSubnormal(&dfp.a, &dfp.context);           \
    574    is_normal = decNumberIsNormal(&dfp.a, &dfp.context);                 \
    575    leftmost_is_nonzero = (dfp.a.digits == nzero_digits) &&              \
    576                          (dfp.a.lsu[nzero_idx] != 0);                   \
    577    match = 0;                                                           \
    578                                                                         \
    579    match |= (dcm & 0x20) && is_zero && !is_extreme_exp;                 \
    580    match |= (dcm & 0x10) && is_zero && is_extreme_exp;                  \
    581    match |= (dcm & 0x08) &&                                             \
    582             (is_subnormal || (is_normal && is_extreme_exp));            \
    583    match |= (dcm & 0x04) && is_normal && !is_extreme_exp &&             \
    584             !leftmost_is_nonzero;                                       \
    585    match |= (dcm & 0x02) && is_normal && !is_extreme_exp &&             \
    586             leftmost_is_nonzero;                                        \
    587    match |= (dcm & 0x01) && decNumberIsSpecial(&dfp.a);                 \
    588                                                                         \
    589    if (is_negative) {                                                   \
    590        dfp.crbf = match ? 0xA : 0x8;                                    \
    591    } else {                                                             \
    592        dfp.crbf = match ? 0x2 : 0x0;                                    \
    593    }                                                                    \
    594                                                                         \
    595    dfp_set_FPCC_from_CRBF(&dfp);                                        \
    596    return dfp.crbf;                                                     \
    597}
    598
    599DFP_HELPER_TSTDG(dtstdg, 64)
    600DFP_HELPER_TSTDG(dtstdgq, 128)
    601
    602#define DFP_HELPER_TSTEX(op, size)                                       \
    603uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b)     \
    604{                                                                        \
    605    struct PPC_DFP dfp;                                                  \
    606    int expa, expb, a_is_special, b_is_special;                          \
    607                                                                         \
    608    dfp_prepare_decimal##size(&dfp, a, b, env);                          \
    609                                                                         \
    610    expa = dfp.a.exponent;                                               \
    611    expb = dfp.b.exponent;                                               \
    612    a_is_special = decNumberIsSpecial(&dfp.a);                           \
    613    b_is_special = decNumberIsSpecial(&dfp.b);                           \
    614                                                                         \
    615    if (a_is_special || b_is_special) {                                  \
    616        int atype = a_is_special ? (decNumberIsNaN(&dfp.a) ? 4 : 2) : 1; \
    617        int btype = b_is_special ? (decNumberIsNaN(&dfp.b) ? 4 : 2) : 1; \
    618        dfp.crbf = (atype ^ btype) ? 0x1 : 0x2;                          \
    619    } else if (expa < expb) {                                            \
    620        dfp.crbf = 0x8;                                                  \
    621    } else if (expa > expb) {                                            \
    622        dfp.crbf = 0x4;                                                  \
    623    } else {                                                             \
    624        dfp.crbf = 0x2;                                                  \
    625    }                                                                    \
    626                                                                         \
    627    dfp_set_FPCC_from_CRBF(&dfp);                                        \
    628    return dfp.crbf;                                                     \
    629}
    630
    631DFP_HELPER_TSTEX(dtstex, 64)
    632DFP_HELPER_TSTEX(dtstexq, 128)
    633
    634#define DFP_HELPER_TSTSF(op, size)                                       \
    635uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b)     \
    636{                                                                        \
    637    struct PPC_DFP dfp;                                                  \
    638    unsigned k;                                                          \
    639    ppc_vsr_t va;                                                        \
    640                                                                         \
    641    dfp_prepare_decimal##size(&dfp, 0, b, env);                          \
    642                                                                         \
    643    get_dfp64(&va, a);                                                   \
    644    k = va.VsrD(1) & 0x3F;                                               \
    645                                                                         \
    646    if (unlikely(decNumberIsSpecial(&dfp.b))) {                          \
    647        dfp.crbf = 1;                                                    \
    648    } else if (k == 0) {                                                 \
    649        dfp.crbf = 4;                                                    \
    650    } else if (unlikely(decNumberIsZero(&dfp.b))) {                      \
    651        /* Zero has no sig digits */                                     \
    652        dfp.crbf = 4;                                                    \
    653    } else {                                                             \
    654        unsigned nsd = dfp.b.digits;                                     \
    655        if (k < nsd) {                                                   \
    656            dfp.crbf = 8;                                                \
    657        } else if (k > nsd) {                                            \
    658            dfp.crbf = 4;                                                \
    659        } else {                                                         \
    660            dfp.crbf = 2;                                                \
    661        }                                                                \
    662    }                                                                    \
    663                                                                         \
    664    dfp_set_FPCC_from_CRBF(&dfp);                                        \
    665    return dfp.crbf;                                                     \
    666}
    667
    668DFP_HELPER_TSTSF(dtstsf, 64)
    669DFP_HELPER_TSTSF(dtstsfq, 128)
    670
    671#define DFP_HELPER_TSTSFI(op, size)                                     \
    672uint32_t helper_##op(CPUPPCState *env, uint32_t a, ppc_fprp_t *b)       \
    673{                                                                       \
    674    struct PPC_DFP dfp;                                                 \
    675    unsigned uim;                                                       \
    676                                                                        \
    677    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
    678                                                                        \
    679    uim = a & 0x3F;                                                     \
    680                                                                        \
    681    if (unlikely(decNumberIsSpecial(&dfp.b))) {                         \
    682        dfp.crbf = 1;                                                   \
    683    } else if (uim == 0) {                                              \
    684        dfp.crbf = 4;                                                   \
    685    } else if (unlikely(decNumberIsZero(&dfp.b))) {                     \
    686        /* Zero has no sig digits */                                    \
    687        dfp.crbf = 4;                                                   \
    688    } else {                                                            \
    689        unsigned nsd = dfp.b.digits;                                    \
    690        if (uim < nsd) {                                                \
    691            dfp.crbf = 8;                                               \
    692        } else if (uim > nsd) {                                         \
    693            dfp.crbf = 4;                                               \
    694        } else {                                                        \
    695            dfp.crbf = 2;                                               \
    696        }                                                               \
    697    }                                                                   \
    698                                                                        \
    699    dfp_set_FPCC_from_CRBF(&dfp);                                       \
    700    return dfp.crbf;                                                    \
    701}
    702
    703DFP_HELPER_TSTSFI(dtstsfi, 64)
    704DFP_HELPER_TSTSFI(dtstsfiq, 128)
    705
    706static void QUA_PPs(struct PPC_DFP *dfp)
    707{
    708    dfp_set_FPRF_from_FRT(dfp);
    709    dfp_check_for_XX(dfp);
    710    dfp_check_for_VXSNAN(dfp);
    711    dfp_check_for_VXCVI(dfp);
    712}
    713
    714static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp)
    715{
    716    dfp_set_round_mode_from_immediate(0, rmc, dfp);
    717    decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context);
    718    if (decNumberIsSNaN(&dfp->a)) {
    719        dfp->t = dfp->a;
    720        dfp_makeQNaN(&dfp->t);
    721    } else if (decNumberIsSNaN(&dfp->b)) {
    722        dfp->t = dfp->b;
    723        dfp_makeQNaN(&dfp->t);
    724    } else if (decNumberIsQNaN(&dfp->a)) {
    725        dfp->t = dfp->a;
    726    } else if (decNumberIsQNaN(&dfp->b)) {
    727        dfp->t = dfp->b;
    728    }
    729}
    730
    731#define DFP_HELPER_QUAI(op, size)                                       \
    732void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,        \
    733                 uint32_t te, uint32_t rmc)                             \
    734{                                                                       \
    735    struct PPC_DFP dfp;                                                 \
    736                                                                        \
    737    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
    738                                                                        \
    739    decNumberFromUInt32(&dfp.a, 1);                                     \
    740    dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3);                 \
    741                                                                        \
    742    dfp_quantize(rmc, &dfp);                                            \
    743    dfp_finalize_decimal##size(&dfp);                                   \
    744    QUA_PPs(&dfp);                                                      \
    745                                                                        \
    746    set_dfp##size(t, &dfp.vt);                                          \
    747}
    748
    749DFP_HELPER_QUAI(dquai, 64)
    750DFP_HELPER_QUAI(dquaiq, 128)
    751
    752#define DFP_HELPER_QUA(op, size)                                        \
    753void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a,        \
    754                 ppc_fprp_t *b, uint32_t rmc)                           \
    755{                                                                       \
    756    struct PPC_DFP dfp;                                                 \
    757                                                                        \
    758    dfp_prepare_decimal##size(&dfp, a, b, env);                         \
    759                                                                        \
    760    dfp_quantize(rmc, &dfp);                                            \
    761    dfp_finalize_decimal##size(&dfp);                                   \
    762    QUA_PPs(&dfp);                                                      \
    763                                                                        \
    764    set_dfp##size(t, &dfp.vt);                                          \
    765}
    766
    767DFP_HELPER_QUA(dqua, 64)
    768DFP_HELPER_QUA(dquaq, 128)
    769
    770static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax,
    771                             struct PPC_DFP *dfp)
    772{
    773    int msd_orig, msd_rslt;
    774
    775    if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) {
    776        dfp->t = dfp->b;
    777        if (decNumberIsSNaN(&dfp->b)) {
    778            dfp_makeQNaN(&dfp->t);
    779            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE);
    780        }
    781        return;
    782    }
    783
    784    /* Reround is equivalent to quantizing b with 1**E(n) where */
    785    /* n = exp(b) + numDigits(b) - reference_significance.      */
    786
    787    decNumberFromUInt32(&dfp->a, 1);
    788    dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig;
    789
    790    if (unlikely(dfp->a.exponent > xmax)) {
    791        dfp->t.digits = 0;
    792        dfp->t.bits &= ~DECNEG;
    793        dfp_makeQNaN(&dfp->t);
    794        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
    795        return;
    796    }
    797
    798    dfp_quantize(rmc, dfp);
    799
    800    msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1);
    801    msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1);
    802
    803    /* If the quantization resulted in rounding up to the next magnitude, */
    804    /* then we need to shift the significand and adjust the exponent.     */
    805
    806    if (unlikely((msd_orig == 9) && (msd_rslt == 1))) {
    807
    808        decNumber negone;
    809
    810        decNumberFromInt32(&negone, -1);
    811        decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context);
    812        dfp->t.exponent++;
    813
    814        if (unlikely(dfp->t.exponent > xmax)) {
    815            dfp_makeQNaN(&dfp->t);
    816            dfp->t.digits = 0;
    817            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
    818            /* Inhibit XX in this case */
    819            decContextClearStatus(&dfp->context, DEC_Inexact);
    820        }
    821    }
    822}
    823
    824#define DFP_HELPER_RRND(op, size)                                       \
    825void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a,        \
    826                 ppc_fprp_t *b, uint32_t rmc)                           \
    827{                                                                       \
    828    struct PPC_DFP dfp;                                                 \
    829    ppc_vsr_t va;                                                       \
    830    int32_t ref_sig;                                                    \
    831    int32_t xmax = ((size) == 64) ? 369 : 6111;                         \
    832                                                                        \
    833    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
    834                                                                        \
    835    get_dfp64(&va, a);                                                  \
    836    ref_sig = va.VsrD(1) & 0x3f;                                        \
    837                                                                        \
    838    _dfp_reround(rmc, ref_sig, xmax, &dfp);                             \
    839    dfp_finalize_decimal##size(&dfp);                                   \
    840    QUA_PPs(&dfp);                                                      \
    841                                                                        \
    842    set_dfp##size(t, &dfp.vt);                                          \
    843}
    844
    845DFP_HELPER_RRND(drrnd, 64)
    846DFP_HELPER_RRND(drrndq, 128)
    847
    848#define DFP_HELPER_RINT(op, postprocs, size)                                   \
    849void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,               \
    850             uint32_t r, uint32_t rmc)                                         \
    851{                                                                              \
    852    struct PPC_DFP dfp;                                                        \
    853                                                                               \
    854    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
    855                                                                               \
    856    dfp_set_round_mode_from_immediate(r, rmc, &dfp);                           \
    857    decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context);                    \
    858    dfp_finalize_decimal##size(&dfp);                                          \
    859    postprocs(&dfp);                                                           \
    860                                                                               \
    861    set_dfp##size(t, &dfp.vt);                                                 \
    862}
    863
    864static void RINTX_PPs(struct PPC_DFP *dfp)
    865{
    866    dfp_set_FPRF_from_FRT(dfp);
    867    dfp_check_for_XX(dfp);
    868    dfp_check_for_VXSNAN(dfp);
    869}
    870
    871DFP_HELPER_RINT(drintx, RINTX_PPs, 64)
    872DFP_HELPER_RINT(drintxq, RINTX_PPs, 128)
    873
    874static void RINTN_PPs(struct PPC_DFP *dfp)
    875{
    876    dfp_set_FPRF_from_FRT(dfp);
    877    dfp_check_for_VXSNAN(dfp);
    878}
    879
    880DFP_HELPER_RINT(drintn, RINTN_PPs, 64)
    881DFP_HELPER_RINT(drintnq, RINTN_PPs, 128)
    882
    883void helper_dctdp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
    884{
    885    struct PPC_DFP dfp;
    886    ppc_vsr_t vb;
    887    uint32_t b_short;
    888
    889    get_dfp64(&vb, b);
    890    b_short = (uint32_t)vb.VsrD(1);
    891
    892    dfp_prepare_decimal64(&dfp, 0, 0, env);
    893    decimal32ToNumber((decimal32 *)&b_short, &dfp.t);
    894    dfp_finalize_decimal64(&dfp);
    895    set_dfp64(t, &dfp.vt);
    896    dfp_set_FPRF_from_FRT(&dfp);
    897}
    898
    899void helper_dctqpq(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
    900{
    901    struct PPC_DFP dfp;
    902    ppc_vsr_t vb;
    903    dfp_prepare_decimal128(&dfp, 0, 0, env);
    904    get_dfp64(&vb, b);
    905    decimal64ToNumber((decimal64 *)&vb.VsrD(1), &dfp.t);
    906
    907    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
    908    dfp_set_FPRF_from_FRT(&dfp);
    909
    910    dfp_finalize_decimal128(&dfp);
    911    set_dfp128(t, &dfp.vt);
    912}
    913
    914void helper_drsp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
    915{
    916    struct PPC_DFP dfp;
    917    uint32_t t_short = 0;
    918    ppc_vsr_t vt;
    919    dfp_prepare_decimal64(&dfp, 0, b, env);
    920    decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context);
    921    decimal32ToNumber((decimal32 *)&t_short, &dfp.t);
    922
    923    dfp_set_FPRF_from_FRT_short(&dfp);
    924    dfp_check_for_OX(&dfp);
    925    dfp_check_for_UX(&dfp);
    926    dfp_check_for_XX(&dfp);
    927
    928    vt.VsrD(1) = (uint64_t)t_short;
    929    set_dfp64(t, &vt);
    930}
    931
    932void helper_drdpq(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
    933{
    934    struct PPC_DFP dfp;
    935    dfp_prepare_decimal128(&dfp, 0, b, env);
    936    decimal64FromNumber((decimal64 *)&dfp.vt.VsrD(1), &dfp.b, &dfp.context);
    937    decimal64ToNumber((decimal64 *)&dfp.vt.VsrD(1), &dfp.t);
    938
    939    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
    940    dfp_set_FPRF_from_FRT_long(&dfp);
    941    dfp_check_for_OX(&dfp);
    942    dfp_check_for_UX(&dfp);
    943    dfp_check_for_XX(&dfp);
    944
    945    dfp.vt.VsrD(0) = dfp.vt.VsrD(1) = 0;
    946    dfp_finalize_decimal64(&dfp);
    947    set_dfp128(t, &dfp.vt);
    948}
    949
    950#define DFP_HELPER_CFFIX(op, size)                                             \
    951void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)               \
    952{                                                                              \
    953    struct PPC_DFP dfp;                                                        \
    954    ppc_vsr_t vb;                                                              \
    955    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
    956    get_dfp64(&vb, b);                                                         \
    957    decNumberFromInt64(&dfp.t, (int64_t)vb.VsrD(1));                           \
    958    dfp_finalize_decimal##size(&dfp);                                          \
    959    CFFIX_PPs(&dfp);                                                           \
    960                                                                               \
    961    set_dfp##size(t, &dfp.vt);                                                 \
    962}
    963
    964static void CFFIX_PPs(struct PPC_DFP *dfp)
    965{
    966    dfp_set_FPRF_from_FRT(dfp);
    967    dfp_check_for_XX(dfp);
    968}
    969
    970DFP_HELPER_CFFIX(dcffix, 64)
    971DFP_HELPER_CFFIX(dcffixq, 128)
    972
    973#define DFP_HELPER_CTFIX(op, size)                                            \
    974void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)              \
    975{                                                                             \
    976    struct PPC_DFP dfp;                                                       \
    977    dfp_prepare_decimal##size(&dfp, 0, b, env);                               \
    978                                                                              \
    979    if (unlikely(decNumberIsSpecial(&dfp.b))) {                               \
    980        uint64_t invalid_flags = FP_VX | FP_VXCVI;                            \
    981        if (decNumberIsInfinite(&dfp.b)) {                                    \
    982            dfp.vt.VsrD(1) = decNumberIsNegative(&dfp.b) ? INT64_MIN :        \
    983                                                           INT64_MAX;         \
    984        } else { /* NaN */                                                    \
    985            dfp.vt.VsrD(1) = INT64_MIN;                                       \
    986            if (decNumberIsSNaN(&dfp.b)) {                                    \
    987                invalid_flags |= FP_VXSNAN;                                   \
    988            }                                                                 \
    989        }                                                                     \
    990        dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE);                       \
    991    } else if (unlikely(decNumberIsZero(&dfp.b))) {                           \
    992        dfp.vt.VsrD(1) = 0;                                                   \
    993    } else {                                                                  \
    994        decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context);               \
    995        dfp.vt.VsrD(1) = decNumberIntegralToInt64(&dfp.b, &dfp.context);      \
    996        if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) {      \
    997            dfp.vt.VsrD(1) = decNumberIsNegative(&dfp.b) ? INT64_MIN :        \
    998                                                           INT64_MAX;         \
    999            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE);                \
   1000        } else {                                                              \
   1001            dfp_check_for_XX(&dfp);                                           \
   1002        }                                                                     \
   1003    }                                                                         \
   1004                                                                              \
   1005    set_dfp64(t, &dfp.vt);                                                    \
   1006}
   1007
   1008DFP_HELPER_CTFIX(dctfix, 64)
   1009DFP_HELPER_CTFIX(dctfixq, 128)
   1010
   1011static inline void dfp_set_bcd_digit_64(ppc_vsr_t *t, uint8_t digit,
   1012                                        unsigned n)
   1013{
   1014    t->VsrD(1) |= ((uint64_t)(digit & 0xF) << (n << 2));
   1015}
   1016
   1017static inline void dfp_set_bcd_digit_128(ppc_vsr_t *t, uint8_t digit,
   1018                                         unsigned n)
   1019{
   1020    t->VsrD((n & 0x10) ? 0 : 1) |=
   1021        ((uint64_t)(digit & 0xF) << ((n & 15) << 2));
   1022}
   1023
   1024static inline void dfp_set_sign_64(ppc_vsr_t *t, uint8_t sgn)
   1025{
   1026    t->VsrD(1) <<= 4;
   1027    t->VsrD(1) |= (sgn & 0xF);
   1028}
   1029
   1030static inline void dfp_set_sign_128(ppc_vsr_t *t, uint8_t sgn)
   1031{
   1032    t->VsrD(0) <<= 4;
   1033    t->VsrD(0) |= (t->VsrD(1) >> 60);
   1034    t->VsrD(1) <<= 4;
   1035    t->VsrD(1) |= (sgn & 0xF);
   1036}
   1037
   1038#define DFP_HELPER_DEDPD(op, size)                                        \
   1039void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,          \
   1040                 uint32_t sp)                                             \
   1041{                                                                         \
   1042    struct PPC_DFP dfp;                                                   \
   1043    uint8_t digits[34];                                                   \
   1044    int i, N;                                                             \
   1045                                                                          \
   1046    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
   1047                                                                          \
   1048    decNumberGetBCD(&dfp.b, digits);                                      \
   1049    dfp.vt.VsrD(0) = dfp.vt.VsrD(1) = 0;                                  \
   1050    N = dfp.b.digits;                                                     \
   1051                                                                          \
   1052    for (i = 0; (i < N) && (i < (size)/4); i++) {                         \
   1053        dfp_set_bcd_digit_##size(&dfp.vt, digits[N - i - 1], i);          \
   1054    }                                                                     \
   1055                                                                          \
   1056    if (sp & 2) {                                                         \
   1057        uint8_t sgn;                                                      \
   1058                                                                          \
   1059        if (decNumberIsNegative(&dfp.b)) {                                \
   1060            sgn = 0xD;                                                    \
   1061        } else {                                                          \
   1062            sgn = ((sp & 1) ? 0xF : 0xC);                                 \
   1063        }                                                                 \
   1064        dfp_set_sign_##size(&dfp.vt, sgn);                                \
   1065    }                                                                     \
   1066                                                                          \
   1067    set_dfp##size(t, &dfp.vt);                                            \
   1068}
   1069
   1070DFP_HELPER_DEDPD(ddedpd, 64)
   1071DFP_HELPER_DEDPD(ddedpdq, 128)
   1072
   1073static inline uint8_t dfp_get_bcd_digit_64(ppc_vsr_t *t, unsigned n)
   1074{
   1075    return t->VsrD(1) >> ((n << 2) & 63) & 15;
   1076}
   1077
   1078static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n)
   1079{
   1080    return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15;
   1081}
   1082
   1083#define DFP_HELPER_ENBCD(op, size)                                           \
   1084void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
   1085                 uint32_t s)                                                 \
   1086{                                                                            \
   1087    struct PPC_DFP dfp;                                                      \
   1088    uint8_t digits[32];                                                      \
   1089    int n = 0, offset = 0, sgn = 0, nonzero = 0;                             \
   1090                                                                             \
   1091    dfp_prepare_decimal##size(&dfp, 0, b, env);                              \
   1092                                                                             \
   1093    decNumberZero(&dfp.t);                                                   \
   1094                                                                             \
   1095    if (s) {                                                                 \
   1096        uint8_t sgnNibble = dfp_get_bcd_digit_##size(&dfp.vb, offset++);     \
   1097        switch (sgnNibble) {                                                 \
   1098        case 0xD:                                                            \
   1099        case 0xB:                                                            \
   1100            sgn = 1;                                                         \
   1101            break;                                                           \
   1102        case 0xC:                                                            \
   1103        case 0xF:                                                            \
   1104        case 0xA:                                                            \
   1105        case 0xE:                                                            \
   1106            sgn = 0;                                                         \
   1107            break;                                                           \
   1108        default:                                                             \
   1109            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
   1110            return;                                                          \
   1111        }                                                                    \
   1112        }                                                                    \
   1113                                                                             \
   1114    while (offset < (size) / 4) {                                            \
   1115        n++;                                                                 \
   1116        digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb,           \
   1117                                                          offset++);         \
   1118        if (digits[(size) / 4 - n] > 10) {                                   \
   1119            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
   1120            return;                                                          \
   1121        } else {                                                             \
   1122            nonzero |= (digits[(size) / 4 - n] > 0);                         \
   1123        }                                                                    \
   1124    }                                                                        \
   1125                                                                             \
   1126    if (nonzero) {                                                           \
   1127        decNumberSetBCD(&dfp.t, digits + ((size) / 4) - n, n);               \
   1128    }                                                                        \
   1129                                                                             \
   1130    if (s && sgn)  {                                                         \
   1131        dfp.t.bits |= DECNEG;                                                \
   1132    }                                                                        \
   1133    dfp_finalize_decimal##size(&dfp);                                        \
   1134    dfp_set_FPRF_from_FRT(&dfp);                                             \
   1135    set_dfp##size(t, &dfp.vt);                                               \
   1136}
   1137
   1138DFP_HELPER_ENBCD(denbcd, 64)
   1139DFP_HELPER_ENBCD(denbcdq, 128)
   1140
   1141#define DFP_HELPER_XEX(op, size)                               \
   1142void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \
   1143{                                                              \
   1144    struct PPC_DFP dfp;                                        \
   1145    ppc_vsr_t vt;                                              \
   1146                                                               \
   1147    dfp_prepare_decimal##size(&dfp, 0, b, env);                \
   1148                                                               \
   1149    if (unlikely(decNumberIsSpecial(&dfp.b))) {                \
   1150        if (decNumberIsInfinite(&dfp.b)) {                     \
   1151            vt.VsrD(1) = -1;                                   \
   1152        } else if (decNumberIsSNaN(&dfp.b)) {                  \
   1153            vt.VsrD(1) = -3;                                   \
   1154        } else if (decNumberIsQNaN(&dfp.b)) {                  \
   1155            vt.VsrD(1) = -2;                                   \
   1156        } else {                                               \
   1157            assert(0);                                         \
   1158        }                                                      \
   1159        set_dfp64(t, &vt);                                     \
   1160    } else {                                                   \
   1161        if ((size) == 64) {                                    \
   1162            vt.VsrD(1) = dfp.b.exponent + 398;                 \
   1163        } else if ((size) == 128) {                            \
   1164            vt.VsrD(1) = dfp.b.exponent + 6176;                \
   1165        } else {                                               \
   1166            assert(0);                                         \
   1167        }                                                      \
   1168        set_dfp64(t, &vt);                                     \
   1169    }                                                          \
   1170}
   1171
   1172DFP_HELPER_XEX(dxex, 64)
   1173DFP_HELPER_XEX(dxexq, 128)
   1174
   1175static void dfp_set_raw_exp_64(ppc_vsr_t *t, uint64_t raw)
   1176{
   1177    t->VsrD(1) &= 0x8003ffffffffffffULL;
   1178    t->VsrD(1) |= (raw << (63 - 13));
   1179}
   1180
   1181static void dfp_set_raw_exp_128(ppc_vsr_t *t, uint64_t raw)
   1182{
   1183    t->VsrD(0) &= 0x80003fffffffffffULL;
   1184    t->VsrD(0) |= (raw << (63 - 17));
   1185}
   1186
   1187#define DFP_HELPER_IEX(op, size)                                          \
   1188void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a,          \
   1189                 ppc_fprp_t *b)                                           \
   1190{                                                                         \
   1191    struct PPC_DFP dfp;                                                   \
   1192    uint64_t raw_qnan, raw_snan, raw_inf, max_exp;                        \
   1193    ppc_vsr_t va;                                                         \
   1194    int bias;                                                             \
   1195    int64_t exp;                                                          \
   1196                                                                          \
   1197    get_dfp64(&va, a);                                                    \
   1198    exp = (int64_t)va.VsrD(1);                                            \
   1199    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
   1200                                                                          \
   1201    if ((size) == 64) {                                                   \
   1202        max_exp = 767;                                                    \
   1203        raw_qnan = 0x1F00;                                                \
   1204        raw_snan = 0x1F80;                                                \
   1205        raw_inf = 0x1E00;                                                 \
   1206        bias = 398;                                                       \
   1207    } else if ((size) == 128) {                                           \
   1208        max_exp = 12287;                                                  \
   1209        raw_qnan = 0x1f000;                                               \
   1210        raw_snan = 0x1f800;                                               \
   1211        raw_inf = 0x1e000;                                                \
   1212        bias = 6176;                                                      \
   1213    } else {                                                              \
   1214        assert(0);                                                        \
   1215    }                                                                     \
   1216                                                                          \
   1217    if (unlikely((exp < 0) || (exp > max_exp))) {                         \
   1218        dfp.vt.VsrD(0) = dfp.vb.VsrD(0);                                  \
   1219        dfp.vt.VsrD(1) = dfp.vb.VsrD(1);                                  \
   1220        if (exp == -1) {                                                  \
   1221            dfp_set_raw_exp_##size(&dfp.vt, raw_inf);                     \
   1222        } else if (exp == -3) {                                           \
   1223            dfp_set_raw_exp_##size(&dfp.vt, raw_snan);                    \
   1224        } else {                                                          \
   1225            dfp_set_raw_exp_##size(&dfp.vt, raw_qnan);                    \
   1226        }                                                                 \
   1227    } else {                                                              \
   1228        dfp.t = dfp.b;                                                    \
   1229        if (unlikely(decNumberIsSpecial(&dfp.t))) {                       \
   1230            dfp.t.bits &= ~DECSPECIAL;                                    \
   1231        }                                                                 \
   1232        dfp.t.exponent = exp - bias;                                      \
   1233        dfp_finalize_decimal##size(&dfp);                                 \
   1234    }                                                                     \
   1235    set_dfp##size(t, &dfp.vt);                                            \
   1236}
   1237
   1238DFP_HELPER_IEX(diex, 64)
   1239DFP_HELPER_IEX(diexq, 128)
   1240
   1241static void dfp_clear_lmd_from_g5msb(uint64_t *t)
   1242{
   1243
   1244    /* The most significant 5 bits of the PowerPC DFP format combine bits  */
   1245    /* from the left-most decimal digit (LMD) and the biased exponent.     */
   1246    /* This  routine clears the LMD bits while preserving the exponent     */
   1247    /*  bits.  See "Figure 80: Encoding of bits 0:4 of the G field for     */
   1248    /*  Finite Numbers" in the Power ISA for additional details.           */
   1249
   1250    uint64_t g5msb = (*t >> 58) & 0x1F;
   1251
   1252    if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
   1253       *t &= ~(7ULL << 58);
   1254    } else {
   1255       switch (g5msb & 7) {
   1256       case 0:
   1257       case 1:
   1258           g5msb = 0;
   1259           break;
   1260       case 2:
   1261       case 3:
   1262           g5msb = 0x8;
   1263           break;
   1264       case 4:
   1265       case 5:
   1266           g5msb = 0x10;
   1267           break;
   1268       case 6:
   1269           g5msb = 0x1E;
   1270           break;
   1271       case 7:
   1272           g5msb = 0x1F;
   1273           break;
   1274       }
   1275
   1276        *t &= ~(0x1fULL << 58);
   1277        *t |= (g5msb << 58);
   1278    }
   1279}
   1280
   1281#define DFP_HELPER_SHIFT(op, size, shift_left)                      \
   1282void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a,    \
   1283                 uint32_t sh)                                       \
   1284{                                                                   \
   1285    struct PPC_DFP dfp;                                             \
   1286    unsigned max_digits = ((size) == 64) ? 16 : 34;                 \
   1287                                                                    \
   1288    dfp_prepare_decimal##size(&dfp, a, 0, env);                     \
   1289                                                                    \
   1290    if (sh <= max_digits) {                                         \
   1291                                                                    \
   1292        decNumber shd;                                              \
   1293        unsigned special = dfp.a.bits & DECSPECIAL;                 \
   1294                                                                    \
   1295        if (shift_left) {                                           \
   1296            decNumberFromUInt32(&shd, sh);                          \
   1297        } else {                                                    \
   1298            decNumberFromInt32(&shd, -((int32_t)sh));               \
   1299        }                                                           \
   1300                                                                    \
   1301        dfp.a.bits &= ~DECSPECIAL;                                  \
   1302        decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context);         \
   1303                                                                    \
   1304        dfp.t.bits |= special;                                      \
   1305        if (special && (dfp.t.digits >= max_digits)) {              \
   1306            dfp.t.digits = max_digits - 1;                          \
   1307        }                                                           \
   1308                                                                    \
   1309        dfp_finalize_decimal##size(&dfp);                           \
   1310    } else {                                                        \
   1311        if ((size) == 64) {                                         \
   1312            dfp.vt.VsrD(1) = dfp.va.VsrD(1) &                       \
   1313                             0xFFFC000000000000ULL;                 \
   1314            dfp_clear_lmd_from_g5msb(&dfp.vt.VsrD(1));              \
   1315        } else {                                                    \
   1316            dfp.vt.VsrD(0) = dfp.va.VsrD(0) &                       \
   1317                             0xFFFFC00000000000ULL;                 \
   1318            dfp_clear_lmd_from_g5msb(&dfp.vt.VsrD(0));              \
   1319            dfp.vt.VsrD(1) = 0;                                     \
   1320        }                                                           \
   1321    }                                                               \
   1322                                                                    \
   1323    set_dfp##size(t, &dfp.vt);                                      \
   1324}
   1325
   1326DFP_HELPER_SHIFT(dscli, 64, 1)
   1327DFP_HELPER_SHIFT(dscliq, 128, 1)
   1328DFP_HELPER_SHIFT(dscri, 64, 0)
   1329DFP_HELPER_SHIFT(dscriq, 128, 0)