configure.ac (fixed-point): Add ARM support.
[platform/upstream/gcc.git] / gcc / testsuite / gcc.target / arm / fixed-point-exec.c
1 /* { 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 }