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