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