]>
Commit | Line | Data |
---|---|---|
154e4a0a | 1 | /* This is a software fixed-point library. |
a5544970 | 2 | Copyright (C) 2007-2019 Free Software Foundation, Inc. |
154e4a0a CF |
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 | |
748086b7 | 8 | Software Foundation; either version 3, or (at your option) any later |
154e4a0a CF |
9 | version. |
10 | ||
154e4a0a CF |
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 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
154e4a0a CF |
24 | |
25 | /* This implements fixed-point arithmetic. | |
26 | ||
27 | Contributed by Chao-ying Fu <fu@mips.com>. */ | |
28 | ||
29 | /* To use this file, we need to define one of the following: | |
30 | QQ_MODE, UQQ_MODE, HQ_MODE, UHQ_MODE, SQ_MODE, USQ_MODE, DQ_MODE, UDQ_MODE, | |
31 | TQ_MODE, UTQ_MODE, HA_MODE, UHA_MODE, SA_MODE, USA_MODE, DA_MODE, UDA_MODE, | |
32 | TA_MODE, UTA_MODE. | |
33 | Then, all operators for this machine mode will be created. | |
34 | ||
35 | Or, we need to define FROM_* TO_* for conversions from one mode to another | |
36 | mode. The mode could be one of the following: | |
37 | Fract: QQ, UQQ, HQ, UHQ, SQ, USQ, DQ, UDQ, TQ, UTQ | |
38 | Accum: HA, UHA, SA, USA, DA, UDA, TA, UTA | |
39 | Signed integer: QI, HI, SI, DI, TI | |
40 | Unsigned integer: UQI, UHI, USI, UDI, UTI | |
41 | Floating-point: SF, DF | |
42 | Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is | |
43 | generated. */ | |
44 | ||
45 | #include "tconfig.h" | |
46 | #include "tsystem.h" | |
47 | #include "coretypes.h" | |
48 | #include "tm.h" | |
852b75ed | 49 | #include "libgcc_tm.h" |
154e4a0a CF |
50 | |
51 | #ifndef MIN_UNITS_PER_WORD | |
52 | #define MIN_UNITS_PER_WORD UNITS_PER_WORD | |
53 | #endif | |
54 | ||
a039d7c2 | 55 | #include "fixed-bit.h" |
154e4a0a CF |
56 | |
57 | #if defined(FIXED_ADD) && defined(L_add) | |
58 | FIXED_C_TYPE | |
59 | FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
60 | { | |
61 | FIXED_C_TYPE c; | |
62 | INT_C_TYPE x, y, z; | |
63 | memcpy (&x, &a, FIXED_SIZE); | |
64 | memcpy (&y, &b, FIXED_SIZE); | |
65 | z = x + y; | |
66 | #if HAVE_PADDING_BITS | |
67 | z = z << PADDING_BITS; | |
68 | z = z >> PADDING_BITS; | |
69 | #endif | |
70 | memcpy (&c, &z, FIXED_SIZE); | |
71 | return c; | |
72 | } | |
73 | #endif /* FIXED_ADD */ | |
74 | ||
75 | #if defined(FIXED_SSADD) && defined(L_ssadd) | |
76 | FIXED_C_TYPE | |
77 | FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
78 | { | |
79 | FIXED_C_TYPE c; | |
80 | INT_C_TYPE x, y, z; | |
81 | memcpy (&x, &a, FIXED_SIZE); | |
82 | memcpy (&y, &b, FIXED_SIZE); | |
ee3ae4f7 | 83 | z = x + (UINT_C_TYPE) y; |
154e4a0a CF |
84 | if ((((x ^ y) >> I_F_BITS) & 1) == 0) |
85 | { | |
86 | if (((z ^ x) >> I_F_BITS) & 1) | |
87 | { | |
ee3ae4f7 JJ |
88 | z = ((UINT_C_TYPE) 1) << I_F_BITS; |
89 | if (x >= 0) | |
90 | z -= (UINT_C_TYPE) 1; | |
154e4a0a CF |
91 | } |
92 | } | |
93 | #if HAVE_PADDING_BITS | |
94 | z = z << PADDING_BITS; | |
95 | z = z >> PADDING_BITS; | |
96 | #endif | |
97 | memcpy (&c, &z, FIXED_SIZE); | |
98 | return c; | |
99 | } | |
100 | #endif /* FIXED_SSADD */ | |
101 | ||
102 | #if defined(FIXED_USADD) && defined(L_usadd) | |
103 | FIXED_C_TYPE | |
104 | FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
105 | { | |
106 | FIXED_C_TYPE c; | |
107 | INT_C_TYPE x, y, z; | |
108 | memcpy (&x, &a, FIXED_SIZE); | |
109 | memcpy (&y, &b, FIXED_SIZE); | |
110 | z = x + y; | |
111 | #if HAVE_PADDING_BITS | |
112 | z = z << PADDING_BITS; | |
113 | z = z >> PADDING_BITS; | |
114 | #endif | |
115 | if (z < x || z < y) /* max */ | |
116 | { | |
117 | z = -1; | |
118 | #if HAVE_PADDING_BITS | |
119 | z = z << PADDING_BITS; | |
120 | z = z >> PADDING_BITS; | |
121 | #endif | |
122 | } | |
123 | memcpy (&c, &z, FIXED_SIZE); | |
124 | return c; | |
125 | } | |
126 | #endif /* FIXED_USADD */ | |
127 | ||
128 | #if defined(FIXED_SUB) && defined(L_sub) | |
129 | FIXED_C_TYPE | |
130 | FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
131 | { | |
132 | FIXED_C_TYPE c; | |
133 | INT_C_TYPE x, y, z; | |
134 | memcpy (&x, &a, FIXED_SIZE); | |
135 | memcpy (&y, &b, FIXED_SIZE); | |
136 | z = x - y; | |
137 | #if HAVE_PADDING_BITS | |
138 | z = z << PADDING_BITS; | |
139 | z = z >> PADDING_BITS; | |
140 | #endif | |
141 | memcpy (&c, &z, FIXED_SIZE); | |
142 | return c; | |
143 | } | |
144 | #endif /* FIXED_SUB */ | |
145 | ||
146 | #if defined(FIXED_SSSUB) && defined(L_sssub) | |
147 | FIXED_C_TYPE | |
148 | FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
149 | { | |
150 | FIXED_C_TYPE c; | |
151 | INT_C_TYPE x, y, z; | |
152 | memcpy (&x, &a, FIXED_SIZE); | |
153 | memcpy (&y, &b, FIXED_SIZE); | |
ee3ae4f7 | 154 | z = x - (UINT_C_TYPE) y; |
154e4a0a CF |
155 | if (((x ^ y) >> I_F_BITS) & 1) |
156 | { | |
157 | if (((z ^ x) >> I_F_BITS) & 1) | |
158 | { | |
ee3ae4f7 JJ |
159 | z = ((UINT_C_TYPE) 1) << I_F_BITS; |
160 | if (x >= 0) | |
161 | z -= (UINT_C_TYPE) 1; | |
154e4a0a CF |
162 | } |
163 | } | |
164 | #if HAVE_PADDING_BITS | |
165 | z = z << PADDING_BITS; | |
166 | z = z >> PADDING_BITS; | |
167 | #endif | |
168 | memcpy (&c, &z, FIXED_SIZE); | |
169 | return c; | |
170 | } | |
171 | #endif /* FIXED_SSSUB */ | |
172 | ||
173 | #if defined(FIXED_USSUB) && defined(L_ussub) | |
174 | FIXED_C_TYPE | |
175 | FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
176 | { | |
177 | FIXED_C_TYPE c; | |
178 | INT_C_TYPE x, y, z; | |
179 | memcpy (&x, &a, FIXED_SIZE); | |
180 | memcpy (&y, &b, FIXED_SIZE); | |
181 | z = x - y; | |
182 | if (x < y) | |
183 | z = 0; | |
184 | #if HAVE_PADDING_BITS | |
185 | z = z << PADDING_BITS; | |
186 | z = z >> PADDING_BITS; | |
187 | #endif | |
188 | memcpy (&c, &z, FIXED_SIZE); | |
189 | return c; | |
190 | } | |
191 | #endif /* FIXED_USSUB */ | |
192 | ||
193 | #if defined(FIXED_SATURATE1) && defined(L_saturate1) | |
194 | void | |
195 | FIXED_SATURATE1 (DINT_C_TYPE *a) | |
196 | { | |
197 | DINT_C_TYPE max, min; | |
198 | max = (DINT_C_TYPE)1 << I_F_BITS; | |
199 | max = max - 1; | |
200 | #if MODE_UNSIGNED == 0 | |
201 | min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1); | |
202 | min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS); | |
203 | #else | |
204 | min = 0; | |
205 | #endif | |
206 | if (*a > max) | |
207 | *a = max; | |
208 | else if (*a < min) | |
209 | *a = min; | |
210 | } | |
211 | #endif /* FIXED_SATURATE1 */ | |
212 | ||
213 | #if defined(FIXED_SATURATE2) && defined(L_saturate2) | |
214 | void | |
215 | FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low) | |
216 | { | |
217 | INT_C_TYPE r_max, s_max, r_min, s_min; | |
218 | r_max = 0; | |
219 | #if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS | |
220 | s_max = (INT_C_TYPE)1 << I_F_BITS; | |
221 | s_max = s_max - 1; | |
222 | #else | |
223 | s_max = -1; | |
224 | #endif | |
225 | #if MODE_UNSIGNED == 0 | |
226 | r_min = -1; | |
227 | s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1); | |
228 | s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS); | |
229 | #else | |
230 | r_min = 0; | |
231 | s_min = 0; | |
232 | #endif | |
233 | ||
234 | if (*high > r_max | |
235 | || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max)) | |
236 | { | |
237 | *high = r_max; | |
238 | *low = s_max; | |
239 | } | |
240 | else if (*high < r_min || | |
241 | (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min)) | |
242 | { | |
243 | *high = r_min; | |
244 | *low = s_min; | |
245 | } | |
246 | } | |
247 | #endif /* FIXED_SATURATE2 */ | |
248 | ||
249 | #if defined(FIXED_MULHELPER) && defined(L_mulhelper) | |
250 | FIXED_C_TYPE | |
251 | FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp) | |
252 | { | |
253 | FIXED_C_TYPE c; | |
254 | INT_C_TYPE x, y; | |
255 | ||
256 | #if defined (DINT_C_TYPE) | |
257 | INT_C_TYPE z; | |
258 | DINT_C_TYPE dx, dy, dz; | |
259 | memcpy (&x, &a, FIXED_SIZE); | |
260 | memcpy (&y, &b, FIXED_SIZE); | |
261 | dx = (DINT_C_TYPE) x; | |
262 | dy = (DINT_C_TYPE) y; | |
263 | dz = dx * dy; | |
264 | /* Round the result by adding (1 << (FBITS -1)). */ | |
265 | dz += ((DINT_C_TYPE) 1 << (FBITS - 1)); | |
266 | dz = dz >> FBITS; | |
267 | if (satp) | |
268 | FIXED_SATURATE1 (&dz); | |
269 | ||
270 | z = (INT_C_TYPE) dz; | |
271 | #if HAVE_PADDING_BITS | |
272 | z = z << PADDING_BITS; | |
273 | z = z >> PADDING_BITS; | |
274 | #endif | |
275 | memcpy (&c, &z, FIXED_SIZE); | |
276 | return c; | |
277 | ||
278 | #else /* No DINT_C_TYPE */ | |
279 | /* The result of multiplication expands to two INT_C_TYPE. */ | |
280 | INTunion aa, bb; | |
281 | INTunion a_high, a_low, b_high, b_low; | |
282 | INTunion high_high, high_low, low_high, low_low; | |
283 | INTunion r, s, temp1, temp2; | |
284 | INT_C_TYPE carry = 0; | |
285 | INT_C_TYPE z; | |
286 | ||
287 | memcpy (&x, &a, FIXED_SIZE); | |
288 | memcpy (&y, &b, FIXED_SIZE); | |
289 | ||
290 | /* Decompose a and b. */ | |
291 | aa.ll = x; | |
292 | bb.ll = y; | |
293 | ||
294 | a_high.s.low = aa.s.high; | |
295 | a_high.s.high = 0; | |
296 | a_low.s.low = aa.s.low; | |
297 | a_low.s.high = 0; | |
298 | b_high.s.low = bb.s.high; | |
299 | b_high.s.high = 0; | |
300 | b_low.s.low = bb.s.low; | |
301 | b_low.s.high = 0; | |
302 | ||
303 | /* Perform four multiplications. */ | |
304 | low_low.ll = a_low.ll * b_low.ll; | |
305 | low_high.ll = a_low.ll * b_high.ll; | |
306 | high_low.ll = a_high.ll * b_low.ll; | |
307 | high_high.ll = a_high.ll * b_high.ll; | |
308 | ||
309 | /* Accumulate four results to {r, s}. */ | |
310 | temp1.s.high = high_low.s.low; | |
311 | temp1.s.low = 0; | |
312 | s.ll = low_low.ll + temp1.ll; | |
313 | if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll | |
314 | || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll) | |
315 | carry ++; /* Carry. */ | |
316 | temp1.ll = s.ll; | |
317 | temp2.s.high = low_high.s.low; | |
318 | temp2.s.low = 0; | |
319 | s.ll = temp1.ll + temp2.ll; | |
320 | if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll | |
321 | || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll) | |
322 | carry ++; /* Carry. */ | |
323 | ||
324 | temp1.s.low = high_low.s.high; | |
325 | temp1.s.high = 0; | |
326 | r.ll = high_high.ll + temp1.ll; | |
327 | temp1.s.low = low_high.s.high; | |
328 | temp1.s.high = 0; | |
329 | r.ll = r.ll + temp1.ll + carry; | |
330 | ||
331 | #if MODE_UNSIGNED == 0 | |
332 | /* For signed types, we need to add neg(y) to r, if x < 0. */ | |
333 | if (x < 0) | |
334 | r.ll = r.ll - y; | |
335 | /* We need to add neg(x) to r, if y < 0. */ | |
336 | if (y < 0) | |
337 | r.ll = r.ll - x; | |
338 | #endif | |
339 | ||
340 | /* Round the result by adding (1 << (FBITS -1)). */ | |
341 | temp1.ll = s.ll; | |
342 | s.ll += ((INT_C_TYPE) 1 << (FBITS -1)); | |
343 | if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll | |
344 | || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1))) | |
345 | r.ll += 1; | |
346 | ||
347 | /* Shift right the result by FBITS. */ | |
348 | #if FBITS == FIXED_WIDTH | |
349 | /* This happens only for unsigned types without any padding bits. | |
350 | So, it is safe to set r.ll to 0 as it is logically shifted right. */ | |
351 | s.ll = r.ll; | |
352 | r.ll = 0; | |
353 | #else | |
354 | s.ll = ((UINT_C_TYPE)s.ll) >> FBITS; | |
355 | temp1.ll = r.ll << (FIXED_WIDTH - FBITS); | |
356 | s.ll = s.ll | temp1.ll; | |
357 | r.ll = r.ll >> FBITS; | |
358 | #endif | |
359 | ||
360 | if (satp) | |
361 | FIXED_SATURATE2 (&r.ll, &s.ll); | |
362 | ||
363 | z = (INT_C_TYPE) s.ll; | |
364 | #if HAVE_PADDING_BITS | |
365 | z = z << PADDING_BITS; | |
366 | z = z >> PADDING_BITS; | |
367 | #endif | |
368 | memcpy (&c, &z, FIXED_SIZE); | |
369 | return c; | |
370 | #endif | |
371 | } | |
372 | #endif /* FIXED_MULHELPER */ | |
373 | ||
374 | #if defined(FIXED_MUL) && defined(L_mul) | |
375 | FIXED_C_TYPE | |
376 | FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
377 | { | |
378 | return FIXED_MULHELPER (a, b, 0); | |
379 | } | |
380 | #endif /* FIXED_MUL */ | |
381 | ||
382 | #if defined(FIXED_SSMUL) && defined(L_ssmul) | |
383 | FIXED_C_TYPE | |
384 | FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
385 | { | |
386 | return FIXED_MULHELPER (a, b, 1); | |
387 | } | |
388 | #endif /* FIXED_SSMUL */ | |
389 | ||
390 | #if defined(FIXED_USMUL) && defined(L_usmul) | |
391 | FIXED_C_TYPE | |
392 | FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
393 | { | |
394 | return FIXED_MULHELPER (a, b, 1); | |
395 | } | |
396 | #endif /* FIXED_USMUL */ | |
397 | ||
398 | #if defined(FIXED_DIVHELPER) && defined(L_divhelper) | |
399 | FIXED_C_TYPE | |
400 | FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp) | |
401 | { | |
402 | FIXED_C_TYPE c; | |
403 | INT_C_TYPE x, y; | |
404 | INT_C_TYPE z; | |
405 | ||
406 | #if defined (DINT_C_TYPE) | |
407 | DINT_C_TYPE dx, dy, dz; | |
408 | memcpy (&x, &a, FIXED_SIZE); | |
409 | memcpy (&y, &b, FIXED_SIZE); | |
410 | dx = (DINT_C_TYPE) x; | |
411 | dy = (DINT_C_TYPE) y; | |
412 | dx = dx << FBITS; | |
413 | dz = dx / dy; | |
414 | if (satp) | |
415 | FIXED_SATURATE1 (&dz); | |
416 | z = (INT_C_TYPE) dz; | |
417 | #if HAVE_PADDING_BITS | |
418 | z = z << PADDING_BITS; | |
419 | z = z >> PADDING_BITS; | |
420 | #endif | |
421 | memcpy (&c, &z, FIXED_SIZE); | |
422 | return c; | |
423 | ||
424 | #else /* No DINT_C_TYPE */ | |
425 | INT_C_TYPE pos_a, pos_b, r, s; | |
426 | INT_C_TYPE quo_r, quo_s, mod, temp; | |
427 | word_type i; | |
428 | #if MODE_UNSIGNED == 0 | |
429 | word_type num_of_neg = 0; | |
430 | #endif | |
431 | ||
432 | memcpy (&x, &a, FIXED_SIZE); | |
433 | memcpy (&y, &b, FIXED_SIZE); | |
434 | pos_a = x; | |
435 | pos_b = y; | |
436 | ||
437 | #if MODE_UNSIGNED == 0 | |
438 | /* If a < 0, negate a. */ | |
439 | if (pos_a < 0) | |
440 | { | |
441 | pos_a = -pos_a; | |
442 | num_of_neg ++; | |
443 | } | |
444 | /* If b < 0, negate b. */ | |
445 | if (pos_b < 0) | |
446 | { | |
447 | pos_b = -pos_b; | |
448 | num_of_neg ++; | |
449 | } | |
450 | #endif | |
451 | ||
452 | /* Left shift pos_a to {r, s} by FBITS. */ | |
453 | #if FBITS == FIXED_WIDTH | |
454 | /* This happens only for unsigned types without any padding bits. */ | |
455 | r = pos_a; | |
456 | s = 0; | |
457 | #else | |
458 | s = pos_a << FBITS; | |
459 | r = pos_a >> (FIXED_WIDTH - FBITS); | |
460 | #endif | |
461 | ||
84fbffb2 | 462 | /* Unsigned divide r by pos_b to quo_r. The remainder is in mod. */ |
154e4a0a CF |
463 | quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b; |
464 | mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b; | |
465 | quo_s = 0; | |
466 | ||
467 | for (i = 0; i < FIXED_WIDTH; i++) | |
468 | { | |
469 | /* Record the leftmost bit of mod. */ | |
470 | word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1; | |
471 | /* Shift left mod by 1 bit. */ | |
472 | mod = mod << 1; | |
473 | /* Test the leftmost bit of s to add to mod. */ | |
474 | if ((s >> (FIXED_WIDTH - 1)) & 1) | |
475 | mod ++; | |
476 | /* Shift left quo_s by 1 bit. */ | |
477 | quo_s = quo_s << 1; | |
478 | /* Try to calculate (mod - pos_b). */ | |
479 | temp = mod - pos_b; | |
480 | if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b) | |
481 | { | |
482 | quo_s ++; | |
483 | mod = temp; | |
484 | } | |
485 | /* Shift left s by 1 bit. */ | |
486 | s = s << 1; | |
487 | } | |
488 | ||
489 | #if MODE_UNSIGNED == 0 | |
490 | if (num_of_neg == 1) | |
491 | { | |
492 | quo_s = -quo_s; | |
493 | if (quo_s == 0) | |
494 | quo_r = -quo_r; | |
495 | else | |
496 | quo_r = ~quo_r; | |
497 | } | |
498 | #endif | |
499 | if (satp) | |
500 | FIXED_SATURATE2 (&quo_r, &quo_s); | |
501 | z = quo_s; | |
502 | #if HAVE_PADDING_BITS | |
503 | z = z << PADDING_BITS; | |
504 | z = z >> PADDING_BITS; | |
505 | #endif | |
506 | memcpy (&c, &z, FIXED_SIZE); | |
507 | return c; | |
508 | #endif | |
509 | } | |
510 | #endif /* FIXED_DIVHELPER */ | |
511 | ||
512 | #if defined(FIXED_DIV) && defined(L_div) | |
513 | FIXED_C_TYPE | |
514 | FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
515 | { | |
516 | return FIXED_DIVHELPER (a, b, 0); | |
517 | } | |
518 | #endif /* FIXED_DIV */ | |
519 | ||
520 | ||
521 | #if defined(FIXED_UDIV) && defined(L_udiv) | |
522 | FIXED_C_TYPE | |
523 | FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
524 | { | |
525 | return FIXED_DIVHELPER (a, b, 0); | |
526 | } | |
527 | #endif /* FIXED_UDIV */ | |
528 | ||
529 | #if defined(FIXED_SSDIV) && defined(L_ssdiv) | |
530 | FIXED_C_TYPE | |
531 | FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
532 | { | |
533 | return FIXED_DIVHELPER (a, b, 1); | |
534 | } | |
535 | #endif /* FIXED_SSDIV */ | |
536 | ||
537 | #if defined(FIXED_USDIV) && defined(L_usdiv) | |
538 | FIXED_C_TYPE | |
539 | FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
540 | { | |
541 | return FIXED_DIVHELPER (a, b, 1); | |
542 | } | |
543 | #endif /* FIXED_USDIV */ | |
544 | ||
545 | #if defined(FIXED_NEG) && defined(L_neg) | |
546 | FIXED_C_TYPE | |
547 | FIXED_NEG (FIXED_C_TYPE a) | |
548 | { | |
549 | FIXED_C_TYPE c; | |
550 | INT_C_TYPE x, z; | |
551 | memcpy (&x, &a, FIXED_SIZE); | |
552 | z = -x; | |
553 | #if HAVE_PADDING_BITS | |
554 | z = z << PADDING_BITS; | |
555 | z = z >> PADDING_BITS; | |
556 | #endif | |
557 | memcpy (&c, &z, FIXED_SIZE); | |
558 | return c; | |
559 | } | |
560 | #endif /* FIXED_NEG */ | |
561 | ||
562 | #if defined(FIXED_SSNEG) && defined(L_ssneg) | |
563 | FIXED_C_TYPE | |
564 | FIXED_SSNEG (FIXED_C_TYPE a) | |
565 | { | |
566 | FIXED_C_TYPE c; | |
567 | INT_C_TYPE x, y, z; | |
568 | memcpy (&y, &a, FIXED_SIZE); | |
569 | x = 0; | |
ee3ae4f7 | 570 | z = x - (UINT_C_TYPE) y; |
154e4a0a CF |
571 | if (((x ^ y) >> I_F_BITS) & 1) |
572 | { | |
573 | if (((z ^ x) >> I_F_BITS) & 1) | |
ee3ae4f7 | 574 | z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1; |
154e4a0a CF |
575 | } |
576 | #if HAVE_PADDING_BITS | |
577 | z = z << PADDING_BITS; | |
578 | z = z >> PADDING_BITS; | |
579 | #endif | |
580 | memcpy (&c, &z, FIXED_SIZE); | |
581 | return c; | |
582 | } | |
583 | #endif /* FIXED_SSNEG */ | |
584 | ||
585 | #if defined(FIXED_USNEG) && defined(L_usneg) | |
586 | FIXED_C_TYPE | |
587 | FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__))) | |
588 | { | |
589 | FIXED_C_TYPE c; | |
590 | INT_C_TYPE z; | |
591 | z = 0; | |
592 | memcpy (&c, &z, FIXED_SIZE); | |
593 | return c; | |
594 | } | |
595 | #endif /* FIXED_USNEG */ | |
596 | ||
597 | #if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper) | |
598 | FIXED_C_TYPE | |
599 | FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp) | |
600 | { | |
601 | FIXED_C_TYPE c; | |
602 | INT_C_TYPE x, z; | |
603 | ||
604 | #if defined (DINT_C_TYPE) | |
605 | DINT_C_TYPE dx, dz; | |
606 | memcpy (&x, &a, FIXED_SIZE); | |
607 | dx = (DINT_C_TYPE) x; | |
608 | if (b >= FIXED_WIDTH) | |
609 | dz = dx << FIXED_WIDTH; | |
610 | else | |
611 | dz = dx << b; | |
612 | if (satp) | |
613 | FIXED_SATURATE1 (&dz); | |
614 | z = (INT_C_TYPE) dz; | |
615 | #if HAVE_PADDING_BITS | |
616 | z = z << PADDING_BITS; | |
617 | z = z >> PADDING_BITS; | |
618 | #endif | |
619 | memcpy (&c, &z, FIXED_SIZE); | |
620 | return c; | |
621 | ||
622 | #else /* No DINT_C_TYPE */ | |
623 | INT_C_TYPE r, s; | |
624 | memcpy (&x, &a, FIXED_SIZE); | |
625 | /* We need to shift left x by b bits to {r, s}. */ | |
626 | if (b >= FIXED_WIDTH) | |
627 | { | |
628 | r = b; | |
629 | s = 0; | |
630 | } | |
631 | else | |
632 | { | |
633 | s = x << b; | |
634 | r = x >> (FIXED_WIDTH - b); | |
635 | } | |
636 | if (satp) | |
637 | FIXED_SATURATE2 (&r, &s); | |
638 | z = s; | |
639 | #if HAVE_PADDING_BITS | |
640 | z = z << PADDING_BITS; | |
641 | z = z >> PADDING_BITS; | |
642 | #endif | |
643 | memcpy (&c, &z, FIXED_SIZE); | |
644 | return c; | |
645 | #endif | |
646 | } | |
647 | #endif /* FIXED_ASHLHELPER */ | |
648 | ||
649 | #if defined(FIXED_ASHL) && defined(L_ashl) | |
650 | FIXED_C_TYPE | |
651 | FIXED_ASHL (FIXED_C_TYPE a, word_type b) | |
652 | { | |
653 | return FIXED_ASHLHELPER (a, b, 0); | |
654 | } | |
655 | #endif /* FIXED_ASHL */ | |
656 | ||
657 | #if defined(FIXED_ASHR) && defined(L_ashr) | |
658 | FIXED_C_TYPE | |
659 | FIXED_ASHR (FIXED_C_TYPE a, word_type b) | |
660 | { | |
661 | FIXED_C_TYPE c; | |
662 | INT_C_TYPE x, z; | |
663 | memcpy (&x, &a, FIXED_SIZE); | |
664 | z = x >> b; | |
665 | #if HAVE_PADDING_BITS | |
666 | z = z << PADDING_BITS; | |
667 | z = z >> PADDING_BITS; | |
668 | #endif | |
669 | memcpy (&c, &z, FIXED_SIZE); | |
670 | return c; | |
671 | } | |
672 | #endif /* FIXED_ASHR */ | |
673 | ||
674 | #if defined(FIXED_LSHR) && defined(L_lshr) | |
675 | FIXED_C_TYPE | |
676 | FIXED_LSHR (FIXED_C_TYPE a, word_type b) | |
677 | { | |
678 | FIXED_C_TYPE c; | |
679 | INT_C_TYPE x, z; | |
680 | memcpy (&x, &a, FIXED_SIZE); | |
681 | z = x >> b; | |
682 | #if HAVE_PADDING_BITS | |
683 | z = z << PADDING_BITS; | |
684 | z = z >> PADDING_BITS; | |
685 | #endif | |
686 | memcpy (&c, &z, FIXED_SIZE); | |
687 | return c; | |
688 | } | |
689 | #endif /* FIXED_LSHR */ | |
690 | ||
691 | #if defined(FIXED_SSASHL) && defined(L_ssashl) | |
692 | FIXED_C_TYPE | |
693 | FIXED_SSASHL (FIXED_C_TYPE a, word_type b) | |
694 | { | |
695 | return FIXED_ASHLHELPER (a, b, 1); | |
696 | } | |
697 | #endif /* FIXED_SSASHL */ | |
698 | ||
699 | #if defined(FIXED_USASHL) && defined(L_usashl) | |
700 | FIXED_C_TYPE | |
701 | FIXED_USASHL (FIXED_C_TYPE a, word_type b) | |
702 | { | |
703 | return FIXED_ASHLHELPER (a, b, 1); | |
704 | } | |
705 | #endif /* FIXED_USASHL */ | |
706 | ||
707 | #if defined(FIXED_CMP) && defined(L_cmp) | |
708 | word_type | |
709 | FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b) | |
710 | { | |
711 | INT_C_TYPE x, y; | |
712 | memcpy (&x, &a, FIXED_SIZE); | |
713 | memcpy (&y, &b, FIXED_SIZE); | |
714 | ||
715 | if (x < y) | |
716 | return 0; | |
717 | else if (x > y) | |
718 | return 2; | |
719 | ||
720 | return 1; | |
721 | } | |
722 | #endif /* FIXED_CMP */ | |
723 | ||
724 | /* Fixed -> Fixed. */ | |
725 | #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4 | |
726 | TO_FIXED_C_TYPE | |
727 | FRACT (FROM_FIXED_C_TYPE a) | |
728 | { | |
729 | TO_FIXED_C_TYPE c; | |
730 | FROM_INT_C_TYPE x; | |
731 | TO_INT_C_TYPE z; | |
732 | int shift_amount; | |
733 | memcpy (&x, &a, FROM_FIXED_SIZE); | |
734 | #if TO_FBITS > FROM_FBITS /* Need left shift. */ | |
735 | shift_amount = TO_FBITS - FROM_FBITS; | |
736 | z = (TO_INT_C_TYPE) x; | |
737 | z = z << shift_amount; | |
738 | #else /* TO_FBITS <= FROM_FBITS. Need right Shift. */ | |
739 | shift_amount = FROM_FBITS - TO_FBITS; | |
740 | x = x >> shift_amount; | |
741 | z = (TO_INT_C_TYPE) x; | |
742 | #endif /* TO_FBITS > FROM_FBITS */ | |
743 | ||
744 | #if TO_HAVE_PADDING_BITS | |
745 | z = z << TO_PADDING_BITS; | |
746 | z = z >> TO_PADDING_BITS; | |
747 | #endif | |
748 | memcpy (&c, &z, TO_FIXED_SIZE); | |
749 | return c; | |
750 | } | |
751 | #endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4 */ | |
752 | ||
753 | /* Fixed -> Fixed with saturation. */ | |
754 | #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4 | |
755 | TO_FIXED_C_TYPE | |
756 | SATFRACT (FROM_FIXED_C_TYPE a) | |
757 | { | |
758 | TO_FIXED_C_TYPE c; | |
759 | TO_INT_C_TYPE z; | |
760 | FROM_INT_C_TYPE x; | |
761 | #if FROM_MODE_UNSIGNED == 0 | |
762 | BIG_SINT_C_TYPE high, low; | |
763 | BIG_SINT_C_TYPE max_high, max_low; | |
3ffc1958 | 764 | #if TO_MODE_UNSIGNED == 0 |
154e4a0a | 765 | BIG_SINT_C_TYPE min_high, min_low; |
3ffc1958 | 766 | #endif |
154e4a0a CF |
767 | #else |
768 | BIG_UINT_C_TYPE high, low; | |
769 | BIG_UINT_C_TYPE max_high, max_low; | |
154e4a0a CF |
770 | #endif |
771 | #if TO_FBITS > FROM_FBITS | |
772 | BIG_UINT_C_TYPE utemp; | |
773 | #endif | |
774 | #if TO_MODE_UNSIGNED == 0 | |
775 | BIG_SINT_C_TYPE stemp; | |
776 | #endif | |
777 | #if TO_FBITS != FROM_FBITS | |
778 | int shift_amount; | |
779 | #endif | |
780 | memcpy (&x, &a, FROM_FIXED_SIZE); | |
781 | ||
782 | /* Step 1. We need to store x to {high, low}. */ | |
783 | #if FROM_MODE_UNSIGNED == 0 | |
784 | low = (BIG_SINT_C_TYPE) x; | |
785 | if (x < 0) | |
786 | high = -1; | |
787 | else | |
788 | high = 0; | |
789 | #else | |
790 | low = (BIG_UINT_C_TYPE) x; | |
791 | high = 0; | |
792 | #endif | |
793 | ||
794 | /* Step 2. We need to shift {high, low}. */ | |
795 | #if TO_FBITS > FROM_FBITS /* Left shift. */ | |
796 | shift_amount = TO_FBITS - FROM_FBITS; | |
797 | utemp = (BIG_UINT_C_TYPE) low; | |
798 | utemp = utemp >> (BIG_WIDTH - shift_amount); | |
799 | high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; | |
800 | low = low << shift_amount; | |
801 | #elif TO_FBITS < FROM_FBITS /* Right shift. */ | |
802 | shift_amount = FROM_FBITS - TO_FBITS; | |
803 | low = low >> shift_amount; | |
804 | #endif | |
805 | ||
806 | /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ | |
807 | max_high = 0; | |
808 | #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS | |
809 | max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; | |
810 | max_low = max_low - 1; | |
811 | #else | |
812 | max_low = -1; | |
813 | #endif | |
814 | ||
815 | #if TO_MODE_UNSIGNED == 0 | |
154e4a0a CF |
816 | stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1); |
817 | stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS); | |
3ffc1958 GJL |
818 | #if FROM_MODE_UNSIGNED == 0 |
819 | min_high = -1; | |
154e4a0a | 820 | min_low = stemp; |
3ffc1958 | 821 | #endif |
154e4a0a CF |
822 | #endif |
823 | ||
824 | #if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0 | |
825 | /* Signed -> Signed. */ | |
826 | if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high | |
827 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high | |
828 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
829 | low = max_low; /* Maximum. */ | |
830 | else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high | |
831 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high | |
832 | && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low)) | |
833 | low = min_low; /* Minimum. */ | |
834 | #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1 | |
835 | /* Unigned -> Unsigned. */ | |
836 | if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high | |
837 | || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high | |
838 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
839 | low = max_low; /* Maximum. */ | |
840 | #elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1 | |
841 | /* Signed -> Unsigned. */ | |
842 | if (x < 0) | |
843 | low = 0; /* Minimum. */ | |
844 | else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high | |
845 | || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high | |
846 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
847 | low = max_low; /* Maximum. */ | |
848 | #elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0 | |
849 | /* Unsigned -> Signed. */ | |
850 | if ((BIG_SINT_C_TYPE) high < 0) | |
851 | low = max_low; /* Maximum. */ | |
852 | else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high | |
853 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high | |
854 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
855 | low = max_low; /* Maximum. */ | |
856 | #endif | |
857 | ||
858 | /* Step 4. Store the result. */ | |
859 | z = (TO_INT_C_TYPE) low; | |
860 | #if TO_HAVE_PADDING_BITS | |
861 | z = z << TO_PADDING_BITS; | |
862 | z = z >> TO_PADDING_BITS; | |
863 | #endif | |
864 | memcpy (&c, &z, TO_FIXED_SIZE); | |
865 | return c; | |
866 | } | |
867 | #endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4 */ | |
868 | ||
869 | /* Fixed -> Int. */ | |
870 | #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1 | |
871 | TO_INT_C_TYPE | |
872 | FRACT (FROM_FIXED_C_TYPE a) | |
873 | { | |
874 | FROM_INT_C_TYPE x; | |
875 | TO_INT_C_TYPE z; | |
876 | FROM_INT_C_TYPE i = 0; | |
877 | memcpy (&x, &a, FROM_FIXED_SIZE); | |
878 | ||
879 | #if FROM_MODE_UNSIGNED == 0 | |
880 | if (x < 0) | |
881 | { | |
882 | #if FROM_FIXED_WIDTH == FROM_FBITS | |
883 | if (x != 0) | |
884 | i = 1; | |
885 | #else | |
886 | if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0) | |
887 | i = 1; | |
888 | #endif | |
889 | } | |
890 | #endif | |
891 | ||
892 | #if FROM_FIXED_WIDTH == FROM_FBITS | |
893 | x = 0; | |
894 | #else | |
895 | x = x >> FROM_FBITS; | |
896 | #endif | |
897 | x = x + i; | |
898 | z = (TO_INT_C_TYPE) x; | |
899 | return z; | |
900 | } | |
901 | #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1 */ | |
902 | ||
903 | /* Fixed -> Unsigned int. */ | |
904 | #if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2 | |
905 | TO_INT_C_TYPE | |
906 | FRACTUNS (FROM_FIXED_C_TYPE a) | |
907 | { | |
908 | FROM_INT_C_TYPE x; | |
909 | TO_INT_C_TYPE z; | |
910 | FROM_INT_C_TYPE i = 0; | |
911 | memcpy (&x, &a, FROM_FIXED_SIZE); | |
912 | ||
913 | #if FROM_MODE_UNSIGNED == 0 | |
914 | if (x < 0) | |
915 | { | |
916 | #if FROM_FIXED_WIDTH == FROM_FBITS | |
917 | if (x != 0) | |
918 | i = 1; | |
919 | #else | |
920 | if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0) | |
921 | i = 1; | |
922 | #endif | |
923 | } | |
924 | #endif | |
925 | ||
926 | #if FROM_FIXED_WIDTH == FROM_FBITS | |
927 | x = 0; | |
928 | #else | |
929 | x = x >> FROM_FBITS; | |
930 | #endif | |
931 | x = x + i; | |
932 | z = (TO_INT_C_TYPE) x; | |
933 | return z; | |
934 | } | |
935 | #endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2 */ | |
936 | ||
937 | /* Int -> Fixed. */ | |
938 | #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4 | |
939 | TO_FIXED_C_TYPE | |
940 | FRACT (FROM_INT_C_TYPE a) | |
941 | { | |
942 | TO_FIXED_C_TYPE c; | |
943 | TO_INT_C_TYPE z; | |
944 | z = (TO_INT_C_TYPE) a; | |
945 | #if TO_FIXED_WIDTH == TO_FBITS | |
946 | z = 0; | |
947 | #else | |
948 | z = z << TO_FBITS; | |
949 | #endif | |
950 | #if TO_HAVE_PADDING_BITS | |
951 | z = z << TO_PADDING_BITS; | |
952 | z = z >> TO_PADDING_BITS; | |
953 | #endif | |
954 | memcpy (&c, &z, TO_FIXED_SIZE); | |
955 | return c; | |
956 | } | |
957 | #endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */ | |
958 | ||
959 | /* Signed int -> Fixed with saturation. */ | |
3ffc1958 | 960 | #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 1 && TO_TYPE == 4 |
154e4a0a CF |
961 | TO_FIXED_C_TYPE |
962 | SATFRACT (FROM_INT_C_TYPE a) | |
963 | { | |
964 | TO_FIXED_C_TYPE c; | |
965 | TO_INT_C_TYPE z; | |
966 | FROM_INT_C_TYPE x = a; | |
967 | BIG_SINT_C_TYPE high, low; | |
968 | BIG_SINT_C_TYPE max_high, max_low; | |
154e4a0a | 969 | #if TO_MODE_UNSIGNED == 0 |
3ffc1958 | 970 | BIG_SINT_C_TYPE min_high, min_low; |
154e4a0a CF |
971 | BIG_SINT_C_TYPE stemp; |
972 | #endif | |
973 | #if BIG_WIDTH != TO_FBITS | |
974 | BIG_UINT_C_TYPE utemp; | |
975 | int shift_amount; | |
976 | #endif | |
977 | ||
978 | /* Step 1. We need to store x to {high, low}. */ | |
979 | low = (BIG_SINT_C_TYPE) x; | |
980 | if (x < 0) | |
981 | high = -1; | |
982 | else | |
983 | high = 0; | |
984 | ||
985 | /* Step 2. We need to left shift {high, low}. */ | |
986 | #if BIG_WIDTH == TO_FBITS | |
987 | high = low; | |
988 | low = 0; | |
989 | #else | |
990 | shift_amount = TO_FBITS; | |
991 | utemp = (BIG_UINT_C_TYPE) low; | |
992 | utemp = utemp >> (BIG_WIDTH - shift_amount); | |
993 | high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; | |
994 | low = low << shift_amount; | |
995 | #endif | |
996 | ||
997 | /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ | |
998 | max_high = 0; | |
999 | #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS | |
1000 | max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; | |
1001 | max_low = max_low - 1; | |
1002 | #else | |
1003 | max_low = -1; | |
1004 | #endif | |
1005 | ||
1006 | #if TO_MODE_UNSIGNED == 0 | |
1007 | min_high = -1; | |
1008 | stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1); | |
1009 | stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS); | |
1010 | min_low = stemp; | |
154e4a0a | 1011 | |
154e4a0a CF |
1012 | /* Signed -> Signed. */ |
1013 | if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high | |
1014 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high | |
1015 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
1016 | low = max_low; /* Maximum. */ | |
1017 | else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high | |
1018 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high | |
1019 | && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low)) | |
1020 | low = min_low; /* Minimum. */ | |
1021 | #else | |
1022 | /* Signed -> Unsigned. */ | |
1023 | if (x < 0) | |
1024 | low = 0; /* Minimum. */ | |
1025 | else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high | |
1026 | || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high | |
1027 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
1028 | low = max_low; /* Maximum. */ | |
1029 | #endif | |
1030 | ||
1031 | /* Step 4. Store the result. */ | |
1032 | z = (TO_INT_C_TYPE) low; | |
1033 | #if TO_HAVE_PADDING_BITS | |
1034 | z = z << TO_PADDING_BITS; | |
1035 | z = z >> TO_PADDING_BITS; | |
1036 | #endif | |
1037 | memcpy (&c, &z, TO_FIXED_SIZE); | |
1038 | return c; | |
1039 | } | |
1040 | #endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */ | |
1041 | ||
1042 | /* Unsigned int -> Fixed. */ | |
1043 | #if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4 | |
1044 | TO_FIXED_C_TYPE | |
1045 | FRACTUNS (FROM_INT_C_TYPE a) | |
1046 | { | |
1047 | TO_FIXED_C_TYPE c; | |
1048 | TO_INT_C_TYPE z; | |
1049 | z = (TO_INT_C_TYPE) a; | |
1050 | #if TO_FIXED_WIDTH == TO_FBITS | |
1051 | z = 0; | |
1052 | #else | |
1053 | z = z << TO_FBITS; | |
1054 | #endif | |
1055 | #if TO_HAVE_PADDING_BITS | |
1056 | z = z << TO_PADDING_BITS; | |
1057 | z = z >> TO_PADDING_BITS; | |
1058 | #endif | |
1059 | memcpy (&c, &z, TO_FIXED_SIZE); | |
1060 | return c; | |
1061 | } | |
1062 | #endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */ | |
1063 | ||
1064 | /* Unsigned int -> Fixed with saturation. */ | |
1065 | #if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4 | |
1066 | TO_FIXED_C_TYPE | |
1067 | SATFRACTUNS (FROM_INT_C_TYPE a) | |
1068 | { | |
1069 | TO_FIXED_C_TYPE c; | |
1070 | TO_INT_C_TYPE z; | |
1071 | FROM_INT_C_TYPE x = a; | |
1072 | BIG_UINT_C_TYPE high, low; | |
1073 | BIG_UINT_C_TYPE max_high, max_low; | |
1074 | #if BIG_WIDTH != TO_FBITS | |
1075 | BIG_UINT_C_TYPE utemp; | |
1076 | int shift_amount; | |
1077 | #endif | |
1078 | ||
1079 | /* Step 1. We need to store x to {high, low}. */ | |
1080 | low = (BIG_UINT_C_TYPE) x; | |
1081 | high = 0; | |
1082 | ||
1083 | /* Step 2. We need to left shift {high, low}. */ | |
1084 | #if BIG_WIDTH == TO_FBITS | |
1085 | high = low; | |
1086 | low = 0; | |
1087 | #else | |
1088 | shift_amount = TO_FBITS; | |
1089 | utemp = (BIG_UINT_C_TYPE) low; | |
1090 | utemp = utemp >> (BIG_WIDTH - shift_amount); | |
1091 | high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; | |
1092 | low = low << shift_amount; | |
1093 | #endif | |
1094 | ||
1095 | /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ | |
1096 | max_high = 0; | |
1097 | #if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS | |
1098 | max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; | |
1099 | max_low = max_low - 1; | |
1100 | #else | |
1101 | max_low = -1; | |
1102 | #endif | |
1103 | ||
1104 | #if TO_MODE_UNSIGNED == 1 | |
1105 | /* Unigned -> Unsigned. */ | |
1106 | if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high | |
1107 | || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high | |
1108 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
1109 | low = max_low; /* Maximum. */ | |
1110 | #else | |
1111 | /* Unsigned -> Signed. */ | |
1112 | if ((BIG_SINT_C_TYPE) high < 0) | |
1113 | low = max_low; /* Maximum. */ | |
1114 | else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high | |
1115 | || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high | |
1116 | && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) | |
1117 | low = max_low; /* Maximum. */ | |
1118 | #endif | |
1119 | ||
1120 | /* Step 4. Store the result. */ | |
1121 | z = (TO_INT_C_TYPE) low; | |
1122 | #if TO_HAVE_PADDING_BITS | |
1123 | z = z << TO_PADDING_BITS; | |
1124 | z = z >> TO_PADDING_BITS; | |
1125 | #endif | |
1126 | memcpy (&c, &z, TO_FIXED_SIZE); | |
1127 | return c; | |
1128 | } | |
1129 | #endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */ | |
1130 | ||
1131 | /* Fixed -> Float. */ | |
1132 | #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3 | |
1133 | TO_FLOAT_C_TYPE | |
1134 | FRACT (FROM_FIXED_C_TYPE a) | |
1135 | { | |
1136 | FROM_INT_C_TYPE x; | |
1137 | TO_FLOAT_C_TYPE z; | |
1138 | memcpy (&x, &a, FROM_FIXED_SIZE); | |
1139 | z = (TO_FLOAT_C_TYPE) x; | |
1140 | z = z / BASE; | |
1141 | return z; | |
1142 | } | |
1143 | #endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */ | |
1144 | ||
1145 | /* Float -> Fixed. */ | |
1146 | #if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4 | |
1147 | TO_FIXED_C_TYPE | |
1148 | FRACT (FROM_FLOAT_C_TYPE a) | |
1149 | { | |
1150 | FROM_FLOAT_C_TYPE temp; | |
1151 | TO_INT_C_TYPE z; | |
1152 | TO_FIXED_C_TYPE c; | |
1153 | ||
1154 | temp = a * BASE; | |
1155 | z = (TO_INT_C_TYPE) temp; | |
1156 | #if TO_HAVE_PADDING_BITS | |
1157 | z = z << TO_PADDING_BITS; | |
1158 | z = z >> TO_PADDING_BITS; | |
1159 | #endif | |
1160 | memcpy (&c, &z, TO_FIXED_SIZE); | |
1161 | return c; | |
1162 | } | |
1163 | #endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */ | |
1164 | ||
1165 | /* Float -> Fixed with saturation. */ | |
1166 | #if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4 | |
1167 | TO_FIXED_C_TYPE | |
1168 | SATFRACT (FROM_FLOAT_C_TYPE a) | |
1169 | { | |
1170 | FROM_FLOAT_C_TYPE temp; | |
1171 | TO_INT_C_TYPE z; | |
1172 | TO_FIXED_C_TYPE c; | |
1173 | ||
1174 | if (a >= FIXED_MAX) | |
1175 | { | |
1176 | #if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS | |
1177 | z = (TO_INT_C_TYPE)1 << TO_I_F_BITS; | |
1178 | z = z - 1; | |
1179 | #else | |
1180 | z = -1; | |
1181 | #endif | |
1182 | } | |
1183 | else if (a <= FIXED_MIN) | |
1184 | { | |
1185 | #if TO_MODE_UNSIGNED == 0 | |
1186 | z = (TO_INT_C_TYPE)1 << TO_I_F_BITS; | |
1187 | #else | |
1188 | z = 0; | |
1189 | #endif | |
1190 | } | |
1191 | else | |
1192 | { | |
1193 | temp = a * BASE; | |
1194 | z = (TO_INT_C_TYPE) temp; | |
1195 | } | |
1196 | ||
1197 | #if TO_HAVE_PADDING_BITS | |
1198 | z = z << TO_PADDING_BITS; | |
1199 | z = z >> TO_PADDING_BITS; | |
1200 | #endif | |
1201 | memcpy (&c, &z, TO_FIXED_SIZE); | |
1202 | return c; | |
1203 | } | |
1204 | #endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */ | |
1205 |