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