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