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