1 | /* Decimal floating point support. |
---|---|

2 | Copyright (C) 2005-2017 Free Software Foundation, Inc. |

3 | |

4 | This file is part of GCC. |

5 | |

6 | GCC is free software; you can redistribute it and/or modify it under |

7 | the terms of the GNU General Public License as published by the Free |

8 | Software Foundation; either version 3, or (at your option) any later |

9 | version. |

10 | |

11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |

12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |

13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |

14 | for more details. |

15 | |

16 | You should have received a copy of the GNU General Public License |

17 | along with GCC; see the file COPYING3. If not see |

18 | <http://www.gnu.org/licenses/>. */ |

19 | |

20 | #include "config.h" |

21 | #include "system.h" |

22 | #include "coretypes.h" |

23 | #include "tm.h" |

24 | #include "tree.h" |

25 | #include "dfp.h" |

26 | |

27 | /* The order of the following headers is important for making sure |

28 | decNumber structure is large enough to hold decimal128 digits. */ |

29 | |

30 | #include "decimal128.h" |

31 | #include "decimal64.h" |

32 | #include "decimal32.h" |

33 | |

34 | #ifndef WORDS_BIGENDIAN |

35 | #define WORDS_BIGENDIAN 0 |

36 | #endif |

37 | |

38 | /* Initialize R (a real with the decimal flag set) from DN. Can |

39 | utilize status passed in via CONTEXT, if a previous operation had |

40 | interesting status. */ |

41 | |

42 | static void |

43 | decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context) |

44 | { |

45 | memset (r, 0, sizeof (REAL_VALUE_TYPE)); |

46 | |

47 | r->cl = rvc_normal; |

48 | if (decNumberIsNaN (dn)) |

49 | r->cl = rvc_nan; |

50 | if (decNumberIsInfinite (dn)) |

51 | r->cl = rvc_inf; |

52 | if (context->status & DEC_Overflow) |

53 | r->cl = rvc_inf; |

54 | if (decNumberIsNegative (dn)) |

55 | r->sign = 1; |

56 | r->decimal = 1; |

57 | |

58 | if (r->cl != rvc_normal) |

59 | return; |

60 | |

61 | decContextDefault (context, DEC_INIT_DECIMAL128); |

62 | context->traps = 0; |

63 | |

64 | decimal128FromNumber ((decimal128 *) r->sig, dn, context); |

65 | } |

66 | |

67 | /* Create decimal encoded R from string S. */ |

68 | |

69 | void |

70 | decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s) |

71 | { |

72 | decNumber dn; |

73 | decContext set; |

74 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

75 | set.traps = 0; |

76 | |

77 | decNumberFromString (&dn, s, &set); |

78 | |

79 | /* It would be more efficient to store directly in decNumber format, |

80 | but that is impractical from current data structure size. |

81 | Encoding as a decimal128 is much more compact. */ |

82 | decimal_from_decnumber (r, &dn, &set); |

83 | } |

84 | |

85 | /* Initialize a decNumber from a REAL_VALUE_TYPE. */ |

86 | |

87 | static void |

88 | decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn) |

89 | { |

90 | decContext set; |

91 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

92 | set.traps = 0; |

93 | |

94 | switch (r->cl) |

95 | { |

96 | case rvc_zero: |

97 | decNumberZero (dn); |

98 | break; |

99 | case rvc_inf: |

100 | decNumberFromString (dn, "Infinity", &set); |

101 | break; |

102 | case rvc_nan: |

103 | if (r->signalling) |

104 | decNumberFromString (dn, "snan", &set); |

105 | else |

106 | decNumberFromString (dn, "nan", &set); |

107 | break; |

108 | case rvc_normal: |

109 | if (!r->decimal) |

110 | { |

111 | /* dconst{1,2,m1,half} are used in various places in |

112 | the middle-end and optimizers, allow them here |

113 | as an exception by converting them to decimal. */ |

114 | if (memcmp (r, &dconst1, sizeof (*r)) == 0) |

115 | { |

116 | decNumberFromString (dn, "1", &set); |

117 | break; |

118 | } |

119 | if (memcmp (r, &dconst2, sizeof (*r)) == 0) |

120 | { |

121 | decNumberFromString (dn, "2", &set); |

122 | break; |

123 | } |

124 | if (memcmp (r, &dconstm1, sizeof (*r)) == 0) |

125 | { |

126 | decNumberFromString (dn, "-1", &set); |

127 | break; |

128 | } |

129 | if (memcmp (r, &dconsthalf, sizeof (*r)) == 0) |

130 | { |

131 | decNumberFromString (dn, "0.5", &set); |

132 | break; |

133 | } |

134 | gcc_unreachable (); |

135 | } |

136 | decimal128ToNumber ((const decimal128 *) r->sig, dn); |

137 | break; |

138 | default: |

139 | gcc_unreachable (); |

140 | } |

141 | |

142 | /* Fix up sign bit. */ |

143 | if (r->sign != decNumberIsNegative (dn)) |

144 | dn->bits ^= DECNEG; |

145 | } |

146 | |

147 | /* Encode a real into an IEEE 754 decimal32 type. */ |

148 | |

149 | void |

150 | encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

151 | long *buf, const REAL_VALUE_TYPE *r) |

152 | { |

153 | decNumber dn; |

154 | decimal32 d32; |

155 | decContext set; |

156 | int32_t image; |

157 | |

158 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

159 | set.traps = 0; |

160 | |

161 | decimal_to_decnumber (r, &dn); |

162 | decimal32FromNumber (&d32, &dn, &set); |

163 | |

164 | memcpy (&image, d32.bytes, sizeof (int32_t)); |

165 | buf[0] = image; |

166 | } |

167 | |

168 | /* Decode an IEEE 754 decimal32 type into a real. */ |

169 | |

170 | void |

171 | decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

172 | REAL_VALUE_TYPE *r, const long *buf) |

173 | { |

174 | decNumber dn; |

175 | decimal32 d32; |

176 | decContext set; |

177 | int32_t image; |

178 | |

179 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

180 | set.traps = 0; |

181 | |

182 | image = buf[0]; |

183 | memcpy (&d32.bytes, &image, sizeof (int32_t)); |

184 | |

185 | decimal32ToNumber (&d32, &dn); |

186 | decimal_from_decnumber (r, &dn, &set); |

187 | } |

188 | |

189 | /* Encode a real into an IEEE 754 decimal64 type. */ |

190 | |

191 | void |

192 | encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

193 | long *buf, const REAL_VALUE_TYPE *r) |

194 | { |

195 | decNumber dn; |

196 | decimal64 d64; |

197 | decContext set; |

198 | int32_t image; |

199 | |

200 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

201 | set.traps = 0; |

202 | |

203 | decimal_to_decnumber (r, &dn); |

204 | decimal64FromNumber (&d64, &dn, &set); |

205 | |

206 | if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) |

207 | { |

208 | memcpy (&image, &d64.bytes[0], sizeof (int32_t)); |

209 | buf[0] = image; |

210 | memcpy (&image, &d64.bytes[4], sizeof (int32_t)); |

211 | buf[1] = image; |

212 | } |

213 | else |

214 | { |

215 | memcpy (&image, &d64.bytes[4], sizeof (int32_t)); |

216 | buf[0] = image; |

217 | memcpy (&image, &d64.bytes[0], sizeof (int32_t)); |

218 | buf[1] = image; |

219 | } |

220 | } |

221 | |

222 | /* Decode an IEEE 754 decimal64 type into a real. */ |

223 | |

224 | void |

225 | decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

226 | REAL_VALUE_TYPE *r, const long *buf) |

227 | { |

228 | decNumber dn; |

229 | decimal64 d64; |

230 | decContext set; |

231 | int32_t image; |

232 | |

233 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

234 | set.traps = 0; |

235 | |

236 | if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) |

237 | { |

238 | image = buf[0]; |

239 | memcpy (&d64.bytes[0], &image, sizeof (int32_t)); |

240 | image = buf[1]; |

241 | memcpy (&d64.bytes[4], &image, sizeof (int32_t)); |

242 | } |

243 | else |

244 | { |

245 | image = buf[1]; |

246 | memcpy (&d64.bytes[0], &image, sizeof (int32_t)); |

247 | image = buf[0]; |

248 | memcpy (&d64.bytes[4], &image, sizeof (int32_t)); |

249 | } |

250 | |

251 | decimal64ToNumber (&d64, &dn); |

252 | decimal_from_decnumber (r, &dn, &set); |

253 | } |

254 | |

255 | /* Encode a real into an IEEE 754 decimal128 type. */ |

256 | |

257 | void |

258 | encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

259 | long *buf, const REAL_VALUE_TYPE *r) |

260 | { |

261 | decNumber dn; |

262 | decContext set; |

263 | decimal128 d128; |

264 | int32_t image; |

265 | |

266 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

267 | set.traps = 0; |

268 | |

269 | decimal_to_decnumber (r, &dn); |

270 | decimal128FromNumber (&d128, &dn, &set); |

271 | |

272 | if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) |

273 | { |

274 | memcpy (&image, &d128.bytes[0], sizeof (int32_t)); |

275 | buf[0] = image; |

276 | memcpy (&image, &d128.bytes[4], sizeof (int32_t)); |

277 | buf[1] = image; |

278 | memcpy (&image, &d128.bytes[8], sizeof (int32_t)); |

279 | buf[2] = image; |

280 | memcpy (&image, &d128.bytes[12], sizeof (int32_t)); |

281 | buf[3] = image; |

282 | } |

283 | else |

284 | { |

285 | memcpy (&image, &d128.bytes[12], sizeof (int32_t)); |

286 | buf[0] = image; |

287 | memcpy (&image, &d128.bytes[8], sizeof (int32_t)); |

288 | buf[1] = image; |

289 | memcpy (&image, &d128.bytes[4], sizeof (int32_t)); |

290 | buf[2] = image; |

291 | memcpy (&image, &d128.bytes[0], sizeof (int32_t)); |

292 | buf[3] = image; |

293 | } |

294 | } |

295 | |

296 | /* Decode an IEEE 754 decimal128 type into a real. */ |

297 | |

298 | void |

299 | decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, |

300 | REAL_VALUE_TYPE *r, const long *buf) |

301 | { |

302 | decNumber dn; |

303 | decimal128 d128; |

304 | decContext set; |

305 | int32_t image; |

306 | |

307 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

308 | set.traps = 0; |

309 | |

310 | if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) |

311 | { |

312 | image = buf[0]; |

313 | memcpy (&d128.bytes[0], &image, sizeof (int32_t)); |

314 | image = buf[1]; |

315 | memcpy (&d128.bytes[4], &image, sizeof (int32_t)); |

316 | image = buf[2]; |

317 | memcpy (&d128.bytes[8], &image, sizeof (int32_t)); |

318 | image = buf[3]; |

319 | memcpy (&d128.bytes[12], &image, sizeof (int32_t)); |

320 | } |

321 | else |

322 | { |

323 | image = buf[3]; |

324 | memcpy (&d128.bytes[0], &image, sizeof (int32_t)); |

325 | image = buf[2]; |

326 | memcpy (&d128.bytes[4], &image, sizeof (int32_t)); |

327 | image = buf[1]; |

328 | memcpy (&d128.bytes[8], &image, sizeof (int32_t)); |

329 | image = buf[0]; |

330 | memcpy (&d128.bytes[12], &image, sizeof (int32_t)); |

331 | } |

332 | |

333 | decimal128ToNumber (&d128, &dn); |

334 | decimal_from_decnumber (r, &dn, &set); |

335 | } |

336 | |

337 | /* Helper function to convert from a binary real internal |

338 | representation. */ |

339 | |

340 | static void |

341 | decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from, |

342 | const real_format *fmt) |

343 | { |

344 | char string[256]; |

345 | const decimal128 *const d128 = (const decimal128 *) from->sig; |

346 | |

347 | decimal128ToString (d128, string); |

348 | real_from_string3 (to, string, fmt); |

349 | } |

350 | |

351 | |

352 | /* Helper function to convert from a binary real internal |

353 | representation. */ |

354 | |

355 | static void |

356 | decimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from) |

357 | { |

358 | char string[256]; |

359 | |

360 | /* We convert to string, then to decNumber then to decimal128. */ |

361 | real_to_decimal (string, from, sizeof (string), 0, 1); |

362 | decimal_real_from_string (to, string); |

363 | } |

364 | |

365 | /* Helper function to real.c:do_compare() to handle decimal internal |

366 | representation including when one of the operands is still in the |

367 | binary internal representation. */ |

368 | |

369 | int |

370 | decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, |

371 | int nan_result) |

372 | { |

373 | decContext set; |

374 | decNumber dn, dn2, dn3; |

375 | REAL_VALUE_TYPE a1, b1; |

376 | |

377 | /* If either operand is non-decimal, create temporary versions. */ |

378 | if (!a->decimal) |

379 | { |

380 | decimal_from_binary (&a1, a); |

381 | a = &a1; |

382 | } |

383 | if (!b->decimal) |

384 | { |

385 | decimal_from_binary (&b1, b); |

386 | b = &b1; |

387 | } |

388 | |

389 | /* Convert into decNumber form for comparison operation. */ |

390 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

391 | set.traps = 0; |

392 | decimal128ToNumber ((const decimal128 *) a->sig, &dn2); |

393 | decimal128ToNumber ((const decimal128 *) b->sig, &dn3); |

394 | |

395 | /* Finally, do the comparison. */ |

396 | decNumberCompare (&dn, &dn2, &dn3, &set); |

397 | |

398 | /* Return the comparison result. */ |

399 | if (decNumberIsNaN (&dn)) |

400 | return nan_result; |

401 | else if (decNumberIsZero (&dn)) |

402 | return 0; |

403 | else if (decNumberIsNegative (&dn)) |

404 | return -1; |

405 | else |

406 | return 1; |

407 | } |

408 | |

409 | /* Helper to round_for_format, handling decimal float types. */ |

410 | |

411 | void |

412 | decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) |

413 | { |

414 | decNumber dn; |

415 | decContext set; |

416 | |

417 | /* Real encoding occurs later. */ |

418 | if (r->cl != rvc_normal) |

419 | return; |

420 | |

421 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

422 | set.traps = 0; |

423 | decimal128ToNumber ((decimal128 *) r->sig, &dn); |

424 | |

425 | if (fmt == &decimal_quad_format) |

426 | { |

427 | /* The internal format is already in this format. */ |

428 | return; |

429 | } |

430 | else if (fmt == &decimal_single_format) |

431 | { |

432 | decimal32 d32; |

433 | decContextDefault (&set, DEC_INIT_DECIMAL32); |

434 | set.traps = 0; |

435 | |

436 | decimal32FromNumber (&d32, &dn, &set); |

437 | decimal32ToNumber (&d32, &dn); |

438 | } |

439 | else if (fmt == &decimal_double_format) |

440 | { |

441 | decimal64 d64; |

442 | decContextDefault (&set, DEC_INIT_DECIMAL64); |

443 | set.traps = 0; |

444 | |

445 | decimal64FromNumber (&d64, &dn, &set); |

446 | decimal64ToNumber (&d64, &dn); |

447 | } |

448 | else |

449 | gcc_unreachable (); |

450 | |

451 | decimal_from_decnumber (r, &dn, &set); |

452 | } |

453 | |

454 | /* Extend or truncate to a new mode. Handles conversions between |

455 | binary and decimal types. */ |

456 | |

457 | void |

458 | decimal_real_convert (REAL_VALUE_TYPE *r, const real_format *fmt, |

459 | const REAL_VALUE_TYPE *a) |

460 | { |

461 | if (a->decimal && fmt->b == 10) |

462 | return; |

463 | if (a->decimal) |

464 | decimal_to_binary (r, a, fmt); |

465 | else |

466 | decimal_from_binary (r, a); |

467 | } |

468 | |

469 | /* Render R_ORIG as a decimal floating point constant. Emit DIGITS |

470 | significant digits in the result, bounded by BUF_SIZE. If DIGITS |

471 | is 0, choose the maximum for the representation. If |

472 | CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring |

473 | DIGITS or CROP_TRAILING_ZEROS. */ |

474 | |

475 | void |

476 | decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, |

477 | size_t buf_size, |

478 | size_t digits ATTRIBUTE_UNUSED, |

479 | int crop_trailing_zeros ATTRIBUTE_UNUSED) |

480 | { |

481 | const decimal128 *const d128 = (const decimal128*) r_orig->sig; |

482 | |

483 | /* decimal128ToString requires space for at least 24 characters; |

484 | Require two more for suffix. */ |

485 | gcc_assert (buf_size >= 24); |

486 | decimal128ToString (d128, str); |

487 | } |

488 | |

489 | static bool |

490 | decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, |

491 | const REAL_VALUE_TYPE *op1, int subtract_p) |

492 | { |

493 | decNumber dn; |

494 | decContext set; |

495 | decNumber dn2, dn3; |

496 | |

497 | decimal_to_decnumber (op0, &dn2); |

498 | decimal_to_decnumber (op1, &dn3); |

499 | |

500 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

501 | set.traps = 0; |

502 | |

503 | if (subtract_p) |

504 | decNumberSubtract (&dn, &dn2, &dn3, &set); |

505 | else |

506 | decNumberAdd (&dn, &dn2, &dn3, &set); |

507 | |

508 | decimal_from_decnumber (r, &dn, &set); |

509 | |

510 | /* Return true, if inexact. */ |

511 | return (set.status & DEC_Inexact); |

512 | } |

513 | |

514 | /* Compute R = OP0 * OP1. */ |

515 | |

516 | static bool |

517 | decimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, |

518 | const REAL_VALUE_TYPE *op1) |

519 | { |

520 | decContext set; |

521 | decNumber dn, dn2, dn3; |

522 | |

523 | decimal_to_decnumber (op0, &dn2); |

524 | decimal_to_decnumber (op1, &dn3); |

525 | |

526 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

527 | set.traps = 0; |

528 | |

529 | decNumberMultiply (&dn, &dn2, &dn3, &set); |

530 | decimal_from_decnumber (r, &dn, &set); |

531 | |

532 | /* Return true, if inexact. */ |

533 | return (set.status & DEC_Inexact); |

534 | } |

535 | |

536 | /* Compute R = OP0 / OP1. */ |

537 | |

538 | static bool |

539 | decimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, |

540 | const REAL_VALUE_TYPE *op1) |

541 | { |

542 | decContext set; |

543 | decNumber dn, dn2, dn3; |

544 | |

545 | decimal_to_decnumber (op0, &dn2); |

546 | decimal_to_decnumber (op1, &dn3); |

547 | |

548 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

549 | set.traps = 0; |

550 | |

551 | decNumberDivide (&dn, &dn2, &dn3, &set); |

552 | decimal_from_decnumber (r, &dn, &set); |

553 | |

554 | /* Return true, if inexact. */ |

555 | return (set.status & DEC_Inexact); |

556 | } |

557 | |

558 | /* Set R to A truncated to an integral value toward zero (decimal |

559 | floating point). */ |

560 | |

561 | void |

562 | decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |

563 | { |

564 | decNumber dn, dn2; |

565 | decContext set; |

566 | |

567 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

568 | set.traps = 0; |

569 | set.round = DEC_ROUND_DOWN; |

570 | decimal128ToNumber ((const decimal128 *) a->sig, &dn2); |

571 | |

572 | decNumberToIntegralValue (&dn, &dn2, &set); |

573 | decimal_from_decnumber (r, &dn, &set); |

574 | } |

575 | |

576 | /* Render decimal float value R as an integer. */ |

577 | |

578 | HOST_WIDE_INT |

579 | decimal_real_to_integer (const REAL_VALUE_TYPE *r) |

580 | { |

581 | decContext set; |

582 | decNumber dn, dn2, dn3; |

583 | REAL_VALUE_TYPE to; |

584 | char string[256]; |

585 | |

586 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

587 | set.traps = 0; |

588 | set.round = DEC_ROUND_DOWN; |

589 | decimal128ToNumber ((const decimal128 *) r->sig, &dn); |

590 | |

591 | decNumberToIntegralValue (&dn2, &dn, &set); |

592 | decNumberZero (&dn3); |

593 | decNumberRescale (&dn, &dn2, &dn3, &set); |

594 | |

595 | /* Convert to REAL_VALUE_TYPE and call appropriate conversion |

596 | function. */ |

597 | decNumberToString (&dn, string); |

598 | real_from_string (&to, string); |

599 | return real_to_integer (&to); |

600 | } |

601 | |

602 | /* Likewise, but returns a wide_int with PRECISION. *FAIL is set if the |

603 | value does not fit. */ |

604 | |

605 | wide_int |

606 | decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision) |

607 | { |

608 | decContext set; |

609 | decNumber dn, dn2, dn3; |

610 | REAL_VALUE_TYPE to; |

611 | char string[256]; |

612 | |

613 | decContextDefault (&set, DEC_INIT_DECIMAL128); |

614 | set.traps = 0; |

615 | set.round = DEC_ROUND_DOWN; |

616 | decimal128ToNumber ((const decimal128 *) r->sig, &dn); |

617 | |

618 | decNumberToIntegralValue (&dn2, &dn, &set); |

619 | decNumberZero (&dn3); |

620 | decNumberRescale (&dn, &dn2, &dn3, &set); |

621 | |

622 | /* Convert to REAL_VALUE_TYPE and call appropriate conversion |

623 | function. */ |

624 | decNumberToString (&dn, string); |

625 | real_from_string (&to, string); |

626 | return real_to_integer (&to, fail, precision); |

627 | } |

628 | |

629 | /* Perform the decimal floating point operation described by CODE. |

630 | For a unary operation, OP1 will be NULL. This function returns |

631 | true if the result may be inexact due to loss of precision. */ |

632 | |

633 | bool |

634 | decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code, |

635 | const REAL_VALUE_TYPE *op0, |

636 | const REAL_VALUE_TYPE *op1) |

637 | { |

638 | REAL_VALUE_TYPE a, b; |

639 | |

640 | /* If either operand is non-decimal, create temporaries. */ |

641 | if (!op0->decimal) |

642 | { |

643 | decimal_from_binary (&a, op0); |

644 | op0 = &a; |

645 | } |

646 | if (op1 && !op1->decimal) |

647 | { |

648 | decimal_from_binary (&b, op1); |

649 | op1 = &b; |

650 | } |

651 | |

652 | switch (code) |

653 | { |

654 | case PLUS_EXPR: |

655 | return decimal_do_add (r, op0, op1, 0); |

656 | |

657 | case MINUS_EXPR: |

658 | return decimal_do_add (r, op0, op1, 1); |

659 | |

660 | case MULT_EXPR: |

661 | return decimal_do_multiply (r, op0, op1); |

662 | |

663 | case RDIV_EXPR: |

664 | return decimal_do_divide (r, op0, op1); |

665 | |

666 | case MIN_EXPR: |

667 | if (op1->cl == rvc_nan) |

668 | *r = *op1; |

669 | else if (real_compare (UNLT_EXPR, op0, op1)) |

670 | *r = *op0; |

671 | else |

672 | *r = *op1; |

673 | return false; |

674 | |

675 | case MAX_EXPR: |

676 | if (op1->cl == rvc_nan) |

677 | *r = *op1; |

678 | else if (real_compare (LT_EXPR, op0, op1)) |

679 | *r = *op1; |

680 | else |

681 | *r = *op0; |

682 | return false; |

683 | |

684 | case NEGATE_EXPR: |

685 | { |

686 | *r = *op0; |

687 | /* Flip sign bit. */ |

688 | decimal128FlipSign ((decimal128 *) r->sig); |

689 | /* Keep sign field in sync. */ |

690 | r->sign ^= 1; |

691 | } |

692 | return false; |

693 | |

694 | case ABS_EXPR: |

695 | { |

696 | *r = *op0; |

697 | /* Clear sign bit. */ |

698 | decimal128ClearSign ((decimal128 *) r->sig); |

699 | /* Keep sign field in sync. */ |

700 | r->sign = 0; |

701 | } |

702 | return false; |

703 | |

704 | case FIX_TRUNC_EXPR: |

705 | decimal_do_fix_trunc (r, op0); |

706 | return false; |

707 | |

708 | default: |

709 | gcc_unreachable (); |

710 | } |

711 | } |

712 | |

713 | /* Fills R with the largest finite value representable in mode MODE. |

714 | If SIGN is nonzero, R is set to the most negative finite value. */ |

715 | |

716 | void |

717 | decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode) |

718 | { |

719 | const char *max; |

720 | |

721 | switch (mode) |

722 | { |

723 | case E_SDmode: |

724 | max = "9.999999E96"; |

725 | break; |

726 | case E_DDmode: |

727 | max = "9.999999999999999E384"; |

728 | break; |

729 | case E_TDmode: |

730 | max = "9.999999999999999999999999999999999E6144"; |

731 | break; |

732 | default: |

733 | gcc_unreachable (); |

734 | } |

735 | |

736 | decimal_real_from_string (r, max); |

737 | if (sign) |

738 | decimal128SetSign ((decimal128 *) r->sig, 1); |

739 | } |

740 |