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
 650static void QUA_PPs(struct PPC_DFP *dfp)
 651{
 652    dfp_set_FPRF_from_FRT(dfp);
 653    dfp_check_for_XX(dfp);
 654    dfp_check_for_VXSNAN(dfp);
 655    dfp_check_for_VXCVI(dfp);
 656}
 657
 658static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp)
 659{
 660    dfp_set_round_mode_from_immediate(0, rmc, dfp);
 661    decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context);
 662    if (decNumberIsSNaN(&dfp->a)) {
 663        dfp->t = dfp->a;
 664        dfp_makeQNaN(&dfp->t);
 665    } else if (decNumberIsSNaN(&dfp->b)) {
 666        dfp->t = dfp->b;
 667        dfp_makeQNaN(&dfp->t);
 668    } else if (decNumberIsQNaN(&dfp->a)) {
 669        dfp->t = dfp->a;
 670    } else if (decNumberIsQNaN(&dfp->b)) {
 671        dfp->t = dfp->b;
 672    }
 673}
 674
 675#define DFP_HELPER_QUAI(op, size)                                       \
 676void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b,            \
 677                 uint32_t te, uint32_t rmc)                             \
 678{                                                                       \
 679    struct PPC_DFP dfp;                                                 \
 680                                                                        \
 681    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
 682                                                                        \
 683    decNumberFromUInt32(&dfp.a, 1);                                     \
 684    dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3);                 \
 685                                                                        \
 686    dfp_quantize(rmc, &dfp);                                            \
 687    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
 688                              &dfp.context);                            \
 689    QUA_PPs(&dfp);                                                      \
 690                                                                        \
 691    if (size == 64) {                                                   \
 692        t[0] = dfp.t64[0];                                              \
 693    } else if (size == 128) {                                           \
 694        t[0] = dfp.t64[HI_IDX];                                         \
 695        t[1] = dfp.t64[LO_IDX];                                         \
 696    }                                                                   \
 697}
 698
 699DFP_HELPER_QUAI(dquai, 64)
 700DFP_HELPER_QUAI(dquaiq, 128)
 701
 702#define DFP_HELPER_QUA(op, size)                                        \
 703void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,            \
 704                 uint64_t *b, uint32_t rmc)                             \
 705{                                                                       \
 706    struct PPC_DFP dfp;                                                 \
 707                                                                        \
 708    dfp_prepare_decimal##size(&dfp, a, b, env);                         \
 709                                                                        \
 710    dfp_quantize(rmc, &dfp);                                            \
 711    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
 712                              &dfp.context);                            \
 713    QUA_PPs(&dfp);                                                      \
 714                                                                        \
 715    if (size == 64) {                                                   \
 716        t[0] = dfp.t64[0];                                              \
 717    } else if (size == 128) {                                           \
 718        t[0] = dfp.t64[HI_IDX];                                         \
 719        t[1] = dfp.t64[LO_IDX];                                         \
 720    }                                                                   \
 721}
 722
 723DFP_HELPER_QUA(dqua, 64)
 724DFP_HELPER_QUA(dquaq, 128)
 725
 726static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax,
 727                             struct PPC_DFP *dfp)
 728{
 729    int msd_orig, msd_rslt;
 730
 731    if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) {
 732        dfp->t = dfp->b;
 733        if (decNumberIsSNaN(&dfp->b)) {
 734            dfp_makeQNaN(&dfp->t);
 735            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE);
 736        }
 737        return;
 738    }
 739
 740    /* Reround is equivalent to quantizing b with 1**E(n) where */
 741    /* n = exp(b) + numDigits(b) - reference_significance.      */
 742
 743    decNumberFromUInt32(&dfp->a, 1);
 744    dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig;
 745
 746    if (unlikely(dfp->a.exponent > xmax)) {
 747        dfp->t.digits = 0;
 748        dfp->t.bits &= ~DECNEG;
 749        dfp_makeQNaN(&dfp->t);
 750        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
 751        return;
 752    }
 753
 754    dfp_quantize(rmc, dfp);
 755
 756    msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1);
 757    msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1);
 758
 759    /* If the quantization resulted in rounding up to the next magnitude, */
 760    /* then we need to shift the significand and adjust the exponent.     */
 761
 762    if (unlikely((msd_orig == 9) && (msd_rslt == 1))) {
 763
 764        decNumber negone;
 765
 766        decNumberFromInt32(&negone, -1);
 767        decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context);
 768        dfp->t.exponent++;
 769
 770        if (unlikely(dfp->t.exponent > xmax)) {
 771            dfp_makeQNaN(&dfp->t);
 772            dfp->t.digits = 0;
 773            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
 774            /* Inhibit XX in this case */
 775            decContextClearStatus(&dfp->context, DEC_Inexact);
 776        }
 777    }
 778}
 779
 780#define DFP_HELPER_RRND(op, size)                                       \
 781void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,            \
 782                 uint64_t *b, uint32_t rmc)                             \
 783{                                                                       \
 784    struct PPC_DFP dfp;                                                 \
 785    int32_t ref_sig = *a & 0x3F;                                        \
 786    int32_t xmax = ((size) == 64) ? 369 : 6111;                         \
 787                                                                        \
 788    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
 789                                                                        \
 790    _dfp_reround(rmc, ref_sig, xmax, &dfp);                             \
 791    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
 792                              &dfp.context);                            \
 793    QUA_PPs(&dfp);                                                      \
 794                                                                        \
 795    if (size == 64) {                                                   \
 796        t[0] = dfp.t64[0];                                              \
 797    } else if (size == 128) {                                           \
 798        t[0] = dfp.t64[HI_IDX];                                         \
 799        t[1] = dfp.t64[LO_IDX];                                         \
 800    }                                                                   \
 801}
 802
 803DFP_HELPER_RRND(drrnd, 64)
 804DFP_HELPER_RRND(drrndq, 128)
 805
 806#define DFP_HELPER_RINT(op, postprocs, size)                                   \
 807void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b,                   \
 808             uint32_t r, uint32_t rmc)                                         \
 809{                                                                              \
 810    struct PPC_DFP dfp;                                                        \
 811                                                                               \
 812    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
 813                                                                               \
 814    dfp_set_round_mode_from_immediate(r, rmc, &dfp);                           \
 815    decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context);                    \
 816    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
 817    postprocs(&dfp);                                                           \
 818                                                                               \
 819    if (size == 64) {                                                          \
 820        t[0] = dfp.t64[0];                                                     \
 821    } else if (size == 128) {                                                  \
 822        t[0] = dfp.t64[HI_IDX];                                                \
 823        t[1] = dfp.t64[LO_IDX];                                                \
 824    }                                                                          \
 825}
 826
 827static void RINTX_PPs(struct PPC_DFP *dfp)
 828{
 829    dfp_set_FPRF_from_FRT(dfp);
 830    dfp_check_for_XX(dfp);
 831    dfp_check_for_VXSNAN(dfp);
 832}
 833
 834DFP_HELPER_RINT(drintx, RINTX_PPs, 64)
 835DFP_HELPER_RINT(drintxq, RINTX_PPs, 128)
 836
 837static void RINTN_PPs(struct PPC_DFP *dfp)
 838{
 839    dfp_set_FPRF_from_FRT(dfp);
 840    dfp_check_for_VXSNAN(dfp);
 841}
 842
 843DFP_HELPER_RINT(drintn, RINTN_PPs, 64)
 844DFP_HELPER_RINT(drintnq, RINTN_PPs, 128)
 845
 846void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b)
 847{
 848    struct PPC_DFP dfp;
 849    uint32_t b_short = *b;
 850    dfp_prepare_decimal64(&dfp, 0, 0, env);
 851    decimal32ToNumber((decimal32 *)&b_short, &dfp.t);
 852    decimal64FromNumber((decimal64 *)t, &dfp.t, &dfp.context);
 853    dfp_set_FPRF_from_FRT(&dfp);
 854}
 855
 856void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
 857{
 858    struct PPC_DFP dfp;
 859    dfp_prepare_decimal128(&dfp, 0, 0, env);
 860    decimal64ToNumber((decimal64 *)b, &dfp.t);
 861
 862    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
 863    dfp_set_FPRF_from_FRT(&dfp);
 864
 865    decimal128FromNumber((decimal128 *)&dfp.t64, &dfp.t, &dfp.context);
 866    t[0] = dfp.t64[HI_IDX];
 867    t[1] = dfp.t64[LO_IDX];
 868}
 869
 870void helper_drsp(CPUPPCState *env, uint64_t *t, uint64_t *b)
 871{
 872    struct PPC_DFP dfp;
 873    uint32_t t_short = 0;
 874    dfp_prepare_decimal64(&dfp, 0, b, env);
 875    decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context);
 876    decimal32ToNumber((decimal32 *)&t_short, &dfp.t);
 877
 878    dfp_set_FPRF_from_FRT_short(&dfp);
 879    dfp_check_for_OX(&dfp);
 880    dfp_check_for_UX(&dfp);
 881    dfp_check_for_XX(&dfp);
 882
 883    *t = t_short;
 884}
 885
 886void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
 887{
 888    struct PPC_DFP dfp;
 889    dfp_prepare_decimal128(&dfp, 0, b, env);
 890    decimal64FromNumber((decimal64 *)&dfp.t64, &dfp.b, &dfp.context);
 891    decimal64ToNumber((decimal64 *)&dfp.t64, &dfp.t);
 892
 893    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
 894    dfp_set_FPRF_from_FRT_long(&dfp);
 895    dfp_check_for_OX(&dfp);
 896    dfp_check_for_UX(&dfp);
 897    dfp_check_for_XX(&dfp);
 898
 899    decimal64FromNumber((decimal64 *)dfp.t64, &dfp.t, &dfp.context);
 900    t[0] = dfp.t64[0];
 901    t[1] = 0;
 902}
 903
 904#define DFP_HELPER_CFFIX(op, size)                                             \
 905void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)                   \
 906{                                                                              \
 907    struct PPC_DFP dfp;                                                        \
 908    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
 909    decNumberFromInt64(&dfp.t, (int64_t)(*b));                                 \
 910    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
 911    CFFIX_PPs(&dfp);                                                           \
 912                                                                               \
 913    if (size == 64) {                                                          \
 914        t[0] = dfp.t64[0];                                                     \
 915    } else if (size == 128) {                                                  \
 916        t[0] = dfp.t64[HI_IDX];                                                \
 917        t[1] = dfp.t64[LO_IDX];                                                \
 918    }                                                                          \
 919}
 920
 921static void CFFIX_PPs(struct PPC_DFP *dfp)
 922{
 923    dfp_set_FPRF_from_FRT(dfp);
 924    dfp_check_for_XX(dfp);
 925}
 926
 927DFP_HELPER_CFFIX(dcffix, 64)
 928DFP_HELPER_CFFIX(dcffixq, 128)
 929
 930#define DFP_HELPER_CTFIX(op, size)                                            \
 931void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)                  \
 932{                                                                             \
 933    struct PPC_DFP dfp;                                                       \
 934    dfp_prepare_decimal##size(&dfp, 0, b, env);                               \
 935                                                                              \
 936    if (unlikely(decNumberIsSpecial(&dfp.b))) {                               \
 937        uint64_t invalid_flags = FP_VX | FP_VXCVI;                            \
 938        if (decNumberIsInfinite(&dfp.b)) {                                    \
 939            dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
 940        } else { /* NaN */                                                    \
 941            dfp.t64[0] = INT64_MIN;                                           \
 942            if (decNumberIsSNaN(&dfp.b)) {                                    \
 943                invalid_flags |= FP_VXSNAN;                                   \
 944            }                                                                 \
 945        }                                                                     \
 946        dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE);                       \
 947    } else if (unlikely(decNumberIsZero(&dfp.b))) {                           \
 948        dfp.t64[0] = 0;                                                       \
 949    } else {                                                                  \
 950        decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context);               \
 951        dfp.t64[0] = decNumberIntegralToInt64(&dfp.b, &dfp.context);          \
 952        if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) {      \
 953            dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
 954            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE);                \
 955        } else {                                                              \
 956            dfp_check_for_XX(&dfp);                                           \
 957        }                                                                     \
 958    }                                                                         \
 959                                                                              \
 960    *t = dfp.t64[0];                                                          \
 961}
 962
 963DFP_HELPER_CTFIX(dctfix, 64)
 964DFP_HELPER_CTFIX(dctfixq, 128)
 965
 966static inline void dfp_set_bcd_digit_64(uint64_t *t, uint8_t digit,
 967                                            unsigned n)
 968{
 969    *t |= ((uint64_t)(digit & 0xF) << (n << 2));
 970}
 971
 972static inline void dfp_set_bcd_digit_128(uint64_t *t, uint8_t digit,
 973                                             unsigned n)
 974{
 975    t[(n & 0x10) ? HI_IDX : LO_IDX] |=
 976        ((uint64_t)(digit & 0xF) << ((n & 15) << 2));
 977}
 978
 979static inline void dfp_set_sign_64(uint64_t *t, uint8_t sgn)
 980{
 981    *t <<= 4;
 982    *t |= (sgn & 0xF);
 983}
 984
 985static inline void dfp_set_sign_128(uint64_t *t, uint8_t sgn)
 986{
 987    t[HI_IDX] <<= 4;
 988    t[HI_IDX] |= (t[LO_IDX] >> 60);
 989    t[LO_IDX] <<= 4;
 990    t[LO_IDX] |= (sgn & 0xF);
 991}
 992
 993#define DFP_HELPER_DEDPD(op, size)                                        \
 994void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \
 995{                                                                         \
 996    struct PPC_DFP dfp;                                                   \
 997    uint8_t digits[34];                                                   \
 998    int i, N;                                                             \
 999                                                                          \
1000    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
1001                                                                          \
1002    decNumberGetBCD(&dfp.b, digits);                                      \
1003    dfp.t64[0] = dfp.t64[1] = 0;                                          \
1004    N = dfp.b.digits;                                                     \
1005                                                                          \
1006    for (i = 0; (i < N) && (i < (size)/4); i++) {                         \
1007        dfp_set_bcd_digit_##size(dfp.t64, digits[N-i-1], i);              \
1008    }                                                                     \
1009                                                                          \
1010    if (sp & 2) {                                                         \
1011        uint8_t sgn;                                                      \
1012                                                                          \
1013        if (decNumberIsNegative(&dfp.b)) {                                \
1014            sgn = 0xD;                                                    \
1015        } else {                                                          \
1016            sgn = ((sp & 1) ? 0xF : 0xC);                                 \
1017        }                                                                 \
1018        dfp_set_sign_##size(dfp.t64, sgn);                                \
1019    }                                                                     \
1020                                                                          \
1021    if (size == 64) {                                                     \
1022        t[0] = dfp.t64[0];                                                \
1023    } else if (size == 128) {                                             \
1024        t[0] = dfp.t64[HI_IDX];                                           \
1025        t[1] = dfp.t64[LO_IDX];                                           \
1026    }                                                                     \
1027}
1028
1029DFP_HELPER_DEDPD(ddedpd, 64)
1030DFP_HELPER_DEDPD(ddedpdq, 128)
1031
1032static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n)
1033{
1034    return *t >> ((n << 2) & 63) & 15;
1035}
1036
1037static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n)
1038{
1039    return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15;
1040}
1041
1042#define DFP_HELPER_ENBCD(op, size)                                           \
1043void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s)     \
1044{                                                                            \
1045    struct PPC_DFP dfp;                                                      \
1046    uint8_t digits[32];                                                      \
1047    int n = 0, offset = 0, sgn = 0, nonzero = 0;                             \
1048                                                                             \
1049    dfp_prepare_decimal##size(&dfp, 0, b, env);                              \
1050                                                                             \
1051    decNumberZero(&dfp.t);                                                   \
1052                                                                             \
1053    if (s) {                                                                 \
1054        uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++);     \
1055        switch (sgnNibble) {                                                 \
1056        case 0xD:                                                            \
1057        case 0xB:                                                            \
1058            sgn = 1;                                                         \
1059            break;                                                           \
1060        case 0xC:                                                            \
1061        case 0xF:                                                            \
1062        case 0xA:                                                            \
1063        case 0xE:                                                            \
1064            sgn = 0;                                                         \
1065            break;                                                           \
1066        default:                                                             \
1067            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
1068            return;                                                          \
1069        }                                                                    \
1070        }                                                                    \
1071                                                                             \
1072    while (offset < (size)/4) {                                              \
1073        n++;                                                                 \
1074        digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++);    \
1075        if (digits[(size)/4-n] > 10) {                                       \
1076            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
1077            return;                                                          \
1078        } else {                                                             \
1079            nonzero |= (digits[(size)/4-n] > 0);                             \
1080        }                                                                    \
1081    }                                                                        \
1082                                                                             \
1083    if (nonzero) {                                                           \
1084        decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n);                     \
1085    }                                                                        \
1086                                                                             \
1087    if (s && sgn)  {                                                         \
1088        dfp.t.bits |= DECNEG;                                                \
1089    }                                                                        \
1090    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,              \
1091                              &dfp.context);                                 \
1092    dfp_set_FPRF_from_FRT(&dfp);                                             \
1093    if ((size) == 64) {                                                      \
1094        t[0] = dfp.t64[0];                                                   \
1095    } else if ((size) == 128) {                                              \
1096        t[0] = dfp.t64[HI_IDX];                                              \
1097        t[1] = dfp.t64[LO_IDX];                                              \
1098    }                                                                        \
1099}
1100
1101DFP_HELPER_ENBCD(denbcd, 64)
1102DFP_HELPER_ENBCD(denbcdq, 128)
1103
1104#define DFP_HELPER_XEX(op, size)                               \
1105void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)   \
1106{                                                              \
1107    struct PPC_DFP dfp;                                        \
1108                                                               \
1109    dfp_prepare_decimal##size(&dfp, 0, b, env);                \
1110                                                               \
1111    if (unlikely(decNumberIsSpecial(&dfp.b))) {                \
1112        if (decNumberIsInfinite(&dfp.b)) {                     \
1113            *t = -1;                                           \
1114        } else if (decNumberIsSNaN(&dfp.b)) {                  \
1115            *t = -3;                                           \
1116        } else if (decNumberIsQNaN(&dfp.b)) {                  \
1117            *t = -2;                                           \
1118        } else {                                               \
1119            assert(0);                                         \
1120        }                                                      \
1121    } else {                                                   \
1122        if ((size) == 64) {                                    \
1123            *t = dfp.b.exponent + 398;                         \
1124        } else if ((size) == 128) {                            \
1125            *t = dfp.b.exponent + 6176;                        \
1126        } else {                                               \
1127            assert(0);                                         \
1128        }                                                      \
1129    }                                                          \
1130}
1131
1132DFP_HELPER_XEX(dxex, 64)
1133DFP_HELPER_XEX(dxexq, 128)
1134
1135static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw)
1136{
1137    *t &= 0x8003ffffffffffffULL;
1138    *t |= (raw << (63-13));
1139}
1140
1141static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw)
1142{
1143    t[HI_IDX] &= 0x80003fffffffffffULL;
1144    t[HI_IDX] |= (raw << (63-17));
1145}
1146
1147#define DFP_HELPER_IEX(op, size)                                          \
1148void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
1149{                                                                         \
1150    struct PPC_DFP dfp;                                                   \
1151    uint64_t raw_qnan, raw_snan, raw_inf, max_exp;                        \
1152    int bias;                                                             \
1153    int64_t exp = *((int64_t *)a);                                        \
1154                                                                          \
1155    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
1156                                                                          \
1157    if ((size) == 64) {                                                   \
1158        max_exp = 767;                                                    \
1159        raw_qnan = 0x1F00;                                                \
1160        raw_snan = 0x1F80;                                                \
1161        raw_inf = 0x1E00;                                                 \
1162        bias = 398;                                                       \
1163    } else if ((size) == 128) {                                           \
1164        max_exp = 12287;                                                  \
1165        raw_qnan = 0x1f000;                                               \
1166        raw_snan = 0x1f800;                                               \
1167        raw_inf = 0x1e000;                                                \
1168        bias = 6176;                                                      \
1169    } else {                                                              \
1170        assert(0);                                                        \
1171    }                                                                     \
1172                                                                          \
1173    if (unlikely((exp < 0) || (exp > max_exp))) {                         \
1174        dfp.t64[0] = dfp.b64[0];                                          \
1175        dfp.t64[1] = dfp.b64[1];                                          \
1176        if (exp == -1) {                                                  \
1177            dfp_set_raw_exp_##size(dfp.t64, raw_inf);                     \
1178        } else if (exp == -3) {                                           \
1179            dfp_set_raw_exp_##size(dfp.t64, raw_snan);                    \
1180        } else {                                                          \
1181            dfp_set_raw_exp_##size(dfp.t64, raw_qnan);                    \
1182        }                                                                 \
1183    } else {                                                              \
1184        dfp.t = dfp.b;                                                    \
1185        if (unlikely(decNumberIsSpecial(&dfp.t))) {                       \
1186            dfp.t.bits &= ~DECSPECIAL;                                    \
1187        }                                                                 \
1188        dfp.t.exponent = exp - bias;                                      \
1189        decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,       \
1190                                  &dfp.context);                          \
1191    }                                                                     \
1192    if (size == 64) {                                                     \
1193        t[0] = dfp.t64[0];                                                \
1194    } else if (size == 128) {                                             \
1195        t[0] = dfp.t64[HI_IDX];                                           \
1196        t[1] = dfp.t64[LO_IDX];                                           \
1197    }                                                                     \
1198}
1199
1200DFP_HELPER_IEX(diex, 64)
1201DFP_HELPER_IEX(diexq, 128)
1202
1203static void dfp_clear_lmd_from_g5msb(uint64_t *t)
1204{
1205
1206    /* The most significant 5 bits of the PowerPC DFP format combine bits  */
1207    /* from the left-most decimal digit (LMD) and the biased exponent.     */
1208    /* This  routine clears the LMD bits while preserving the exponent     */
1209    /*  bits.  See "Figure 80: Encoding of bits 0:4 of the G field for     */
1210    /*  Finite Numbers" in the Power ISA for additional details.           */
1211
1212    uint64_t g5msb = (*t >> 58) & 0x1F;
1213
1214    if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
1215       *t &= ~(7ULL << 58);
1216    } else {
1217       switch (g5msb & 7) {
1218       case 0:
1219       case 1:
1220           g5msb = 0;
1221           break;
1222       case 2:
1223       case 3:
1224           g5msb = 0x8;
1225           break;
1226       case 4:
1227       case 5:
1228           g5msb = 0x10;
1229           break;
1230       case 6:
1231           g5msb = 0x1E;
1232           break;
1233       case 7:
1234           g5msb = 0x1F;
1235           break;
1236       }
1237
1238        *t &= ~(0x1fULL << 58);
1239        *t |= (g5msb << 58);
1240    }
1241}
1242
1243#define DFP_HELPER_SHIFT(op, size, shift_left)                      \
1244void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,        \
1245                 uint32_t sh)                                       \
1246{                                                                   \
1247    struct PPC_DFP dfp;                                             \
1248    unsigned max_digits = ((size) == 64) ? 16 : 34;                 \
1249                                                                    \
1250    dfp_prepare_decimal##size(&dfp, a, 0, env);                     \
1251                                                                    \
1252    if (sh <= max_digits) {                                         \
1253                                                                    \
1254        decNumber shd;                                              \
1255        unsigned special = dfp.a.bits & DECSPECIAL;                 \
1256                                                                    \
1257        if (shift_left) {                                           \
1258            decNumberFromUInt32(&shd, sh);                          \
1259        } else {                                                    \
1260            decNumberFromInt32(&shd, -((int32_t)sh));               \
1261        }                                                           \
1262                                                                    \
1263        dfp.a.bits &= ~DECSPECIAL;                                  \
1264        decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context);         \
1265                                                                    \
1266        dfp.t.bits |= special;                                      \
1267        if (special && (dfp.t.digits >= max_digits)) {              \
1268            dfp.t.digits = max_digits - 1;                          \
1269        }                                                           \
1270                                                                    \
1271        decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
1272                                  &dfp.context);                    \
1273    } else {                                                        \
1274        if ((size) == 64) {                                         \
1275            dfp.t64[0] = dfp.a64[0] & 0xFFFC000000000000ULL;        \
1276            dfp_clear_lmd_from_g5msb(dfp.t64);                      \
1277        } else {                                                    \
1278            dfp.t64[HI_IDX] = dfp.a64[HI_IDX] &                     \
1279                              0xFFFFC00000000000ULL;                \
1280            dfp_clear_lmd_from_g5msb(dfp.t64 + HI_IDX);             \
1281            dfp.t64[LO_IDX] = 0;                                    \
1282        }                                                           \
1283    }                                                               \
1284                                                                    \
1285    if ((size) == 64) {                                             \
1286        t[0] = dfp.t64[0];                                          \
1287    } else {                                                        \
1288        t[0] = dfp.t64[HI_IDX];                                     \
1289        t[1] = dfp.t64[LO_IDX];                                     \
1290    }                                                               \
1291}
1292
1293DFP_HELPER_SHIFT(dscli, 64, 1)
1294DFP_HELPER_SHIFT(dscliq, 128, 1)
1295DFP_HELPER_SHIFT(dscri, 64, 0)
1296DFP_HELPER_SHIFT(dscriq, 128, 0)
1297