1 |
691 |
jeremybenn |
/* { dg-do run { target { fixed_point } } } */
|
2 |
|
|
/* { dg-options "-std=gnu99" } */
|
3 |
|
|
|
4 |
|
|
/* Check basic arithmetic ops for ARM fixed-point/saturating operation support.
|
5 |
|
|
Not target-independent since we make various assumptions about precision and
|
6 |
|
|
magnitudes of various types. */
|
7 |
|
|
|
8 |
|
|
#include <stdlib.h>
|
9 |
|
|
#include <stdio.h>
|
10 |
|
|
#include <math.h>
|
11 |
|
|
#include <stdfix.h>
|
12 |
|
|
|
13 |
|
|
#define TEST(TYPE, OP, NAME, SUFFIX) \
|
14 |
|
|
TYPE NAME##SUFFIX (TYPE A, TYPE B) \
|
15 |
|
|
{ \
|
16 |
|
|
return A OP B; \
|
17 |
|
|
}
|
18 |
|
|
|
19 |
|
|
#define VARIANTS(TYPE, OP, NAME) \
|
20 |
|
|
TEST (short TYPE, OP, NAME, _short); \
|
21 |
|
|
TEST (TYPE, OP, NAME, _regular); \
|
22 |
|
|
TEST (long TYPE, OP, NAME, _long); \
|
23 |
|
|
TEST (_Sat short TYPE, OP, NAME, _sat_short); \
|
24 |
|
|
TEST (_Sat TYPE, OP, NAME, _sat_regular); \
|
25 |
|
|
TEST (_Sat long TYPE, OP, NAME, _sat_long); \
|
26 |
|
|
TEST (unsigned short TYPE, OP, NAME, _uns_short); \
|
27 |
|
|
TEST (unsigned TYPE, OP, NAME, _uns_regular); \
|
28 |
|
|
TEST (unsigned long TYPE, OP, NAME, _uns_long); \
|
29 |
|
|
TEST (unsigned _Sat short TYPE, OP, NAME, _uns_sat_short); \
|
30 |
|
|
TEST (unsigned _Sat TYPE, OP, NAME, _uns_sat_regular); \
|
31 |
|
|
TEST (unsigned _Sat long TYPE, OP, NAME, _uns_sat_long)
|
32 |
|
|
|
33 |
|
|
VARIANTS (_Fract, +, plus_fract);
|
34 |
|
|
VARIANTS (_Accum, +, plus_accum);
|
35 |
|
|
VARIANTS (_Fract, -, minus_fract);
|
36 |
|
|
VARIANTS (_Accum, -, minus_accum);
|
37 |
|
|
VARIANTS (_Fract, *, mult_fract);
|
38 |
|
|
VARIANTS (_Accum, *, mult_accum);
|
39 |
|
|
VARIANTS (_Accum, /, div_accum);
|
40 |
|
|
|
41 |
|
|
/* Inputs for signed add, multiply fractional tests. */
|
42 |
|
|
short _Fract sf_a = 0.9hr;
|
43 |
|
|
short _Fract sf_b = -0.8hr;
|
44 |
|
|
_Fract f_a = 0.9r;
|
45 |
|
|
_Fract f_b = -0.8r;
|
46 |
|
|
long _Fract lf_a = 0.9lr;
|
47 |
|
|
long _Fract lf_b = -0.8lr;
|
48 |
|
|
|
49 |
|
|
/* Inputs for signed subtract fractional tests. */
|
50 |
|
|
short _Fract sf_c = 0.7hr;
|
51 |
|
|
short _Fract sf_d = 0.9hr;
|
52 |
|
|
_Fract f_c = 0.7r;
|
53 |
|
|
_Fract f_d = 0.9r;
|
54 |
|
|
long _Fract lf_c = 0.7lr;
|
55 |
|
|
long _Fract lf_d = 0.9lr;
|
56 |
|
|
|
57 |
|
|
/* Inputs for unsigned add, subtract, multiply fractional tests. */
|
58 |
|
|
unsigned short _Fract usf_a = 0.4uhr;
|
59 |
|
|
unsigned short _Fract usf_b = 0.3uhr;
|
60 |
|
|
unsigned _Fract uf_a = 0.4ur;
|
61 |
|
|
unsigned _Fract uf_b = 0.3ur;
|
62 |
|
|
unsigned long _Fract ulf_a = 0.4ulr;
|
63 |
|
|
unsigned long _Fract ulf_b = 0.3ulr;
|
64 |
|
|
|
65 |
|
|
/* Inputs for saturating signed add tests. */
|
66 |
|
|
short _Sat _Fract sf_e = 0.8hr;
|
67 |
|
|
short _Sat _Fract sf_f = 0.8hr;
|
68 |
|
|
_Sat _Fract f_e = 0.8r;
|
69 |
|
|
_Sat _Fract f_f = 0.8r;
|
70 |
|
|
long _Sat _Fract lf_e = 0.8r;
|
71 |
|
|
long _Sat _Fract lf_f = 0.8r;
|
72 |
|
|
|
73 |
|
|
short _Sat _Fract sf_g = -0.8hr;
|
74 |
|
|
short _Sat _Fract sf_h = -0.8hr;
|
75 |
|
|
_Sat _Fract f_g = -0.8r;
|
76 |
|
|
_Sat _Fract f_h = -0.8r;
|
77 |
|
|
long _Sat _Fract lf_g = -0.8r;
|
78 |
|
|
long _Sat _Fract lf_h = -0.8r;
|
79 |
|
|
|
80 |
|
|
/* Inputs for saturating unsigned subtract tests. */
|
81 |
|
|
unsigned short _Sat _Fract usf_c = 0.3uhr;
|
82 |
|
|
unsigned short _Sat _Fract usf_d = 0.4uhr;
|
83 |
|
|
unsigned _Sat _Fract uf_c = 0.3ur;
|
84 |
|
|
unsigned _Sat _Fract uf_d = 0.4ur;
|
85 |
|
|
unsigned long _Sat _Fract ulf_c = 0.3ulr;
|
86 |
|
|
unsigned long _Sat _Fract ulf_d = 0.4ulr;
|
87 |
|
|
|
88 |
|
|
/* Inputs for signed accumulator tests. */
|
89 |
|
|
|
90 |
|
|
short _Accum sa_a = 1.25hk;
|
91 |
|
|
short _Accum sa_b = -1.5hk;
|
92 |
|
|
_Accum a_a = 100.25k;
|
93 |
|
|
_Accum a_b = -100.5k;
|
94 |
|
|
long _Accum la_a = 1000.25lk;
|
95 |
|
|
long _Accum la_b = -1000.5lk;
|
96 |
|
|
|
97 |
|
|
/* Inputs for unsigned accumulator tests. */
|
98 |
|
|
|
99 |
|
|
unsigned short _Accum usa_a = 2.5uhk;
|
100 |
|
|
unsigned short _Accum usa_b = 1.75uhk;
|
101 |
|
|
unsigned _Accum ua_a = 255.5uk;
|
102 |
|
|
unsigned _Accum ua_b = 170.25uk;
|
103 |
|
|
unsigned long _Accum ula_a = 1550.5ulk;
|
104 |
|
|
unsigned long _Accum ula_b = 999.5ulk;
|
105 |
|
|
|
106 |
|
|
/* Inputs for signed saturating accumulator tests. */
|
107 |
|
|
|
108 |
|
|
short _Sat _Accum sa_c = 240.0hk;
|
109 |
|
|
short _Sat _Accum sa_d = 250.0hk;
|
110 |
|
|
short _Sat _Accum sa_e = -240.0hk;
|
111 |
|
|
short _Sat _Accum sa_f = -250.0hk;
|
112 |
|
|
short _Sat _Accum sa_g = 0.5hk;
|
113 |
|
|
|
114 |
|
|
_Sat _Accum a_c = 65000.0k;
|
115 |
|
|
_Sat _Accum a_d = 20000.0k;
|
116 |
|
|
_Sat _Accum a_e = -65000.0k;
|
117 |
|
|
_Sat _Accum a_f = -20000.0k;
|
118 |
|
|
_Sat _Accum a_g = 0.5k;
|
119 |
|
|
|
120 |
|
|
long _Sat _Accum la_c = 3472883712.0lk;
|
121 |
|
|
long _Sat _Accum la_d = 3456106496.0lk;
|
122 |
|
|
long _Sat _Accum la_e = -3472883712.0lk;
|
123 |
|
|
long _Sat _Accum la_f = -3456106496.0lk;
|
124 |
|
|
long _Sat _Accum la_g = 0.5lk;
|
125 |
|
|
|
126 |
|
|
/* Inputs for unsigned saturating accumulator tests. */
|
127 |
|
|
|
128 |
|
|
unsigned short _Sat _Accum usa_c = 250.0uhk;
|
129 |
|
|
unsigned short _Sat _Accum usa_d = 240.0uhk;
|
130 |
|
|
unsigned short _Sat _Accum usa_e = 0.5uhk;
|
131 |
|
|
|
132 |
|
|
unsigned _Sat _Accum ua_c = 65000.0uk;
|
133 |
|
|
unsigned _Sat _Accum ua_d = 20000.0uk;
|
134 |
|
|
unsigned _Sat _Accum ua_e = 0.5uk;
|
135 |
|
|
|
136 |
|
|
unsigned long _Sat _Accum ula_c = 3472883712.0ulk;
|
137 |
|
|
unsigned long _Sat _Accum ula_d = 3456106496.0ulk;
|
138 |
|
|
unsigned long _Sat _Accum ula_e = 0.5ulk;
|
139 |
|
|
|
140 |
|
|
#define CHECK(FN, EXP) do { \
|
141 |
|
|
if (fabs ((float) (FN) - (EXP)) > 0.05) \
|
142 |
|
|
{ \
|
143 |
|
|
fprintf (stderr, "result for " #FN " (as float): %f\n", (double) (FN));\
|
144 |
|
|
abort (); \
|
145 |
|
|
} \
|
146 |
|
|
} while (0)
|
147 |
|
|
|
148 |
|
|
#define CHECK_EXACT(FN, EXP) do { \
|
149 |
|
|
if ((FN) != (EXP)) \
|
150 |
|
|
{ \
|
151 |
|
|
fprintf (stderr, "result for " #FN " (as float): %f, should be %f\n", \
|
152 |
|
|
(double) (FN), (double) (EXP)); \
|
153 |
|
|
abort (); \
|
154 |
|
|
} \
|
155 |
|
|
} while (0)
|
156 |
|
|
|
157 |
|
|
int
|
158 |
|
|
main (int argc, char *argv[])
|
159 |
|
|
{
|
160 |
|
|
/* Fract/fract operations, non-saturating. */
|
161 |
|
|
|
162 |
|
|
CHECK (plus_fract_short (sf_a, sf_b), 0.1);
|
163 |
|
|
CHECK (plus_fract_regular (f_a, f_b), 0.1);
|
164 |
|
|
CHECK (plus_fract_long (lf_a, lf_b), 0.1);
|
165 |
|
|
|
166 |
|
|
CHECK (plus_fract_uns_short (usf_a, usf_b), 0.7);
|
167 |
|
|
CHECK (plus_fract_uns_regular (uf_a, uf_b), 0.7);
|
168 |
|
|
CHECK (plus_fract_uns_long (ulf_a, ulf_b), 0.7);
|
169 |
|
|
|
170 |
|
|
CHECK (minus_fract_short (sf_c, sf_d), -0.2);
|
171 |
|
|
CHECK (minus_fract_regular (f_c, f_d), -0.2);
|
172 |
|
|
CHECK (minus_fract_long (lf_c, lf_d), -0.2);
|
173 |
|
|
|
174 |
|
|
CHECK (minus_fract_uns_short (usf_a, usf_b), 0.1);
|
175 |
|
|
CHECK (minus_fract_uns_regular (uf_a, uf_b), 0.1);
|
176 |
|
|
CHECK (minus_fract_uns_long (ulf_a, ulf_b), 0.1);
|
177 |
|
|
|
178 |
|
|
CHECK (mult_fract_short (sf_a, sf_b), -0.72);
|
179 |
|
|
CHECK (mult_fract_regular (f_a, f_b), -0.72);
|
180 |
|
|
CHECK (mult_fract_long (lf_a, lf_b), -0.72);
|
181 |
|
|
|
182 |
|
|
CHECK (mult_fract_uns_short (usf_a, usf_b), 0.12);
|
183 |
|
|
CHECK (mult_fract_uns_regular (uf_a, uf_b), 0.12);
|
184 |
|
|
CHECK (mult_fract_uns_long (ulf_a, ulf_b), 0.12);
|
185 |
|
|
|
186 |
|
|
/* Fract/fract operations, saturating. */
|
187 |
|
|
|
188 |
|
|
CHECK (plus_fract_sat_short (sf_e, sf_f), 1.0);
|
189 |
|
|
CHECK (plus_fract_sat_regular (f_e, f_f), 1.0);
|
190 |
|
|
CHECK (plus_fract_sat_long (lf_e, lf_f), 1.0);
|
191 |
|
|
|
192 |
|
|
CHECK (plus_fract_sat_short (sf_g, sf_h), -1.0);
|
193 |
|
|
CHECK (plus_fract_sat_regular (f_g, f_h), -1.0);
|
194 |
|
|
CHECK (plus_fract_sat_long (lf_g, lf_h), -1.0);
|
195 |
|
|
|
196 |
|
|
CHECK (plus_fract_uns_sat_short (sf_e, sf_f), 1.0);
|
197 |
|
|
CHECK (plus_fract_uns_sat_regular (f_e, f_f), 1.0);
|
198 |
|
|
CHECK (plus_fract_uns_sat_long (lf_e, lf_f), 1.0);
|
199 |
|
|
|
200 |
|
|
CHECK (plus_fract_sat_short (sf_a, sf_b), 0.1);
|
201 |
|
|
CHECK (plus_fract_sat_regular (f_a, f_b), 0.1);
|
202 |
|
|
CHECK (plus_fract_sat_long (lf_a, lf_b), 0.1);
|
203 |
|
|
|
204 |
|
|
CHECK (plus_fract_uns_sat_short (usf_a, usf_b), 0.7);
|
205 |
|
|
CHECK (plus_fract_uns_sat_regular (uf_a, uf_b), 0.7);
|
206 |
|
|
CHECK (plus_fract_uns_sat_long (ulf_a, ulf_b), 0.7);
|
207 |
|
|
|
208 |
|
|
CHECK (minus_fract_uns_sat_short (usf_c, usf_d), 0.0);
|
209 |
|
|
CHECK (minus_fract_uns_sat_regular (uf_c, uf_d), 0.0);
|
210 |
|
|
CHECK (minus_fract_uns_sat_short (ulf_c, ulf_d), 0.0);
|
211 |
|
|
|
212 |
|
|
CHECK (minus_fract_sat_short (sf_c, sf_d), -0.2);
|
213 |
|
|
CHECK (minus_fract_sat_regular (f_c, f_d), -0.2);
|
214 |
|
|
CHECK (minus_fract_sat_long (lf_c, lf_d), -0.2);
|
215 |
|
|
|
216 |
|
|
/* Accum/accum operations, non-saturating. */
|
217 |
|
|
|
218 |
|
|
CHECK (plus_accum_short (sa_a, sa_b), -0.25);
|
219 |
|
|
CHECK (plus_accum_regular (a_a, a_b), -0.25);
|
220 |
|
|
CHECK (plus_accum_long (la_a, la_b), -0.25);
|
221 |
|
|
|
222 |
|
|
CHECK (minus_accum_short (sa_a, sa_b), 2.75);
|
223 |
|
|
CHECK (minus_accum_regular (a_a, a_b), 200.75);
|
224 |
|
|
CHECK (minus_accum_long (la_a, la_b), 2000.75);
|
225 |
|
|
|
226 |
|
|
CHECK (mult_accum_short (sa_a, sa_b), -1.875);
|
227 |
|
|
CHECK (mult_accum_regular (a_a, a_b), -10075.125);
|
228 |
|
|
CHECK (mult_accum_long (la_a, la_b), -1000750.125);
|
229 |
|
|
|
230 |
|
|
CHECK (div_accum_short (sa_a, sa_b), -1.25/1.5);
|
231 |
|
|
CHECK (div_accum_regular (a_a, a_b), -100.25/100.5);
|
232 |
|
|
CHECK (div_accum_long (la_a, la_b), -1000.25/1000.5);
|
233 |
|
|
|
234 |
|
|
/* Unsigned accum/accum operations, non-saturating. */
|
235 |
|
|
|
236 |
|
|
CHECK (plus_accum_uns_short (usa_a, usa_b), 4.25);
|
237 |
|
|
CHECK (plus_accum_uns_regular (ua_a, ua_b), 425.75);
|
238 |
|
|
CHECK (plus_accum_uns_long (ula_a, ula_b), 2550.0);
|
239 |
|
|
|
240 |
|
|
CHECK (minus_accum_uns_short (usa_a, usa_b), 0.75);
|
241 |
|
|
CHECK (minus_accum_uns_regular (ua_a, ua_b), 85.25);
|
242 |
|
|
CHECK (minus_accum_uns_long (ula_a, ula_b), 551.0);
|
243 |
|
|
|
244 |
|
|
CHECK (mult_accum_uns_short (usa_a, usa_b), 4.375);
|
245 |
|
|
CHECK (mult_accum_uns_regular (ua_a, ua_b), 43498.875);
|
246 |
|
|
CHECK (mult_accum_uns_long (ula_a, ula_b), 1549724.75);
|
247 |
|
|
|
248 |
|
|
CHECK (div_accum_uns_short (usa_a, usa_b), 2.5/1.75);
|
249 |
|
|
CHECK (div_accum_uns_regular (ua_a, ua_b), 255.5/170.25);
|
250 |
|
|
CHECK (div_accum_uns_long (ula_a, ula_b), 1550.5/999.5);
|
251 |
|
|
|
252 |
|
|
/* Signed accum/accum operations, saturating. */
|
253 |
|
|
|
254 |
|
|
CHECK_EXACT (plus_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
|
255 |
|
|
CHECK_EXACT (plus_accum_sat_short (sa_e, sa_f), SACCUM_MIN);
|
256 |
|
|
CHECK_EXACT (plus_accum_sat_regular (a_c, a_d), ACCUM_MAX);
|
257 |
|
|
CHECK_EXACT (plus_accum_sat_regular (a_e, a_f), ACCUM_MIN);
|
258 |
|
|
CHECK_EXACT (plus_accum_sat_long (la_c, la_d), LACCUM_MAX);
|
259 |
|
|
CHECK_EXACT (plus_accum_sat_long (la_e, la_f), LACCUM_MIN);
|
260 |
|
|
|
261 |
|
|
CHECK_EXACT (minus_accum_sat_short (sa_e, sa_d), SACCUM_MIN);
|
262 |
|
|
CHECK_EXACT (minus_accum_sat_short (sa_c, sa_f), SACCUM_MAX);
|
263 |
|
|
CHECK_EXACT (minus_accum_sat_regular (a_e, a_d), ACCUM_MIN);
|
264 |
|
|
CHECK_EXACT (minus_accum_sat_regular (a_c, a_f), ACCUM_MAX);
|
265 |
|
|
CHECK_EXACT (minus_accum_sat_long (la_e, la_d), LACCUM_MIN);
|
266 |
|
|
CHECK_EXACT (minus_accum_sat_long (la_c, la_f), LACCUM_MAX);
|
267 |
|
|
|
268 |
|
|
CHECK_EXACT (mult_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
|
269 |
|
|
CHECK_EXACT (mult_accum_sat_short (sa_c, sa_e), SACCUM_MIN);
|
270 |
|
|
CHECK_EXACT (mult_accum_sat_regular (a_c, a_d), ACCUM_MAX);
|
271 |
|
|
CHECK_EXACT (mult_accum_sat_regular (a_c, a_e), ACCUM_MIN);
|
272 |
|
|
CHECK_EXACT (mult_accum_sat_long (la_c, la_d), LACCUM_MAX);
|
273 |
|
|
CHECK_EXACT (mult_accum_sat_long (la_c, la_e), LACCUM_MIN);
|
274 |
|
|
|
275 |
|
|
CHECK_EXACT (div_accum_sat_short (sa_d, sa_g), SACCUM_MAX);
|
276 |
|
|
CHECK_EXACT (div_accum_sat_short (sa_e, sa_g), SACCUM_MIN);
|
277 |
|
|
CHECK_EXACT (div_accum_sat_regular (a_c, a_g), ACCUM_MAX);
|
278 |
|
|
CHECK_EXACT (div_accum_sat_regular (a_e, a_g), ACCUM_MIN);
|
279 |
|
|
CHECK_EXACT (div_accum_sat_long (la_d, la_g), LACCUM_MAX);
|
280 |
|
|
CHECK_EXACT (div_accum_sat_long (la_e, la_g), LACCUM_MIN);
|
281 |
|
|
|
282 |
|
|
/* Unsigned accum/accum operations, saturating. */
|
283 |
|
|
|
284 |
|
|
CHECK_EXACT (plus_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
|
285 |
|
|
CHECK_EXACT (plus_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
|
286 |
|
|
CHECK_EXACT (plus_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
|
287 |
|
|
|
288 |
|
|
CHECK_EXACT (minus_accum_uns_sat_short (usa_d, usa_c), 0uhk);
|
289 |
|
|
CHECK_EXACT (minus_accum_uns_sat_regular (ua_d, ua_c), 0uk);
|
290 |
|
|
CHECK_EXACT (minus_accum_uns_sat_long (ula_d, ula_c), 0ulk);
|
291 |
|
|
|
292 |
|
|
CHECK_EXACT (mult_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
|
293 |
|
|
CHECK_EXACT (mult_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
|
294 |
|
|
CHECK_EXACT (mult_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
|
295 |
|
|
|
296 |
|
|
CHECK_EXACT (div_accum_uns_sat_short (usa_c, usa_e), USACCUM_MAX);
|
297 |
|
|
CHECK_EXACT (div_accum_uns_sat_regular (ua_c, ua_e), UACCUM_MAX);
|
298 |
|
|
CHECK_EXACT (div_accum_uns_sat_long (ula_c, ula_e), ULACCUM_MAX);
|
299 |
|
|
|
300 |
|
|
return 0;
|
301 |
|
|
}
|