annotate libgcc/fixed-bit.c @ 131:84e7813d76e9

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