1 | /* Fixed-point arithmetic support. |
---|---|

2 | Copyright (C) 2006-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 "diagnostic-core.h" |

26 | |

27 | /* Compare two fixed objects for bitwise identity. */ |

28 | |

29 | bool |

30 | fixed_identical (const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b) |

31 | { |

32 | return (a->mode == b->mode |

33 | && a->data.high == b->data.high |

34 | && a->data.low == b->data.low); |

35 | } |

36 | |

37 | /* Calculate a hash value. */ |

38 | |

39 | unsigned int |

40 | fixed_hash (const FIXED_VALUE_TYPE *f) |

41 | { |

42 | return (unsigned int) (f->data.low ^ f->data.high); |

43 | } |

44 | |

45 | /* Define the enum code for the range of the fixed-point value. */ |

46 | enum fixed_value_range_code { |

47 | FIXED_OK, /* The value is within the range. */ |

48 | FIXED_UNDERFLOW, /* The value is less than the minimum. */ |

49 | FIXED_GT_MAX_EPS, /* The value is greater than the maximum, but not equal |

50 | to the maximum plus the epsilon. */ |

51 | FIXED_MAX_EPS /* The value equals the maximum plus the epsilon. */ |

52 | }; |

53 | |

54 | /* Check REAL_VALUE against the range of the fixed-point mode. |

55 | Return FIXED_OK, if it is within the range. |

56 | FIXED_UNDERFLOW, if it is less than the minimum. |

57 | FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to |

58 | the maximum plus the epsilon. |

59 | FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon. */ |

60 | |

61 | static enum fixed_value_range_code |

62 | check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode) |

63 | { |

64 | REAL_VALUE_TYPE max_value, min_value, epsilon_value; |

65 | |

66 | real_2expN (&max_value, GET_MODE_IBIT (mode), VOIDmode); |

67 | real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), VOIDmode); |

68 | |

69 | if (SIGNED_FIXED_POINT_MODE_P (mode)) |

70 | min_value = real_value_negate (&max_value); |

71 | else |

72 | real_from_string (&min_value, "0.0"); |

73 | |

74 | if (real_compare (LT_EXPR, real_value, &min_value)) |

75 | return FIXED_UNDERFLOW; |

76 | if (real_compare (EQ_EXPR, real_value, &max_value)) |

77 | return FIXED_MAX_EPS; |

78 | real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value); |

79 | if (real_compare (GT_EXPR, real_value, &max_value)) |

80 | return FIXED_GT_MAX_EPS; |

81 | return FIXED_OK; |

82 | } |

83 | |

84 | |

85 | /* Construct a CONST_FIXED from a bit payload and machine mode MODE. |

86 | The bits in PAYLOAD are sign-extended/zero-extended according to MODE. */ |

87 | |

88 | FIXED_VALUE_TYPE |

89 | fixed_from_double_int (double_int payload, scalar_mode mode) |

90 | { |

91 | FIXED_VALUE_TYPE value; |

92 | |

93 | gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT); |

94 | |

95 | if (SIGNED_SCALAR_FIXED_POINT_MODE_P (mode)) |

96 | value.data = payload.sext (1 + GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode)); |

97 | else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode)) |

98 | value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode)); |

99 | else |

100 | gcc_unreachable (); |

101 | |

102 | value.mode = mode; |

103 | |

104 | return value; |

105 | } |

106 | |

107 | |

108 | /* Initialize from a decimal or hexadecimal string. */ |

109 | |

110 | void |

111 | fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, scalar_mode mode) |

112 | { |

113 | REAL_VALUE_TYPE real_value, fixed_value, base_value; |

114 | unsigned int fbit; |

115 | enum fixed_value_range_code temp; |

116 | bool fail; |

117 | |

118 | f->mode = mode; |

119 | fbit = GET_MODE_FBIT (mode); |

120 | |

121 | real_from_string (&real_value, str); |

122 | temp = check_real_for_fixed_mode (&real_value, f->mode); |

123 | /* We don't want to warn the case when the _Fract value is 1.0. */ |

124 | if (temp == FIXED_UNDERFLOW |

125 | || temp == FIXED_GT_MAX_EPS |

126 | || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode))) |

127 | warning (OPT_Woverflow, |

128 | "large fixed-point constant implicitly truncated to fixed-point type"); |

129 | real_2expN (&base_value, fbit, VOIDmode); |

130 | real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); |

131 | wide_int w = real_to_integer (&fixed_value, &fail, |

132 | GET_MODE_PRECISION (mode)); |

133 | f->data.low = w.ulow (); |

134 | f->data.high = w.elt (1); |

135 | |

136 | if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode)) |

137 | { |

138 | /* From the spec, we need to evaluate 1 to the maximal value. */ |

139 | f->data.low = -1; |

140 | f->data.high = -1; |

141 | f->data = f->data.zext (GET_MODE_FBIT (f->mode) |

142 | + GET_MODE_IBIT (f->mode)); |

143 | } |

144 | else |

145 | f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode) |

146 | + GET_MODE_FBIT (f->mode) |

147 | + GET_MODE_IBIT (f->mode), |

148 | UNSIGNED_FIXED_POINT_MODE_P (f->mode)); |

149 | } |

150 | |

151 | /* Render F as a decimal floating point constant. */ |

152 | |

153 | void |

154 | fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, |

155 | size_t buf_size) |

156 | { |

157 | REAL_VALUE_TYPE real_value, base_value, fixed_value; |

158 | |

159 | signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED; |

160 | real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode); |

161 | real_from_integer (&real_value, VOIDmode, |

162 | wide_int::from (f_orig->data, |

163 | GET_MODE_PRECISION (f_orig->mode), sgn), |

164 | sgn); |

165 | real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); |

166 | real_to_decimal (str, &fixed_value, buf_size, 0, 1); |

167 | } |

168 | |

169 | /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on |

170 | the machine mode MODE. |

171 | Do not modify *F otherwise. |

172 | This function assumes the width of double_int is greater than the width |

173 | of the fixed-point value (the sum of a possible sign bit, possible ibits, |

174 | and fbits). |

175 | Return true, if !SAT_P and overflow. */ |

176 | |

177 | static bool |

178 | fixed_saturate1 (machine_mode mode, double_int a, double_int *f, |

179 | bool sat_p) |

180 | { |

181 | bool overflow_p = false; |

182 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); |

183 | int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); |

184 | |

185 | if (unsigned_p) /* Unsigned type. */ |

186 | { |

187 | double_int max; |

188 | max.low = -1; |

189 | max.high = -1; |

190 | max = max.zext (i_f_bits); |

191 | if (a.ugt (max)) |

192 | { |

193 | if (sat_p) |

194 | *f = max; |

195 | else |

196 | overflow_p = true; |

197 | } |

198 | } |

199 | else /* Signed type. */ |

200 | { |

201 | double_int max, min; |

202 | max.high = -1; |

203 | max.low = -1; |

204 | max = max.zext (i_f_bits); |

205 | min.high = 0; |

206 | min.low = 1; |

207 | min = min.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT); |

208 | min = min.sext (1 + i_f_bits); |

209 | if (a.sgt (max)) |

210 | { |

211 | if (sat_p) |

212 | *f = max; |

213 | else |

214 | overflow_p = true; |

215 | } |

216 | else if (a.slt (min)) |

217 | { |

218 | if (sat_p) |

219 | *f = min; |

220 | else |

221 | overflow_p = true; |

222 | } |

223 | } |

224 | return overflow_p; |

225 | } |

226 | |

227 | /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and |

228 | save to *F based on the machine mode MODE. |

229 | Do not modify *F otherwise. |

230 | This function assumes the width of two double_int is greater than the width |

231 | of the fixed-point value (the sum of a possible sign bit, possible ibits, |

232 | and fbits). |

233 | Return true, if !SAT_P and overflow. */ |

234 | |

235 | static bool |

236 | fixed_saturate2 (machine_mode mode, double_int a_high, double_int a_low, |

237 | double_int *f, bool sat_p) |

238 | { |

239 | bool overflow_p = false; |

240 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); |

241 | int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); |

242 | |

243 | if (unsigned_p) /* Unsigned type. */ |

244 | { |

245 | double_int max_r, max_s; |

246 | max_r.high = 0; |

247 | max_r.low = 0; |

248 | max_s.high = -1; |

249 | max_s.low = -1; |

250 | max_s = max_s.zext (i_f_bits); |

251 | if (a_high.ugt (max_r) |

252 | || (a_high == max_r && |

253 | a_low.ugt (max_s))) |

254 | { |

255 | if (sat_p) |

256 | *f = max_s; |

257 | else |

258 | overflow_p = true; |

259 | } |

260 | } |

261 | else /* Signed type. */ |

262 | { |

263 | double_int max_r, max_s, min_r, min_s; |

264 | max_r.high = 0; |

265 | max_r.low = 0; |

266 | max_s.high = -1; |

267 | max_s.low = -1; |

268 | max_s = max_s.zext (i_f_bits); |

269 | min_r.high = -1; |

270 | min_r.low = -1; |

271 | min_s.high = 0; |

272 | min_s.low = 1; |

273 | min_s = min_s.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT); |

274 | min_s = min_s.sext (1 + i_f_bits); |

275 | if (a_high.sgt (max_r) |

276 | || (a_high == max_r && |

277 | a_low.ugt (max_s))) |

278 | { |

279 | if (sat_p) |

280 | *f = max_s; |

281 | else |

282 | overflow_p = true; |

283 | } |

284 | else if (a_high.slt (min_r) |

285 | || (a_high == min_r && |

286 | a_low.ult (min_s))) |

287 | { |

288 | if (sat_p) |

289 | *f = min_s; |

290 | else |

291 | overflow_p = true; |

292 | } |

293 | } |

294 | return overflow_p; |

295 | } |

296 | |

297 | /* Return the sign bit based on I_F_BITS. */ |

298 | |

299 | static inline int |

300 | get_fixed_sign_bit (double_int a, int i_f_bits) |

301 | { |

302 | if (i_f_bits < HOST_BITS_PER_WIDE_INT) |

303 | return (a.low >> i_f_bits) & 1; |

304 | else |

305 | return (a.high >> (i_f_bits - HOST_BITS_PER_WIDE_INT)) & 1; |

306 | } |

307 | |

308 | /* Calculate F = A + (SUBTRACT_P ? -B : B). |

309 | If SAT_P, saturate the result to the max or the min. |

310 | Return true, if !SAT_P and overflow. */ |

311 | |

312 | static bool |

313 | do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, |

314 | const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p) |

315 | { |

316 | bool overflow_p = false; |

317 | bool unsigned_p; |

318 | double_int temp; |

319 | int i_f_bits; |

320 | |

321 | /* This was a conditional expression but it triggered a bug in |

322 | Sun C 5.5. */ |

323 | if (subtract_p) |

324 | temp = -b->data; |

325 | else |

326 | temp = b->data; |

327 | |

328 | unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); |

329 | i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); |

330 | f->mode = a->mode; |

331 | f->data = a->data + temp; |

332 | if (unsigned_p) /* Unsigned type. */ |

333 | { |

334 | if (subtract_p) /* Unsigned subtraction. */ |

335 | { |

336 | if (a->data.ult (b->data)) |

337 | { |

338 | if (sat_p) |

339 | { |

340 | f->data.high = 0; |

341 | f->data.low = 0; |

342 | } |

343 | else |

344 | overflow_p = true; |

345 | } |

346 | } |

347 | else /* Unsigned addition. */ |

348 | { |

349 | f->data = f->data.zext (i_f_bits); |

350 | if (f->data.ult (a->data) |

351 | || f->data.ult (b->data)) |

352 | { |

353 | if (sat_p) |

354 | { |

355 | f->data.high = -1; |

356 | f->data.low = -1; |

357 | } |

358 | else |

359 | overflow_p = true; |

360 | } |

361 | } |

362 | } |

363 | else /* Signed type. */ |

364 | { |

365 | if ((!subtract_p |

366 | && (get_fixed_sign_bit (a->data, i_f_bits) |

367 | == get_fixed_sign_bit (b->data, i_f_bits)) |

368 | && (get_fixed_sign_bit (a->data, i_f_bits) |

369 | != get_fixed_sign_bit (f->data, i_f_bits))) |

370 | || (subtract_p |

371 | && (get_fixed_sign_bit (a->data, i_f_bits) |

372 | != get_fixed_sign_bit (b->data, i_f_bits)) |

373 | && (get_fixed_sign_bit (a->data, i_f_bits) |

374 | != get_fixed_sign_bit (f->data, i_f_bits)))) |

375 | { |

376 | if (sat_p) |

377 | { |

378 | f->data.low = 1; |

379 | f->data.high = 0; |

380 | f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT); |

381 | if (get_fixed_sign_bit (a->data, i_f_bits) == 0) |

382 | { |

383 | --f->data; |

384 | } |

385 | } |

386 | else |

387 | overflow_p = true; |

388 | } |

389 | } |

390 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

391 | return overflow_p; |

392 | } |

393 | |

394 | /* Calculate F = A * B. |

395 | If SAT_P, saturate the result to the max or the min. |

396 | Return true, if !SAT_P and overflow. */ |

397 | |

398 | static bool |

399 | do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, |

400 | const FIXED_VALUE_TYPE *b, bool sat_p) |

401 | { |

402 | bool overflow_p = false; |

403 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); |

404 | int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); |

405 | f->mode = a->mode; |

406 | if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT) |

407 | { |

408 | f->data = a->data * b->data; |

409 | f->data = f->data.lshift (-GET_MODE_FBIT (f->mode), |

410 | HOST_BITS_PER_DOUBLE_INT, !unsigned_p); |

411 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); |

412 | } |

413 | else |

414 | { |

415 | /* The result of multiplication expands to two double_int. */ |

416 | double_int a_high, a_low, b_high, b_low; |

417 | double_int high_high, high_low, low_high, low_low; |

418 | double_int r, s, temp1, temp2; |

419 | int carry = 0; |

420 | |

421 | /* Decompose a and b to four double_int. */ |

422 | a_high.low = a->data.high; |

423 | a_high.high = 0; |

424 | a_low.low = a->data.low; |

425 | a_low.high = 0; |

426 | b_high.low = b->data.high; |

427 | b_high.high = 0; |

428 | b_low.low = b->data.low; |

429 | b_low.high = 0; |

430 | |

431 | /* Perform four multiplications. */ |

432 | low_low = a_low * b_low; |

433 | low_high = a_low * b_high; |

434 | high_low = a_high * b_low; |

435 | high_high = a_high * b_high; |

436 | |

437 | /* Accumulate four results to {r, s}. */ |

438 | temp1.high = high_low.low; |

439 | temp1.low = 0; |

440 | s = low_low + temp1; |

441 | if (s.ult (low_low) |

442 | || s.ult (temp1)) |

443 | carry ++; /* Carry */ |

444 | temp1.high = s.high; |

445 | temp1.low = s.low; |

446 | temp2.high = low_high.low; |

447 | temp2.low = 0; |

448 | s = temp1 + temp2; |

449 | if (s.ult (temp1) |

450 | || s.ult (temp2)) |

451 | carry ++; /* Carry */ |

452 | |

453 | temp1.low = high_low.high; |

454 | temp1.high = 0; |

455 | r = high_high + temp1; |

456 | temp1.low = low_high.high; |

457 | temp1.high = 0; |

458 | r += temp1; |

459 | temp1.low = carry; |

460 | temp1.high = 0; |

461 | r += temp1; |

462 | |

463 | /* We need to subtract b from r, if a < 0. */ |

464 | if (!unsigned_p && a->data.high < 0) |

465 | r -= b->data; |

466 | /* We need to subtract a from r, if b < 0. */ |

467 | if (!unsigned_p && b->data.high < 0) |

468 | r -= a->data; |

469 | |

470 | /* Shift right the result by FBIT. */ |

471 | if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT) |

472 | { |

473 | s.low = r.low; |

474 | s.high = r.high; |

475 | if (unsigned_p) |

476 | { |

477 | r.low = 0; |

478 | r.high = 0; |

479 | } |

480 | else |

481 | { |

482 | r.low = -1; |

483 | r.high = -1; |

484 | } |

485 | f->data.low = s.low; |

486 | f->data.high = s.high; |

487 | } |

488 | else |

489 | { |

490 | s = s.llshift ((-GET_MODE_FBIT (f->mode)), HOST_BITS_PER_DOUBLE_INT); |

491 | f->data = r.llshift ((HOST_BITS_PER_DOUBLE_INT |

492 | - GET_MODE_FBIT (f->mode)), |

493 | HOST_BITS_PER_DOUBLE_INT); |

494 | f->data.low = f->data.low | s.low; |

495 | f->data.high = f->data.high | s.high; |

496 | s.low = f->data.low; |

497 | s.high = f->data.high; |

498 | r = r.lshift (-GET_MODE_FBIT (f->mode), |

499 | HOST_BITS_PER_DOUBLE_INT, !unsigned_p); |

500 | } |

501 | |

502 | overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p); |

503 | } |

504 | |

505 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

506 | return overflow_p; |

507 | } |

508 | |

509 | /* Calculate F = A / B. |

510 | If SAT_P, saturate the result to the max or the min. |

511 | Return true, if !SAT_P and overflow. */ |

512 | |

513 | static bool |

514 | do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, |

515 | const FIXED_VALUE_TYPE *b, bool sat_p) |

516 | { |

517 | bool overflow_p = false; |

518 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); |

519 | int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); |

520 | f->mode = a->mode; |

521 | if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT) |

522 | { |

523 | f->data = a->data.lshift (GET_MODE_FBIT (f->mode), |

524 | HOST_BITS_PER_DOUBLE_INT, !unsigned_p); |

525 | f->data = f->data.div (b->data, unsigned_p, TRUNC_DIV_EXPR); |

526 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); |

527 | } |

528 | else |

529 | { |

530 | double_int pos_a, pos_b, r, s; |

531 | double_int quo_r, quo_s, mod, temp; |

532 | int num_of_neg = 0; |

533 | int i; |

534 | |

535 | /* If a < 0, negate a. */ |

536 | if (!unsigned_p && a->data.high < 0) |

537 | { |

538 | pos_a = -a->data; |

539 | num_of_neg ++; |

540 | } |

541 | else |

542 | pos_a = a->data; |

543 | |

544 | /* If b < 0, negate b. */ |

545 | if (!unsigned_p && b->data.high < 0) |

546 | { |

547 | pos_b = -b->data; |

548 | num_of_neg ++; |

549 | } |

550 | else |

551 | pos_b = b->data; |

552 | |

553 | /* Left shift pos_a to {r, s} by FBIT. */ |

554 | if (GET_MODE_FBIT (f->mode) == HOST_BITS_PER_DOUBLE_INT) |

555 | { |

556 | r = pos_a; |

557 | s.high = 0; |

558 | s.low = 0; |

559 | } |

560 | else |

561 | { |

562 | s = pos_a.llshift (GET_MODE_FBIT (f->mode), HOST_BITS_PER_DOUBLE_INT); |

563 | r = pos_a.llshift (- (HOST_BITS_PER_DOUBLE_INT |

564 | - GET_MODE_FBIT (f->mode)), |

565 | HOST_BITS_PER_DOUBLE_INT); |

566 | } |

567 | |

568 | /* Divide r by pos_b to quo_r. The remainder is in mod. */ |

569 | quo_r = r.divmod (pos_b, 1, TRUNC_DIV_EXPR, &mod); |

570 | quo_s = double_int_zero; |

571 | |

572 | for (i = 0; i < HOST_BITS_PER_DOUBLE_INT; i++) |

573 | { |

574 | /* Record the leftmost bit of mod. */ |

575 | int leftmost_mod = (mod.high < 0); |

576 | |

577 | /* Shift left mod by 1 bit. */ |

578 | mod = mod.lshift (1); |

579 | |

580 | /* Test the leftmost bit of s to add to mod. */ |

581 | if (s.high < 0) |

582 | mod.low += 1; |

583 | |

584 | /* Shift left quo_s by 1 bit. */ |

585 | quo_s = quo_s.lshift (1); |

586 | |

587 | /* Try to calculate (mod - pos_b). */ |

588 | temp = mod - pos_b; |

589 | |

590 | if (leftmost_mod == 1 || mod.ucmp (pos_b) != -1) |

591 | { |

592 | quo_s.low += 1; |

593 | mod = temp; |

594 | } |

595 | |

596 | /* Shift left s by 1 bit. */ |

597 | s = s.lshift (1); |

598 | |

599 | } |

600 | |

601 | if (num_of_neg == 1) |

602 | { |

603 | quo_s = -quo_s; |

604 | if (quo_s.high == 0 && quo_s.low == 0) |

605 | quo_r = -quo_r; |

606 | else |

607 | { |

608 | quo_r.low = ~quo_r.low; |

609 | quo_r.high = ~quo_r.high; |

610 | } |

611 | } |

612 | |

613 | f->data = quo_s; |

614 | overflow_p = fixed_saturate2 (f->mode, quo_r, quo_s, &f->data, sat_p); |

615 | } |

616 | |

617 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

618 | return overflow_p; |

619 | } |

620 | |

621 | /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B. |

622 | If SAT_P, saturate the result to the max or the min. |

623 | Return true, if !SAT_P and overflow. */ |

624 | |

625 | static bool |

626 | do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, |

627 | const FIXED_VALUE_TYPE *b, bool left_p, bool sat_p) |

628 | { |

629 | bool overflow_p = false; |

630 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); |

631 | int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); |

632 | f->mode = a->mode; |

633 | |

634 | if (b->data.low == 0) |

635 | { |

636 | f->data = a->data; |

637 | return overflow_p; |

638 | } |

639 | |

640 | if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p)) |

641 | { |

642 | f->data = a->data.lshift (left_p ? b->data.low : -b->data.low, |

643 | HOST_BITS_PER_DOUBLE_INT, !unsigned_p); |

644 | if (left_p) /* Only left shift saturates. */ |

645 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); |

646 | } |

647 | else /* We need two double_int to store the left-shift result. */ |

648 | { |

649 | double_int temp_high, temp_low; |

650 | if (b->data.low == HOST_BITS_PER_DOUBLE_INT) |

651 | { |

652 | temp_high = a->data; |

653 | temp_low.high = 0; |

654 | temp_low.low = 0; |

655 | } |

656 | else |

657 | { |

658 | temp_low = a->data.lshift (b->data.low, |

659 | HOST_BITS_PER_DOUBLE_INT, !unsigned_p); |

660 | /* Logical shift right to temp_high. */ |

661 | temp_high = a->data.llshift (b->data.low - HOST_BITS_PER_DOUBLE_INT, |

662 | HOST_BITS_PER_DOUBLE_INT); |

663 | } |

664 | if (!unsigned_p && a->data.high < 0) /* Signed-extend temp_high. */ |

665 | temp_high = temp_high.ext (b->data.low, unsigned_p); |

666 | f->data = temp_low; |

667 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, |

668 | sat_p); |

669 | } |

670 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

671 | return overflow_p; |

672 | } |

673 | |

674 | /* Calculate F = -A. |

675 | If SAT_P, saturate the result to the max or the min. |

676 | Return true, if !SAT_P and overflow. */ |

677 | |

678 | static bool |

679 | do_fixed_neg (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, bool sat_p) |

680 | { |

681 | bool overflow_p = false; |

682 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); |

683 | int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); |

684 | f->mode = a->mode; |

685 | f->data = -a->data; |

686 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

687 | |

688 | if (unsigned_p) /* Unsigned type. */ |

689 | { |

690 | if (f->data.low != 0 || f->data.high != 0) |

691 | { |

692 | if (sat_p) |

693 | { |

694 | f->data.low = 0; |

695 | f->data.high = 0; |

696 | } |

697 | else |

698 | overflow_p = true; |

699 | } |

700 | } |

701 | else /* Signed type. */ |

702 | { |

703 | if (!(f->data.high == 0 && f->data.low == 0) |

704 | && f->data.high == a->data.high && f->data.low == a->data.low ) |

705 | { |

706 | if (sat_p) |

707 | { |

708 | /* Saturate to the maximum by subtracting f->data by one. */ |

709 | f->data.low = -1; |

710 | f->data.high = -1; |

711 | f->data = f->data.zext (i_f_bits); |

712 | } |

713 | else |

714 | overflow_p = true; |

715 | } |

716 | } |

717 | return overflow_p; |

718 | } |

719 | |

720 | /* Perform the binary or unary operation described by CODE. |

721 | Note that OP0 and OP1 must have the same mode for binary operators. |

722 | For a unary operation, leave OP1 NULL. |

723 | Return true, if !SAT_P and overflow. */ |

724 | |

725 | bool |

726 | fixed_arithmetic (FIXED_VALUE_TYPE *f, int icode, const FIXED_VALUE_TYPE *op0, |

727 | const FIXED_VALUE_TYPE *op1, bool sat_p) |

728 | { |

729 | switch (icode) |

730 | { |

731 | case NEGATE_EXPR: |

732 | return do_fixed_neg (f, op0, sat_p); |

733 | |

734 | case PLUS_EXPR: |

735 | gcc_assert (op0->mode == op1->mode); |

736 | return do_fixed_add (f, op0, op1, false, sat_p); |

737 | |

738 | case MINUS_EXPR: |

739 | gcc_assert (op0->mode == op1->mode); |

740 | return do_fixed_add (f, op0, op1, true, sat_p); |

741 | |

742 | case MULT_EXPR: |

743 | gcc_assert (op0->mode == op1->mode); |

744 | return do_fixed_multiply (f, op0, op1, sat_p); |

745 | |

746 | case TRUNC_DIV_EXPR: |

747 | gcc_assert (op0->mode == op1->mode); |

748 | return do_fixed_divide (f, op0, op1, sat_p); |

749 | |

750 | case LSHIFT_EXPR: |

751 | return do_fixed_shift (f, op0, op1, true, sat_p); |

752 | |

753 | case RSHIFT_EXPR: |

754 | return do_fixed_shift (f, op0, op1, false, sat_p); |

755 | |

756 | default: |

757 | gcc_unreachable (); |

758 | } |

759 | return false; |

760 | } |

761 | |

762 | /* Compare fixed-point values by tree_code. |

763 | Note that OP0 and OP1 must have the same mode. */ |

764 | |

765 | bool |

766 | fixed_compare (int icode, const FIXED_VALUE_TYPE *op0, |

767 | const FIXED_VALUE_TYPE *op1) |

768 | { |

769 | enum tree_code code = (enum tree_code) icode; |

770 | gcc_assert (op0->mode == op1->mode); |

771 | |

772 | switch (code) |

773 | { |

774 | case NE_EXPR: |

775 | return op0->data != op1->data; |

776 | |

777 | case EQ_EXPR: |

778 | return op0->data == op1->data; |

779 | |

780 | case LT_EXPR: |

781 | return op0->data.cmp (op1->data, |

782 | UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == -1; |

783 | |

784 | case LE_EXPR: |

785 | return op0->data.cmp (op1->data, |

786 | UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != 1; |

787 | |

788 | case GT_EXPR: |

789 | return op0->data.cmp (op1->data, |

790 | UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == 1; |

791 | |

792 | case GE_EXPR: |

793 | return op0->data.cmp (op1->data, |

794 | UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != -1; |

795 | |

796 | default: |

797 | gcc_unreachable (); |

798 | } |

799 | } |

800 | |

801 | /* Extend or truncate to a new mode. |

802 | If SAT_P, saturate the result to the max or the min. |

803 | Return true, if !SAT_P and overflow. */ |

804 | |

805 | bool |

806 | fixed_convert (FIXED_VALUE_TYPE *f, scalar_mode mode, |

807 | const FIXED_VALUE_TYPE *a, bool sat_p) |

808 | { |

809 | bool overflow_p = false; |

810 | if (mode == a->mode) |

811 | { |

812 | *f = *a; |

813 | return overflow_p; |

814 | } |

815 | |

816 | if (GET_MODE_FBIT (mode) > GET_MODE_FBIT (a->mode)) |

817 | { |

818 | /* Left shift a to temp_high, temp_low based on a->mode. */ |

819 | double_int temp_high, temp_low; |

820 | int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode); |

821 | temp_low = a->data.lshift (amount, |

822 | HOST_BITS_PER_DOUBLE_INT, |

823 | SIGNED_FIXED_POINT_MODE_P (a->mode)); |

824 | /* Logical shift right to temp_high. */ |

825 | temp_high = a->data.llshift (amount - HOST_BITS_PER_DOUBLE_INT, |

826 | HOST_BITS_PER_DOUBLE_INT); |

827 | if (SIGNED_FIXED_POINT_MODE_P (a->mode) |

828 | && a->data.high < 0) /* Signed-extend temp_high. */ |

829 | temp_high = temp_high.sext (amount); |

830 | f->mode = mode; |

831 | f->data = temp_low; |

832 | if (SIGNED_FIXED_POINT_MODE_P (a->mode) == |

833 | SIGNED_FIXED_POINT_MODE_P (f->mode)) |

834 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, |

835 | sat_p); |

836 | else |

837 | { |

838 | /* Take care of the cases when converting between signed and |

839 | unsigned. */ |

840 | if (SIGNED_FIXED_POINT_MODE_P (a->mode)) |

841 | { |

842 | /* Signed -> Unsigned. */ |

843 | if (a->data.high < 0) |

844 | { |

845 | if (sat_p) |

846 | { |

847 | f->data.low = 0; /* Set to zero. */ |

848 | f->data.high = 0; /* Set to zero. */ |

849 | } |

850 | else |

851 | overflow_p = true; |

852 | } |

853 | else |

854 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, |

855 | &f->data, sat_p); |

856 | } |

857 | else |

858 | { |

859 | /* Unsigned -> Signed. */ |

860 | if (temp_high.high < 0) |

861 | { |

862 | if (sat_p) |

863 | { |

864 | /* Set to maximum. */ |

865 | f->data.low = -1; /* Set to all ones. */ |

866 | f->data.high = -1; /* Set to all ones. */ |

867 | f->data = f->data.zext (GET_MODE_FBIT (f->mode) |

868 | + GET_MODE_IBIT (f->mode)); |

869 | /* Clear the sign. */ |

870 | } |

871 | else |

872 | overflow_p = true; |

873 | } |

874 | else |

875 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, |

876 | &f->data, sat_p); |

877 | } |

878 | } |

879 | } |

880 | else |

881 | { |

882 | /* Right shift a to temp based on a->mode. */ |

883 | double_int temp; |

884 | temp = a->data.lshift (GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode), |

885 | HOST_BITS_PER_DOUBLE_INT, |

886 | SIGNED_FIXED_POINT_MODE_P (a->mode)); |

887 | f->mode = mode; |

888 | f->data = temp; |

889 | if (SIGNED_FIXED_POINT_MODE_P (a->mode) == |

890 | SIGNED_FIXED_POINT_MODE_P (f->mode)) |

891 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); |

892 | else |

893 | { |

894 | /* Take care of the cases when converting between signed and |

895 | unsigned. */ |

896 | if (SIGNED_FIXED_POINT_MODE_P (a->mode)) |

897 | { |

898 | /* Signed -> Unsigned. */ |

899 | if (a->data.high < 0) |

900 | { |

901 | if (sat_p) |

902 | { |

903 | f->data.low = 0; /* Set to zero. */ |

904 | f->data.high = 0; /* Set to zero. */ |

905 | } |

906 | else |

907 | overflow_p = true; |

908 | } |

909 | else |

910 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, |

911 | sat_p); |

912 | } |

913 | else |

914 | { |

915 | /* Unsigned -> Signed. */ |

916 | if (temp.high < 0) |

917 | { |

918 | if (sat_p) |

919 | { |

920 | /* Set to maximum. */ |

921 | f->data.low = -1; /* Set to all ones. */ |

922 | f->data.high = -1; /* Set to all ones. */ |

923 | f->data = f->data.zext (GET_MODE_FBIT (f->mode) |

924 | + GET_MODE_IBIT (f->mode)); |

925 | /* Clear the sign. */ |

926 | } |

927 | else |

928 | overflow_p = true; |

929 | } |

930 | else |

931 | overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, |

932 | sat_p); |

933 | } |

934 | } |

935 | } |

936 | |

937 | f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode) |

938 | + GET_MODE_FBIT (f->mode) |

939 | + GET_MODE_IBIT (f->mode), |

940 | UNSIGNED_FIXED_POINT_MODE_P (f->mode)); |

941 | return overflow_p; |

942 | } |

943 | |

944 | /* Convert to a new fixed-point mode from an integer. |

945 | If UNSIGNED_P, this integer is unsigned. |

946 | If SAT_P, saturate the result to the max or the min. |

947 | Return true, if !SAT_P and overflow. */ |

948 | |

949 | bool |

950 | fixed_convert_from_int (FIXED_VALUE_TYPE *f, scalar_mode mode, |

951 | double_int a, bool unsigned_p, bool sat_p) |

952 | { |

953 | bool overflow_p = false; |

954 | /* Left shift a to temp_high, temp_low. */ |

955 | double_int temp_high, temp_low; |

956 | int amount = GET_MODE_FBIT (mode); |

957 | if (amount == HOST_BITS_PER_DOUBLE_INT) |

958 | { |

959 | temp_high = a; |

960 | temp_low.low = 0; |

961 | temp_low.high = 0; |

962 | } |

963 | else |

964 | { |

965 | temp_low = a.llshift (amount, HOST_BITS_PER_DOUBLE_INT); |

966 | |

967 | /* Logical shift right to temp_high. */ |

968 | temp_high = a.llshift (amount - HOST_BITS_PER_DOUBLE_INT, |

969 | HOST_BITS_PER_DOUBLE_INT); |

970 | } |

971 | if (!unsigned_p && a.high < 0) /* Signed-extend temp_high. */ |

972 | temp_high = temp_high.sext (amount); |

973 | |

974 | f->mode = mode; |

975 | f->data = temp_low; |

976 | |

977 | if (unsigned_p == UNSIGNED_FIXED_POINT_MODE_P (f->mode)) |

978 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, |

979 | sat_p); |

980 | else |

981 | { |

982 | /* Take care of the cases when converting between signed and unsigned. */ |

983 | if (!unsigned_p) |

984 | { |

985 | /* Signed -> Unsigned. */ |

986 | if (a.high < 0) |

987 | { |

988 | if (sat_p) |

989 | { |

990 | f->data.low = 0; /* Set to zero. */ |

991 | f->data.high = 0; /* Set to zero. */ |

992 | } |

993 | else |

994 | overflow_p = true; |

995 | } |

996 | else |

997 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, |

998 | &f->data, sat_p); |

999 | } |

1000 | else |

1001 | { |

1002 | /* Unsigned -> Signed. */ |

1003 | if (temp_high.high < 0) |

1004 | { |

1005 | if (sat_p) |

1006 | { |

1007 | /* Set to maximum. */ |

1008 | f->data.low = -1; /* Set to all ones. */ |

1009 | f->data.high = -1; /* Set to all ones. */ |

1010 | f->data = f->data.zext (GET_MODE_FBIT (f->mode) |

1011 | + GET_MODE_IBIT (f->mode)); |

1012 | /* Clear the sign. */ |

1013 | } |

1014 | else |

1015 | overflow_p = true; |

1016 | } |

1017 | else |

1018 | overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, |

1019 | &f->data, sat_p); |

1020 | } |

1021 | } |

1022 | f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode) |

1023 | + GET_MODE_FBIT (f->mode) |

1024 | + GET_MODE_IBIT (f->mode), |

1025 | UNSIGNED_FIXED_POINT_MODE_P (f->mode)); |

1026 | return overflow_p; |

1027 | } |

1028 | |

1029 | /* Convert to a new fixed-point mode from a real. |

1030 | If SAT_P, saturate the result to the max or the min. |

1031 | Return true, if !SAT_P and overflow. */ |

1032 | |

1033 | bool |

1034 | fixed_convert_from_real (FIXED_VALUE_TYPE *f, scalar_mode mode, |

1035 | const REAL_VALUE_TYPE *a, bool sat_p) |

1036 | { |

1037 | bool overflow_p = false; |

1038 | REAL_VALUE_TYPE real_value, fixed_value, base_value; |

1039 | bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); |

1040 | int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); |

1041 | unsigned int fbit = GET_MODE_FBIT (mode); |

1042 | enum fixed_value_range_code temp; |

1043 | bool fail; |

1044 | |

1045 | real_value = *a; |

1046 | f->mode = mode; |

1047 | real_2expN (&base_value, fbit, VOIDmode); |

1048 | real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); |

1049 | |

1050 | wide_int w = real_to_integer (&fixed_value, &fail, |

1051 | GET_MODE_PRECISION (mode)); |

1052 | f->data.low = w.ulow (); |

1053 | f->data.high = w.elt (1); |

1054 | temp = check_real_for_fixed_mode (&real_value, mode); |

1055 | if (temp == FIXED_UNDERFLOW) /* Minimum. */ |

1056 | { |

1057 | if (sat_p) |

1058 | { |

1059 | if (unsigned_p) |

1060 | { |

1061 | f->data.low = 0; |

1062 | f->data.high = 0; |

1063 | } |

1064 | else |

1065 | { |

1066 | f->data.low = 1; |

1067 | f->data.high = 0; |

1068 | f->data = f->data.alshift (i_f_bits, HOST_BITS_PER_DOUBLE_INT); |

1069 | f->data = f->data.sext (1 + i_f_bits); |

1070 | } |

1071 | } |

1072 | else |

1073 | overflow_p = true; |

1074 | } |

1075 | else if (temp == FIXED_GT_MAX_EPS || temp == FIXED_MAX_EPS) /* Maximum. */ |

1076 | { |

1077 | if (sat_p) |

1078 | { |

1079 | f->data.low = -1; |

1080 | f->data.high = -1; |

1081 | f->data = f->data.zext (i_f_bits); |

1082 | } |

1083 | else |

1084 | overflow_p = true; |

1085 | } |

1086 | f->data = f->data.ext ((!unsigned_p) + i_f_bits, unsigned_p); |

1087 | return overflow_p; |

1088 | } |

1089 | |

1090 | /* Convert to a new real mode from a fixed-point. */ |

1091 | |

1092 | void |

1093 | real_convert_from_fixed (REAL_VALUE_TYPE *r, scalar_mode mode, |

1094 | const FIXED_VALUE_TYPE *f) |

1095 | { |

1096 | REAL_VALUE_TYPE base_value, fixed_value, real_value; |

1097 | |

1098 | signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED; |

1099 | real_2expN (&base_value, GET_MODE_FBIT (f->mode), VOIDmode); |

1100 | real_from_integer (&fixed_value, VOIDmode, |

1101 | wide_int::from (f->data, GET_MODE_PRECISION (f->mode), |

1102 | sgn), sgn); |

1103 | real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value); |

1104 | real_convert (r, mode, &real_value); |

1105 | } |

1106 | |

1107 | /* Determine whether a fixed-point value F is negative. */ |

1108 | |

1109 | bool |

1110 | fixed_isneg (const FIXED_VALUE_TYPE *f) |

1111 | { |

1112 | if (SIGNED_FIXED_POINT_MODE_P (f->mode)) |

1113 | { |

1114 | int i_f_bits = GET_MODE_IBIT (f->mode) + GET_MODE_FBIT (f->mode); |

1115 | int sign_bit = get_fixed_sign_bit (f->data, i_f_bits); |

1116 | if (sign_bit == 1) |

1117 | return true; |

1118 | } |

1119 | |

1120 | return false; |

1121 | } |

1122 |