1169689Skan/* Decimal floating point support. 2169689Skan Copyright (C) 2005, 2006 Free Software Foundation, Inc. 3169689Skan 4169689SkanThis file is part of GCC. 5169689Skan 6169689SkanGCC is free software; you can redistribute it and/or modify it under 7169689Skanthe terms of the GNU General Public License as published by the Free 8169689SkanSoftware Foundation; either version 2, or (at your option) any later 9169689Skanversion. 10169689Skan 11169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 12169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 13169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14169689Skanfor more details. 15169689Skan 16169689SkanYou should have received a copy of the GNU General Public License 17169689Skanalong with GCC; see the file COPYING. If not, write to the Free 18169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 19169689Skan02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include "tm.h" 25169689Skan#include "tree.h" 26169689Skan#include "toplev.h" 27169689Skan#include "real.h" 28169689Skan#include "tm_p.h" 29169689Skan#include "dfp.h" 30169689Skan 31169689Skan/* The order of the following headers is important for making sure 32169689Skan decNumber structure is large enough to hold decimal128 digits. */ 33169689Skan 34169689Skan#include "decimal128.h" 35169689Skan#include "decimal64.h" 36169689Skan#include "decimal32.h" 37169689Skan#include "decNumber.h" 38169689Skan 39169689Skanstatic uint32_t 40169689Skandfp_byte_swap (uint32_t in) 41169689Skan{ 42169689Skan uint32_t out = 0; 43169689Skan unsigned char *p = (unsigned char *) &out; 44169689Skan union { 45169689Skan uint32_t i; 46169689Skan unsigned char b[4]; 47169689Skan } u; 48169689Skan 49169689Skan u.i = in; 50169689Skan p[0] = u.b[3]; 51169689Skan p[1] = u.b[2]; 52169689Skan p[2] = u.b[1]; 53169689Skan p[3] = u.b[0]; 54169689Skan 55169689Skan return out; 56169689Skan} 57169689Skan 58169689Skan/* Initialize R (a real with the decimal flag set) from DN. Can 59169689Skan utilize status passed in via CONTEXT, if a previous operation had 60169689Skan interesting status. */ 61169689Skan 62169689Skanstatic void 63169689Skandecimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context) 64169689Skan{ 65169689Skan memset (r, 0, sizeof (REAL_VALUE_TYPE)); 66169689Skan 67169689Skan r->cl = rvc_normal; 68169689Skan if (decNumberIsZero (dn)) 69169689Skan r->cl = rvc_zero; 70169689Skan if (decNumberIsNaN (dn)) 71169689Skan r->cl = rvc_nan; 72169689Skan if (decNumberIsInfinite (dn)) 73169689Skan r->cl = rvc_inf; 74169689Skan if (context->status & DEC_Overflow) 75169689Skan r->cl = rvc_inf; 76169689Skan if (decNumberIsNegative (dn)) 77169689Skan r->sign = 1; 78169689Skan r->decimal = 1; 79169689Skan 80169689Skan if (r->cl != rvc_normal) 81169689Skan return; 82169689Skan 83169689Skan decContextDefault (context, DEC_INIT_DECIMAL128); 84169689Skan context->traps = 0; 85169689Skan 86169689Skan decimal128FromNumber ((decimal128 *) r->sig, dn, context); 87169689Skan} 88169689Skan 89169689Skan/* Create decimal encoded R from string S. */ 90169689Skan 91169689Skanvoid 92169689Skandecimal_real_from_string (REAL_VALUE_TYPE *r, const char *s) 93169689Skan{ 94169689Skan decNumber dn; 95169689Skan decContext set; 96169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 97169689Skan set.traps = 0; 98169689Skan 99169689Skan decNumberFromString (&dn, (char *) s, &set); 100169689Skan 101169689Skan /* It would be more efficient to store directly in decNumber format, 102169689Skan but that is impractical from current data structure size. 103169689Skan Encoding as a decimal128 is much more compact. */ 104169689Skan decimal_from_decnumber (r, &dn, &set); 105169689Skan} 106169689Skan 107169689Skan/* Initialize a decNumber from a REAL_VALUE_TYPE. */ 108169689Skan 109169689Skanstatic void 110169689Skandecimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn) 111169689Skan{ 112169689Skan decContext set; 113169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 114169689Skan set.traps = 0; 115169689Skan 116169689Skan switch (r->cl) 117169689Skan { 118169689Skan case rvc_zero: 119169689Skan decNumberZero (dn); 120169689Skan break; 121169689Skan case rvc_inf: 122169689Skan decNumberFromString (dn, (char *)"Infinity", &set); 123169689Skan break; 124169689Skan case rvc_nan: 125169689Skan if (r->signalling) 126169689Skan decNumberFromString (dn, (char *)"snan", &set); 127169689Skan else 128169689Skan decNumberFromString (dn, (char *)"nan", &set); 129169689Skan break; 130169689Skan case rvc_normal: 131169689Skan gcc_assert (r->decimal); 132169689Skan decimal128ToNumber ((decimal128 *) r->sig, dn); 133169689Skan break; 134169689Skan default: 135169689Skan gcc_unreachable (); 136169689Skan } 137169689Skan 138169689Skan /* Fix up sign bit. */ 139169689Skan if (r->sign != decNumberIsNegative (dn)) 140169689Skan dn->bits ^= DECNEG; 141169689Skan} 142169689Skan 143169689Skan/* Encode a real into an IEEE 754R decimal32 type. */ 144169689Skan 145169689Skanvoid 146169689Skanencode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, 147169689Skan long *buf, const REAL_VALUE_TYPE *r) 148169689Skan{ 149169689Skan decNumber dn; 150169689Skan decimal32 d32; 151169689Skan decContext set; 152169689Skan 153169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 154169689Skan set.traps = 0; 155169689Skan 156169689Skan decimal_to_decnumber (r, &dn); 157169689Skan decimal32FromNumber (&d32, &dn, &set); 158169689Skan 159169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 160169689Skan buf[0] = *(uint32_t *) d32.bytes; 161169689Skan else 162169689Skan buf[0] = dfp_byte_swap (*(uint32_t *) d32.bytes); 163169689Skan} 164169689Skan 165169689Skan/* Decode an IEEE 754R decimal32 type into a real. */ 166169689Skan 167169689Skanvoid 168169689Skandecode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, 169169689Skan REAL_VALUE_TYPE *r, const long *buf) 170169689Skan{ 171169689Skan decNumber dn; 172169689Skan decimal32 d32; 173169689Skan decContext set; 174169689Skan 175169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 176169689Skan set.traps = 0; 177169689Skan 178169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 179169689Skan *((uint32_t *) d32.bytes) = (uint32_t) buf[0]; 180169689Skan else 181169689Skan *((uint32_t *) d32.bytes) = dfp_byte_swap ((uint32_t) buf[0]); 182169689Skan 183169689Skan decimal32ToNumber (&d32, &dn); 184169689Skan decimal_from_decnumber (r, &dn, &set); 185169689Skan} 186169689Skan 187169689Skan/* Encode a real into an IEEE 754R decimal64 type. */ 188169689Skan 189169689Skanvoid 190169689Skanencode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, 191169689Skan long *buf, const REAL_VALUE_TYPE *r) 192169689Skan{ 193169689Skan decNumber dn; 194169689Skan decimal64 d64; 195169689Skan decContext set; 196169689Skan 197169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 198169689Skan set.traps = 0; 199169689Skan 200169689Skan decimal_to_decnumber (r, &dn); 201169689Skan decimal64FromNumber (&d64, &dn, &set); 202169689Skan 203169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 204169689Skan { 205169689Skan buf[0] = *(uint32_t *) &d64.bytes[0]; 206169689Skan buf[1] = *(uint32_t *) &d64.bytes[4]; 207169689Skan } 208169689Skan else 209169689Skan { 210169689Skan buf[1] = dfp_byte_swap (*(uint32_t *) &d64.bytes[0]); 211169689Skan buf[0] = dfp_byte_swap (*(uint32_t *) &d64.bytes[4]); 212169689Skan } 213169689Skan} 214169689Skan 215169689Skan/* Decode an IEEE 754R decimal64 type into a real. */ 216169689Skan 217169689Skanvoid 218169689Skandecode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, 219169689Skan REAL_VALUE_TYPE *r, const long *buf) 220169689Skan{ 221169689Skan decNumber dn; 222169689Skan decimal64 d64; 223169689Skan decContext set; 224169689Skan 225169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 226169689Skan set.traps = 0; 227169689Skan 228169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 229169689Skan { 230169689Skan *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0]; 231169689Skan *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1]; 232169689Skan } 233169689Skan else 234169689Skan { 235169689Skan *((uint32_t *) &d64.bytes[0]) = dfp_byte_swap ((uint32_t) buf[1]); 236169689Skan *((uint32_t *) &d64.bytes[4]) = dfp_byte_swap ((uint32_t) buf[0]); 237169689Skan } 238169689Skan 239169689Skan decimal64ToNumber (&d64, &dn); 240169689Skan decimal_from_decnumber (r, &dn, &set); 241169689Skan} 242169689Skan 243169689Skan/* Encode a real into an IEEE 754R decimal128 type. */ 244169689Skan 245169689Skanvoid 246169689Skanencode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, 247169689Skan long *buf, const REAL_VALUE_TYPE *r) 248169689Skan{ 249169689Skan decNumber dn; 250169689Skan decContext set; 251169689Skan decimal128 d128; 252169689Skan 253169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 254169689Skan set.traps = 0; 255169689Skan 256169689Skan decimal_to_decnumber (r, &dn); 257169689Skan decimal128FromNumber (&d128, &dn, &set); 258169689Skan 259169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 260169689Skan { 261169689Skan buf[0] = *(uint32_t *) &d128.bytes[0]; 262169689Skan buf[1] = *(uint32_t *) &d128.bytes[4]; 263169689Skan buf[2] = *(uint32_t *) &d128.bytes[8]; 264169689Skan buf[3] = *(uint32_t *) &d128.bytes[12]; 265169689Skan } 266169689Skan else 267169689Skan { 268169689Skan buf[0] = dfp_byte_swap (*(uint32_t *) &d128.bytes[12]); 269169689Skan buf[1] = dfp_byte_swap (*(uint32_t *) &d128.bytes[8]); 270169689Skan buf[2] = dfp_byte_swap (*(uint32_t *) &d128.bytes[4]); 271169689Skan buf[3] = dfp_byte_swap (*(uint32_t *) &d128.bytes[0]); 272169689Skan } 273169689Skan} 274169689Skan 275169689Skan/* Decode an IEEE 754R decimal128 type into a real. */ 276169689Skan 277169689Skanvoid 278169689Skandecode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, 279169689Skan REAL_VALUE_TYPE *r, const long *buf) 280169689Skan{ 281169689Skan decNumber dn; 282169689Skan decimal128 d128; 283169689Skan decContext set; 284169689Skan 285169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 286169689Skan set.traps = 0; 287169689Skan 288169689Skan if (FLOAT_WORDS_BIG_ENDIAN) 289169689Skan { 290169689Skan *((uint32_t *) &d128.bytes[0]) = (uint32_t) buf[0]; 291169689Skan *((uint32_t *) &d128.bytes[4]) = (uint32_t) buf[1]; 292169689Skan *((uint32_t *) &d128.bytes[8]) = (uint32_t) buf[2]; 293169689Skan *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3]; 294169689Skan } 295169689Skan else 296169689Skan { 297169689Skan *((uint32_t *) &d128.bytes[0]) = dfp_byte_swap ((uint32_t) buf[3]); 298169689Skan *((uint32_t *) &d128.bytes[4]) = dfp_byte_swap ((uint32_t) buf[2]); 299169689Skan *((uint32_t *) &d128.bytes[8]) = dfp_byte_swap ((uint32_t) buf[1]); 300169689Skan *((uint32_t *) &d128.bytes[12]) = dfp_byte_swap ((uint32_t) buf[0]); 301169689Skan } 302169689Skan 303169689Skan decimal128ToNumber (&d128, &dn); 304169689Skan decimal_from_decnumber (r, &dn, &set); 305169689Skan} 306169689Skan 307169689Skan/* Helper function to convert from a binary real internal 308169689Skan representation. */ 309169689Skan 310169689Skanstatic void 311169689Skandecimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from, 312169689Skan enum machine_mode mode) 313169689Skan{ 314169689Skan char string[256]; 315169689Skan decimal128 *d128; 316169689Skan d128 = (decimal128 *) from->sig; 317169689Skan 318169689Skan decimal128ToString (d128, string); 319169689Skan real_from_string3 (to, string, mode); 320169689Skan} 321169689Skan 322169689Skan 323169689Skan/* Helper function to convert from a binary real internal 324169689Skan representation. */ 325169689Skan 326169689Skanstatic void 327169689Skandecimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from) 328169689Skan{ 329169689Skan char string[256]; 330169689Skan 331169689Skan /* We convert to string, then to decNumber then to decimal128. */ 332169689Skan real_to_decimal (string, from, sizeof (string), 0, 1); 333169689Skan decimal_real_from_string (to, string); 334169689Skan} 335169689Skan 336169689Skan/* Helper function to real.c:do_compare() to handle decimal internal 337169689Skan representation including when one of the operands is still in the 338169689Skan binary internal representation. */ 339169689Skan 340169689Skanint 341169689Skandecimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, 342169689Skan int nan_result) 343169689Skan{ 344169689Skan decContext set; 345169689Skan decNumber dn, dn2, dn3; 346169689Skan REAL_VALUE_TYPE a1, b1; 347169689Skan 348169689Skan /* If either operand is non-decimal, create temporary versions. */ 349169689Skan if (!a->decimal) 350169689Skan { 351169689Skan decimal_from_binary (&a1, a); 352169689Skan a = &a1; 353169689Skan } 354169689Skan if (!b->decimal) 355169689Skan { 356169689Skan decimal_from_binary (&b1, b); 357169689Skan b = &b1; 358169689Skan } 359169689Skan 360169689Skan /* Convert into decNumber form for comparison operation. */ 361169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 362169689Skan set.traps = 0; 363169689Skan decimal128ToNumber ((decimal128 *) a->sig, &dn2); 364169689Skan decimal128ToNumber ((decimal128 *) b->sig, &dn3); 365169689Skan 366169689Skan /* Finally, do the comparison. */ 367169689Skan decNumberCompare (&dn, &dn2, &dn3, &set); 368169689Skan 369169689Skan /* Return the comparison result. */ 370169689Skan if (decNumberIsNaN (&dn)) 371169689Skan return nan_result; 372169689Skan else if (decNumberIsZero (&dn)) 373169689Skan return 0; 374169689Skan else if (decNumberIsNegative (&dn)) 375169689Skan return -1; 376169689Skan else 377169689Skan return 1; 378169689Skan} 379169689Skan 380169689Skan/* Helper to round_for_format, handling decimal float types. */ 381169689Skan 382169689Skanvoid 383169689Skandecimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) 384169689Skan{ 385169689Skan decNumber dn; 386169689Skan decContext set; 387169689Skan 388169689Skan /* Real encoding occurs later. */ 389169689Skan if (r->cl != rvc_normal) 390169689Skan return; 391169689Skan 392169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 393169689Skan set.traps = 0; 394169689Skan decimal128ToNumber ((decimal128 *) r->sig, &dn); 395169689Skan 396169689Skan if (fmt == &decimal_quad_format) 397169689Skan { 398169689Skan /* The internal format is already in this format. */ 399169689Skan return; 400169689Skan } 401169689Skan else if (fmt == &decimal_single_format) 402169689Skan { 403169689Skan decimal32 d32; 404169689Skan decContextDefault (&set, DEC_INIT_DECIMAL32); 405169689Skan set.traps = 0; 406169689Skan 407169689Skan decimal32FromNumber (&d32, &dn, &set); 408169689Skan decimal32ToNumber (&d32, &dn); 409169689Skan } 410169689Skan else if (fmt == &decimal_double_format) 411169689Skan { 412169689Skan decimal64 d64; 413169689Skan decContextDefault (&set, DEC_INIT_DECIMAL64); 414169689Skan set.traps = 0; 415169689Skan 416169689Skan decimal64FromNumber (&d64, &dn, &set); 417169689Skan decimal64ToNumber (&d64, &dn); 418169689Skan } 419169689Skan else 420169689Skan gcc_unreachable (); 421169689Skan 422169689Skan decimal_from_decnumber (r, &dn, &set); 423169689Skan} 424169689Skan 425169689Skan/* Extend or truncate to a new mode. Handles conversions between 426169689Skan binary and decimal types. */ 427169689Skan 428169689Skanvoid 429169689Skandecimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, 430169689Skan const REAL_VALUE_TYPE *a) 431169689Skan{ 432169689Skan const struct real_format *fmt = REAL_MODE_FORMAT (mode); 433169689Skan 434169689Skan if (a->decimal && fmt->b == 10) 435169689Skan return; 436169689Skan if (a->decimal) 437169689Skan decimal_to_binary (r, a, mode); 438169689Skan else 439169689Skan decimal_from_binary (r, a); 440169689Skan} 441169689Skan 442169689Skan/* Render R_ORIG as a decimal floating point constant. Emit DIGITS 443169689Skan significant digits in the result, bounded by BUF_SIZE. If DIGITS 444169689Skan is 0, choose the maximum for the representation. If 445169689Skan CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring 446169689Skan DIGITS or CROP_TRAILING_ZEROS. */ 447169689Skan 448169689Skanvoid 449169689Skandecimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, 450169689Skan size_t buf_size, 451169689Skan size_t digits ATTRIBUTE_UNUSED, 452169689Skan int crop_trailing_zeros ATTRIBUTE_UNUSED) 453169689Skan{ 454169689Skan decimal128 *d128 = (decimal128*) r_orig->sig; 455169689Skan 456169689Skan /* decimal128ToString requires space for at least 24 characters; 457169689Skan Require two more for suffix. */ 458169689Skan gcc_assert (buf_size >= 24); 459169689Skan decimal128ToString (d128, str); 460169689Skan} 461169689Skan 462169689Skanstatic bool 463169689Skandecimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, 464169689Skan const REAL_VALUE_TYPE *op1, int subtract_p) 465169689Skan{ 466169689Skan decNumber dn; 467169689Skan decContext set; 468169689Skan decNumber dn2, dn3; 469169689Skan 470169689Skan decimal_to_decnumber (op0, &dn2); 471169689Skan decimal_to_decnumber (op1, &dn3); 472169689Skan 473169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 474169689Skan set.traps = 0; 475169689Skan 476169689Skan if (subtract_p) 477169689Skan decNumberSubtract (&dn, &dn2, &dn3, &set); 478169689Skan else 479169689Skan decNumberAdd (&dn, &dn2, &dn3, &set); 480169689Skan 481169689Skan decimal_from_decnumber (r, &dn, &set); 482169689Skan 483169689Skan /* Return true, if inexact. */ 484169689Skan return (set.status & DEC_Inexact); 485169689Skan} 486169689Skan 487169689Skan/* Compute R = OP0 * OP1. */ 488169689Skan 489169689Skanstatic bool 490169689Skandecimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, 491169689Skan const REAL_VALUE_TYPE *op1) 492169689Skan{ 493169689Skan decContext set; 494169689Skan decNumber dn, dn2, dn3; 495169689Skan 496169689Skan decimal_to_decnumber (op0, &dn2); 497169689Skan decimal_to_decnumber (op1, &dn3); 498169689Skan 499169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 500169689Skan set.traps = 0; 501169689Skan 502169689Skan decNumberMultiply (&dn, &dn2, &dn3, &set); 503169689Skan decimal_from_decnumber (r, &dn, &set); 504169689Skan 505169689Skan /* Return true, if inexact. */ 506169689Skan return (set.status & DEC_Inexact); 507169689Skan} 508169689Skan 509169689Skan/* Compute R = OP0 / OP1. */ 510169689Skan 511169689Skanstatic bool 512169689Skandecimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, 513169689Skan const REAL_VALUE_TYPE *op1) 514169689Skan{ 515169689Skan decContext set; 516169689Skan decNumber dn, dn2, dn3; 517169689Skan 518169689Skan decimal_to_decnumber (op0, &dn2); 519169689Skan decimal_to_decnumber (op1, &dn3); 520169689Skan 521169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 522169689Skan set.traps = 0; 523169689Skan 524169689Skan decNumberDivide (&dn, &dn2, &dn3, &set); 525169689Skan decimal_from_decnumber (r, &dn, &set); 526169689Skan 527169689Skan /* Return true, if inexact. */ 528169689Skan return (set.status & DEC_Inexact); 529169689Skan} 530169689Skan 531169689Skan/* Set R to A truncated to an integral value toward zero (decimal 532169689Skan floating point). */ 533169689Skan 534169689Skanvoid 535169689Skandecimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) 536169689Skan{ 537169689Skan decNumber dn, dn2; 538169689Skan decContext set; 539169689Skan 540169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 541169689Skan set.traps = 0; 542169689Skan set.round = DEC_ROUND_DOWN; 543169689Skan decimal128ToNumber ((decimal128 *) a->sig, &dn2); 544169689Skan 545169689Skan decNumberToIntegralValue (&dn, &dn2, &set); 546169689Skan decimal_from_decnumber (r, &dn, &set); 547169689Skan} 548169689Skan 549169689Skan/* Render decimal float value R as an integer. */ 550169689Skan 551169689SkanHOST_WIDE_INT 552169689Skandecimal_real_to_integer (const REAL_VALUE_TYPE *r) 553169689Skan{ 554169689Skan decContext set; 555169689Skan decNumber dn, dn2, dn3; 556169689Skan REAL_VALUE_TYPE to; 557169689Skan char string[256]; 558169689Skan 559169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 560169689Skan set.traps = 0; 561169689Skan set.round = DEC_ROUND_DOWN; 562169689Skan decimal128ToNumber ((decimal128 *) r->sig, &dn); 563169689Skan 564169689Skan decNumberToIntegralValue (&dn2, &dn, &set); 565169689Skan decNumberZero (&dn3); 566169689Skan decNumberRescale (&dn, &dn2, &dn3, &set); 567169689Skan 568169689Skan /* Convert to REAL_VALUE_TYPE and call appropriate conversion 569169689Skan function. */ 570169689Skan decNumberToString (&dn, string); 571169689Skan real_from_string (&to, string); 572169689Skan return real_to_integer (&to); 573169689Skan} 574169689Skan 575169689Skan/* Likewise, but to an integer pair, HI+LOW. */ 576169689Skan 577169689Skanvoid 578169689Skandecimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, 579169689Skan const REAL_VALUE_TYPE *r) 580169689Skan{ 581169689Skan decContext set; 582169689Skan decNumber dn, dn2, dn3; 583169689Skan REAL_VALUE_TYPE to; 584169689Skan char string[256]; 585169689Skan 586169689Skan decContextDefault (&set, DEC_INIT_DECIMAL128); 587169689Skan set.traps = 0; 588169689Skan set.round = DEC_ROUND_DOWN; 589169689Skan decimal128ToNumber ((decimal128 *) r->sig, &dn); 590169689Skan 591169689Skan decNumberToIntegralValue (&dn2, &dn, &set); 592169689Skan decNumberZero (&dn3); 593169689Skan decNumberRescale (&dn, &dn2, &dn3, &set); 594169689Skan 595169689Skan /* Conver to REAL_VALUE_TYPE and call appropriate conversion 596169689Skan function. */ 597169689Skan decNumberToString (&dn, string); 598169689Skan real_from_string (&to, string); 599169689Skan real_to_integer2 (plow, phigh, &to); 600169689Skan} 601169689Skan 602169689Skan/* Perform the decimal floating point operation described by CODE. 603169689Skan For a unary operation, OP1 will be NULL. This function returns 604169689Skan true if the result may be inexact due to loss of precision. */ 605169689Skan 606169689Skanbool 607169689Skandecimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code, 608169689Skan const REAL_VALUE_TYPE *op0, 609169689Skan const REAL_VALUE_TYPE *op1) 610169689Skan{ 611169689Skan REAL_VALUE_TYPE a, b; 612169689Skan 613169689Skan /* If either operand is non-decimal, create temporaries. */ 614169689Skan if (!op0->decimal) 615169689Skan { 616169689Skan decimal_from_binary (&a, op0); 617169689Skan op0 = &a; 618169689Skan } 619169689Skan if (op1 && !op1->decimal) 620169689Skan { 621169689Skan decimal_from_binary (&b, op1); 622169689Skan op1 = &b; 623169689Skan } 624169689Skan 625169689Skan switch (code) 626169689Skan { 627169689Skan case PLUS_EXPR: 628169689Skan return decimal_do_add (r, op0, op1, 0); 629169689Skan 630169689Skan case MINUS_EXPR: 631169689Skan return decimal_do_add (r, op0, op1, 1); 632169689Skan 633169689Skan case MULT_EXPR: 634169689Skan return decimal_do_multiply (r, op0, op1); 635169689Skan 636169689Skan case RDIV_EXPR: 637169689Skan return decimal_do_divide (r, op0, op1); 638169689Skan 639169689Skan case MIN_EXPR: 640169689Skan if (op1->cl == rvc_nan) 641169689Skan *r = *op1; 642169689Skan else if (real_compare (UNLT_EXPR, op0, op1)) 643169689Skan *r = *op0; 644169689Skan else 645169689Skan *r = *op1; 646169689Skan return false; 647169689Skan 648169689Skan case MAX_EXPR: 649169689Skan if (op1->cl == rvc_nan) 650169689Skan *r = *op1; 651169689Skan else if (real_compare (LT_EXPR, op0, op1)) 652169689Skan *r = *op1; 653169689Skan else 654169689Skan *r = *op0; 655169689Skan return false; 656169689Skan 657169689Skan case NEGATE_EXPR: 658169689Skan { 659169689Skan decimal128 *d128; 660169689Skan *r = *op0; 661169689Skan d128 = (decimal128 *) r->sig; 662169689Skan /* Flip high bit. */ 663169689Skan d128->bytes[0] ^= 1 << 7; 664169689Skan /* Keep sign field in sync. */ 665169689Skan r->sign ^= 1; 666169689Skan } 667169689Skan return false; 668169689Skan 669169689Skan case ABS_EXPR: 670169689Skan { 671169689Skan decimal128 *d128; 672169689Skan *r = *op0; 673169689Skan d128 = (decimal128 *) r->sig; 674169689Skan /* Clear high bit. */ 675169689Skan d128->bytes[0] &= 0x7f; 676169689Skan /* Keep sign field in sync. */ 677169689Skan r->sign = 0; 678169689Skan } 679169689Skan return false; 680169689Skan 681169689Skan case FIX_TRUNC_EXPR: 682169689Skan decimal_do_fix_trunc (r, op0); 683169689Skan return false; 684169689Skan 685169689Skan default: 686169689Skan gcc_unreachable (); 687169689Skan } 688169689Skan} 689169689Skan 690169689Skan/* Fills R with the largest finite value representable in mode MODE. 691169689Skan If SIGN is nonzero, R is set to the most negative finite value. */ 692169689Skan 693169689Skanvoid 694169689Skandecimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) 695169689Skan{ 696169689Skan char *max; 697169689Skan 698169689Skan switch (mode) 699169689Skan { 700169689Skan case SDmode: 701169689Skan max = (char *) "9.999999E96"; 702169689Skan break; 703169689Skan case DDmode: 704169689Skan max = (char *) "9.999999999999999E384"; 705169689Skan break; 706169689Skan case TDmode: 707169689Skan max = (char *) "9.999999999999999999999999999999999E6144"; 708169689Skan break; 709169689Skan default: 710169689Skan gcc_unreachable (); 711169689Skan } 712169689Skan 713169689Skan decimal_real_from_string (r, max); 714169689Skan if (sign) 715169689Skan r->sig[0] |= 0x80000000; 716169689Skan} 717