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