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