osdep: protect qemu/osdep.h with extern "C"
[qemu/ar7.git] / tests / tcg / hexagon / fpstuff.c
blobe4f1a0eeb487ccd33d587bb97c18d1313215ecc5
1 /*
2 * Copyright(c) 2020-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 * This test checks various FP operations performed on Hexagon
22 #include <stdio.h>
24 const int FPINVF_BIT = 1; /* Invalid */
25 const int FPINVF = 1 << FPINVF_BIT;
26 const int FPDBZF_BIT = 2; /* Divide by zero */
27 const int FPDBZF = 1 << FPDBZF_BIT;
28 const int FPOVFF_BIT = 3; /* Overflow */
29 const int FPOVFF = 1 << FPOVFF_BIT;
30 const int FPUNFF_BIT = 4; /* Underflow */
31 const int FPUNFF = 1 << FPUNFF_BIT;
32 const int FPINPF_BIT = 5; /* Inexact */
33 const int FPINPF = 1 << FPINPF_BIT;
35 const int SF_ZERO = 0x00000000;
36 const int SF_NaN = 0x7fc00000;
37 const int SF_NaN_special = 0x7f800001;
38 const int SF_ANY = 0x3f800000;
39 const int SF_HEX_NAN = 0xffffffff;
41 const long long DF_NaN = 0x7ff8000000000000ULL;
42 const long long DF_ANY = 0x3f80000000000000ULL;
43 const long long DF_HEX_NAN = 0xffffffffffffffffULL;
45 int err;
47 #define CLEAR_FPSTATUS \
48 "r2 = usr\n\t" \
49 "r2 = clrbit(r2, #1)\n\t" \
50 "r2 = clrbit(r2, #2)\n\t" \
51 "r2 = clrbit(r2, #3)\n\t" \
52 "r2 = clrbit(r2, #4)\n\t" \
53 "r2 = clrbit(r2, #5)\n\t" \
54 "usr = r2\n\t"
56 static void check_fpstatus_bit(int usr, int expect, int flag, const char *n)
58 int bit = 1 << flag;
59 if ((usr & bit) != (expect & bit)) {
60 printf("ERROR %s: usr = %d, expect = %d\n", n,
61 (usr >> flag) & 1, (expect >> flag) & 1);
62 err++;
66 static void check_fpstatus(int usr, int expect)
68 check_fpstatus_bit(usr, expect, FPINVF_BIT, "Invalid");
69 check_fpstatus_bit(usr, expect, FPDBZF_BIT, "Div by zero");
70 check_fpstatus_bit(usr, expect, FPOVFF_BIT, "Overflow");
71 check_fpstatus_bit(usr, expect, FPUNFF_BIT, "Underflow");
72 check_fpstatus_bit(usr, expect, FPINPF_BIT, "Inexact");
75 static void check32(int val, int expect)
77 if (val != expect) {
78 printf("ERROR: 0x%x != 0x%x\n", val, expect);
79 err++;
82 static void check64(unsigned long long val, unsigned long long expect)
84 if (val != expect) {
85 printf("ERROR: 0x%llx != 0x%llx\n", val, expect);
86 err++;
90 static void check_compare_exception(void)
92 int cmp;
93 int usr;
95 /* Check that FP compares are quiet (don't raise any execptions) */
96 asm (CLEAR_FPSTATUS
97 "p0 = sfcmp.eq(%2, %3)\n\t"
98 "%0 = p0\n\t"
99 "%1 = usr\n\t"
100 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
101 : "r2", "p0", "usr");
102 check32(cmp, 0);
103 check_fpstatus(usr, 0);
105 asm (CLEAR_FPSTATUS
106 "p0 = sfcmp.gt(%2, %3)\n\t"
107 "%0 = p0\n\t"
108 "%1 = usr\n\t"
109 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
110 : "r2", "p0", "usr");
111 check32(cmp, 0);
112 check_fpstatus(usr, 0);
114 asm (CLEAR_FPSTATUS
115 "p0 = sfcmp.ge(%2, %3)\n\t"
116 "%0 = p0\n\t"
117 "%1 = usr\n\t"
118 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
119 : "r2", "p0", "usr");
120 check32(cmp, 0);
121 check_fpstatus(usr, 0);
123 asm (CLEAR_FPSTATUS
124 "p0 = dfcmp.eq(%2, %3)\n\t"
125 "%0 = p0\n\t"
126 "%1 = usr\n\t"
127 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
128 : "r2", "p0", "usr");
129 check32(cmp, 0);
130 check_fpstatus(usr, 0);
132 asm (CLEAR_FPSTATUS
133 "p0 = dfcmp.gt(%2, %3)\n\t"
134 "%0 = p0\n\t"
135 "%1 = usr\n\t"
136 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
137 : "r2", "p0", "usr");
138 check32(cmp, 0);
139 check_fpstatus(usr, 0);
141 asm (CLEAR_FPSTATUS
142 "p0 = dfcmp.ge(%2, %3)\n\t"
143 "%0 = p0\n\t"
144 "%1 = usr\n\t"
145 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
146 : "r2", "p0", "usr");
147 check32(cmp, 0);
148 check_fpstatus(usr, 0);
151 static void check_sfminmax(void)
153 int minmax;
154 int usr;
157 * Execute sfmin/sfmax instructions with one operand as NaN
158 * Check that
159 * Result is the other operand
160 * Invalid bit in USR is not set
162 asm (CLEAR_FPSTATUS
163 "%0 = sfmin(%2, %3)\n\t"
164 "%1 = usr\n\t"
165 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
166 : "r2", "usr");
167 check64(minmax, SF_ANY);
168 check_fpstatus(usr, 0);
170 asm (CLEAR_FPSTATUS
171 "%0 = sfmax(%2, %3)\n\t"
172 "%1 = usr\n\t"
173 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
174 : "r2", "usr");
175 check64(minmax, SF_ANY);
176 check_fpstatus(usr, 0);
179 * Execute sfmin/sfmax instructions with both operands NaN
180 * Check that
181 * Result is SF_HEX_NAN
182 * Invalid bit in USR is set
184 asm (CLEAR_FPSTATUS
185 "%0 = sfmin(%2, %3)\n\t"
186 "%1 = usr\n\t"
187 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
188 : "r2", "usr");
189 check64(minmax, SF_HEX_NAN);
190 check_fpstatus(usr, 0);
192 asm (CLEAR_FPSTATUS
193 "%0 = sfmax(%2, %3)\n\t"
194 "%1 = usr\n\t"
195 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
196 : "r2", "usr");
197 check64(minmax, SF_HEX_NAN);
198 check_fpstatus(usr, 0);
201 static void check_dfminmax(void)
203 unsigned long long minmax;
204 int usr;
207 * Execute dfmin/dfmax instructions with one operand as NaN
208 * Check that
209 * Result is the other operand
210 * Invalid bit in USR is set
212 asm (CLEAR_FPSTATUS
213 "%0 = dfmin(%2, %3)\n\t"
214 "%1 = usr\n\t"
215 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
216 : "r2", "usr");
217 check64(minmax, DF_ANY);
218 check_fpstatus(usr, FPINVF);
220 asm (CLEAR_FPSTATUS
221 "%0 = dfmax(%2, %3)\n\t"
222 "%1 = usr\n\t"
223 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
224 : "r2", "usr");
225 check64(minmax, DF_ANY);
226 check_fpstatus(usr, FPINVF);
229 * Execute dfmin/dfmax instructions with both operands NaN
230 * Check that
231 * Result is DF_HEX_NAN
232 * Invalid bit in USR is set
234 asm (CLEAR_FPSTATUS
235 "%0 = dfmin(%2, %3)\n\t"
236 "%1 = usr\n\t"
237 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
238 : "r2", "usr");
239 check64(minmax, DF_HEX_NAN);
240 check_fpstatus(usr, FPINVF);
242 asm (CLEAR_FPSTATUS
243 "%0 = dfmax(%2, %3)\n\t"
244 "%1 = usr\n\t"
245 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
246 : "r2", "usr");
247 check64(minmax, DF_HEX_NAN);
248 check_fpstatus(usr, FPINVF);
251 static void check_canonical_NaN(void)
253 int sf_result;
254 unsigned long long df_result;
255 int usr;
257 /* Check that each FP instruction properly returns SF_HEX_NAN/DF_HEX_NAN */
258 asm(CLEAR_FPSTATUS
259 "%0 = sfadd(%2, %3)\n\t"
260 "%1 = usr\n\t"
261 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
262 : "r2", "usr");
263 check32(sf_result, SF_HEX_NAN);
264 check_fpstatus(usr, 0);
266 asm(CLEAR_FPSTATUS
267 "%0 = sfsub(%2, %3)\n\t"
268 "%1 = usr\n\t"
269 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
270 : "r2", "usr");
271 check32(sf_result, SF_HEX_NAN);
272 check_fpstatus(usr, 0);
274 asm(CLEAR_FPSTATUS
275 "%0 = sfmpy(%2, %3)\n\t"
276 "%1 = usr\n\t"
277 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
278 : "r2", "usr");
279 check32(sf_result, SF_HEX_NAN);
280 check_fpstatus(usr, 0);
282 sf_result = SF_ZERO;
283 asm(CLEAR_FPSTATUS
284 "%0 += sfmpy(%2, %3)\n\t"
285 "%1 = usr\n\t"
286 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
287 : "r2", "usr");
288 check32(sf_result, SF_HEX_NAN);
289 check_fpstatus(usr, 0);
291 sf_result = SF_ZERO;
292 asm(CLEAR_FPSTATUS
293 "p0 = !cmp.eq(r0, r0)\n\t"
294 "%0 += sfmpy(%2, %3, p0):scale\n\t"
295 "%1 = usr\n\t"
296 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
297 : "r2", "usr", "p0");
298 check32(sf_result, SF_HEX_NAN);
299 check_fpstatus(usr, 0);
301 sf_result = SF_ZERO;
302 asm(CLEAR_FPSTATUS
303 "%0 -= sfmpy(%2, %3)\n\t"
304 "%1 = usr\n\t"
305 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
306 : "r2", "usr");
307 check32(sf_result, SF_HEX_NAN);
308 check_fpstatus(usr, 0);
310 sf_result = SF_ZERO;
311 asm(CLEAR_FPSTATUS
312 "%0 += sfmpy(%2, %3):lib\n\t"
313 "%1 = usr\n\t"
314 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
315 : "r2", "usr");
316 check32(sf_result, SF_HEX_NAN);
317 check_fpstatus(usr, 0);
319 sf_result = SF_ZERO;
320 asm(CLEAR_FPSTATUS
321 "%0 -= sfmpy(%2, %3):lib\n\t"
322 "%1 = usr\n\t"
323 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
324 : "r2", "usr");
325 check32(sf_result, SF_HEX_NAN);
326 check_fpstatus(usr, 0);
328 asm(CLEAR_FPSTATUS
329 "%0 = convert_df2sf(%2)\n\t"
330 "%1 = usr\n\t"
331 : "=r"(sf_result), "=r"(usr) : "r"(DF_NaN)
332 : "r2", "usr");
333 check32(sf_result, SF_HEX_NAN);
334 check_fpstatus(usr, 0);
336 asm(CLEAR_FPSTATUS
337 "%0 = dfadd(%2, %3)\n\t"
338 "%1 = usr\n\t"
339 : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
340 : "r2", "usr");
341 check64(df_result, DF_HEX_NAN);
342 check_fpstatus(usr, 0);
344 asm(CLEAR_FPSTATUS
345 "%0 = dfsub(%2, %3)\n\t"
346 "%1 = usr\n\t"
347 : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
348 : "r2", "usr");
349 check64(df_result, DF_HEX_NAN);
350 check_fpstatus(usr, 0);
352 asm(CLEAR_FPSTATUS
353 "%0 = convert_sf2df(%2)\n\t"
354 "%1 = usr\n\t"
355 : "=r"(df_result), "=r"(usr) : "r"(SF_NaN)
356 : "r2", "usr");
357 check64(df_result, DF_HEX_NAN);
358 check_fpstatus(usr, 0);
361 int main()
363 check_compare_exception();
364 check_sfminmax();
365 check_dfminmax();
366 check_canonical_NaN();
368 puts(err ? "FAIL" : "PASS");
369 return err ? 1 : 0;