qemu/target/ppc/dfp_helper.c
<<
>>
Prefs
   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)
1330