1 //===-- aeabi_cdcmpeq.c - Test __aeabi_cdcmpeq ----------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file tests __aeabi_cdcmpeq for the compiler_rt library.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <math.h>
18 #include <pico/double.h>
19 #include "pico/stdlib.h"
20 // Include sys/types.h before inttypes.h to work around issue with
21 // certain versions of GCC and newlib which causes omission of PRIx64
22 #include <sys/types.h>
23 #include "inttypes.h"
24
25 #define test_assert(x) ({ if (!(x)) { printf("Assertion failed: ");puts(#x);printf(" at " __FILE__ ":%d\n", __LINE__); exit(-1); } })
26
27 extern int __aeabi_dcmpun(double a, double b);
28
29 #if __arm__
30
31 #include "call_apsr.h"
32
33 extern __attribute__((pcs("aapcs"))) void __aeabi_cdcmpeq(double a, double b);
34
test__aeabi_cdcmpeq(double a,double b,int expected)35 int test__aeabi_cdcmpeq(double a, double b, int expected) {
36 uint32_t cpsr_value = call_apsr_d(a, b, __aeabi_cdcmpeq);
37 union cpsr cpsr = {.value = cpsr_value};
38 if (expected != cpsr.flags.z) {
39 printf("error in __aeabi_cdcmpeq(%f, %f) => Z = %08x, expected %08x\n",
40 a, b, cpsr.flags.z, expected);
41 return 1;
42 }
43 return 0;
44 }
45
46 #endif
47
test_cdcmpeq()48 int test_cdcmpeq() {
49 #if __arm__
50 if (test__aeabi_cdcmpeq(1.0, 1.0, 1))
51 return 1;
52 if (test__aeabi_cdcmpeq(1234.567, 765.4321, 0))
53 return 1;
54 if (test__aeabi_cdcmpeq(-123.0, -678.0, 0))
55 return 1;
56 if (test__aeabi_cdcmpeq(0.0, -0.0, 1))
57 return 1;
58 if (test__aeabi_cdcmpeq(0.0, 0.0, 1))
59 return 1;
60 if (test__aeabi_cdcmpeq(-0.0, -0.0, 1))
61 return 1;
62 if (test__aeabi_cdcmpeq(-0.0, 0.0, 1))
63 return 1;
64 if (test__aeabi_cdcmpeq(0.0, -1.0, 0))
65 return 1;
66 if (test__aeabi_cdcmpeq(-0.0, -1.0, 0))
67 return 1;
68 if (test__aeabi_cdcmpeq(-1.0, 0.0, 0))
69 return 1;
70 if (test__aeabi_cdcmpeq(-1.0, -0.0, 0))
71 return 1;
72 if (test__aeabi_cdcmpeq(1.0, NAN, 0))
73 return 1;
74 if (test__aeabi_cdcmpeq(NAN, 1.0, 0))
75 return 1;
76 if (test__aeabi_cdcmpeq(NAN, NAN, 0))
77 return 1;
78 if (test__aeabi_cdcmpeq(INFINITY, 1.0, 0))
79 return 1;
80 if (test__aeabi_cdcmpeq(0.0, INFINITY, 0))
81 return 1;
82 if (test__aeabi_cdcmpeq(-INFINITY, 0.0, 0))
83 return 1;
84 if (test__aeabi_cdcmpeq(0.0, -INFINITY, 0))
85 return 1;
86 if (test__aeabi_cdcmpeq(INFINITY, INFINITY, 1))
87 return 1;
88 if (test__aeabi_cdcmpeq(-INFINITY, -INFINITY, 1))
89 return 1;
90 #else
91 printf("skipped\n");
92 #endif
93 return 0;
94 }
95
96 #if __arm__
97
98 extern __attribute__((pcs("aapcs"))) void __aeabi_cdcmple(double a, double b);
99
100 extern __attribute__((pcs("aapcs"))) void __aeabi_cdrcmple(double a, double b);
101
test_dcmple_gt(double a,double b,int expected)102 int test_dcmple_gt(double a, double b, int expected) {
103 if ((a <= b) != expected) {
104 printf("error in dcmple(%f, %f) => %d, expected %d\n",
105 a, b, a <= b, expected);
106 return 1;
107 }
108 if ((a > b) == expected && !isnan(a) && !isnan(b)) {
109 printf("error in dcmpgt(%f, %f) => %d, expected %d\n",
110 a, b, a > b, !expected);
111 return 1;
112 }
113 return 0;
114 }
115
test_dcmplt_ge(double a,double b,int expected)116 int test_dcmplt_ge(double a, double b, int expected) {
117 if ((a < b) != expected) {
118 printf("error in dcmplt(%f, %f) => %d, expected %d\n",
119 a, b, a < b, expected);
120 return 1;
121 }
122 if ((a >= b) == expected && !isnan(a) && !isnan(b)) {
123 printf("error in dcmpge(%f, %f) => %d, expected %d\n",
124 a, b, a >= b, !expected);
125 return 1;
126 }
127 return 0;
128 }
129
test__aeabi_cdcmple(double a,double b,int expected)130 int test__aeabi_cdcmple(double a, double b, int expected) {
131 int32_t cpsr_value = call_apsr_d(a, b, __aeabi_cdcmple);
132 int32_t r_cpsr_value = call_apsr_d(b, a, __aeabi_cdrcmple);
133 int32_t cpsr_value2 = call_apsr_d(b, a, __aeabi_cdcmple);
134 int32_t r_cpsr_value2 = call_apsr_d(a, b, __aeabi_cdrcmple);
135
136 if (cpsr_value != r_cpsr_value) {
137 printf("error: __aeabi_cdcmple(%f, %f) != __aeabi_cdrcmple(%f, %f)\n", a, b, b, a);
138 return 1;
139 }
140
141 int expected_z, expected_c;
142 if (expected == -1) {
143 expected_z = 0;
144 expected_c = 0;
145 } else if (expected == 0) {
146 expected_z = 1;
147 expected_c = 1;
148 } else {
149 // a or b is NaN, or a > b
150 expected_z = 0;
151 expected_c = 1;
152 }
153 #if PICO_DOUBLE_COMPILER
154 // gcc has this backwards it seems - not a good thing, but I guess it doesn't ever call them
155 expected_c ^= 1;
156 #endif
157
158 union cpsr cpsr = {.value = cpsr_value};
159 if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
160 printf("error in __aeabi_cdcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
161 a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
162 return 1;
163 }
164
165 cpsr.value = r_cpsr_value;
166 if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
167 printf("error in __aeabi_cfrcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
168 a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
169 return 1;
170 }
171 return 0;
172 }
173
174 #endif
175
test_cdcmple()176 int test_cdcmple() {
177 #if __arm__
178 if (test__aeabi_cdcmple(1.0, 1.0, 0))
179 return 1;
180 if (test__aeabi_cdcmple(1234.567, 765.4321, 1))
181 return 1;
182 if (test__aeabi_cdcmple(765.4321, 1234.567, -1))
183 return 1;
184 if (test__aeabi_cdcmple(-123.0, -678.0, 1))
185 return 1;
186 if (test__aeabi_cdcmple(-678.0, -123.0, -1))
187 return 1;
188 if (test__aeabi_cdcmple(-123.0, 678.0, -1))
189 return 1;
190 if (test__aeabi_cdcmple(678.0, -123.0, 1))
191 return 1;
192 if (test__aeabi_cdcmple(0.0, -0.0, 0))
193 return 1;
194 if (test__aeabi_cdcmple(1.0, NAN, 1))
195 return 1;
196 if (test__aeabi_cdcmple(NAN, 1.0, 1))
197 return 1;
198 if (test__aeabi_cdcmple(NAN, NAN, 1))
199 return 1;
200 #else
201 printf("skipped\n");
202 #endif
203 return 0;
204 }
205
test_cmple_gt()206 int test_cmple_gt() {
207 if (test_dcmple_gt(1.0, 1.0, 1))
208 return 1;
209 if (test_dcmple_gt(1234.567, 765.4321, 0))
210 return 1;
211 if (test_dcmple_gt(765.4321, 1234.567, 1))
212 return 1;
213 if (test_dcmple_gt(-123.0, -678.0, 0))
214 return 1;
215 if (test_dcmple_gt(-678.0, -123.0, 1))
216 return 1;
217 if (test_dcmple_gt(-123.0, 678.0, 1))
218 return 1;
219 if (test_dcmple_gt(678.0, -123.0, 0))
220 return 1;
221 if (test_dcmple_gt(0.0, -0.0, 1))
222 return 1;
223 if (test_dcmple_gt(-0.0, 0.0, 1))
224 return 1;
225 if (test_dcmple_gt(1.0, NAN, 0))
226 return 1;
227 if (test_dcmple_gt(NAN, 1.0, 0))
228 return 1;
229 if (test_dcmple_gt(NAN, NAN, 0))
230 return 1;
231 return 0;
232 }
233
test_cmplt_ge()234 int test_cmplt_ge() {
235 if (test_dcmplt_ge(1.0, 1.0, 0))
236 return 1;
237 if (test_dcmplt_ge(1234.567, 765.4321, 0))
238 return 1;
239 if (test_dcmplt_ge(765.4321, 1234.567, 1))
240 return 1;
241 if (test_dcmplt_ge(-123.0, -678.0, 0))
242 return 1;
243 if (test_dcmplt_ge(-678.0, -123.0, 1))
244 return 1;
245 if (test_dcmplt_ge(-123.0, 678.0, 1))
246 return 1;
247 if (test_dcmplt_ge(678.0, -123.0, 0))
248 return 1;
249 if (test_dcmplt_ge(0.0, -0.0, 0))
250 return 1;
251 if (test_dcmplt_ge(-0.0, 0.0, 0))
252 return 1;
253 if (test_dcmplt_ge(1.0, NAN, 0))
254 return 1;
255 if (test_dcmplt_ge(NAN, 1.0, 0))
256 return 1;
257 if (test_dcmplt_ge(NAN, NAN, 0))
258 return 1;
259 return 0;
260 }
261
check_dcmpun(double a,double b,bool expected,bool expect_equal)262 int check_dcmpun(double a, double b, bool expected, bool expect_equal) {
263 if (__aeabi_dcmpun(a, b) != expected) {
264 printf("Failed dcmpun(%f, %f)\n", a, b);
265 return 1;
266 }
267 if ((a == b) != expect_equal) {
268 printf("Failed equality check %f %f\n", a, b);
269 __breakpoint();
270 if (b == a) {
271 printf("SAS\n");
272 }
273 return 1;
274 }
275 return 0;
276 }
277
test_dcmpun()278 int test_dcmpun() {
279 if (check_dcmpun(0, 0, false, true) ||
280 check_dcmpun(-INFINITY, INFINITY, false, false) ||
281 check_dcmpun(NAN, 0, true, false) ||
282 check_dcmpun(0, NAN, true, false) ||
283 check_dcmpun(NAN, NAN, true, false) ||
284 check_dcmpun(-NAN, NAN, true, false)) {
285 return 1;
286 }
287 return 0;
288 }
289
290 #define assert_nan(a) test_assert(isnan(a))
291 #define check_nan(a) ({ assert_nan(a); a; })
292
293 double __aeabi_i2d(int32_t);
294 double __aeabi_ui2d(int32_t);
295 double __aeabi_l2d(int64_t);
296 double __aeabi_ul2d(int64_t);
297 int32_t __aeabi_d2iz(double);
298 int64_t __aeabi_d2lz(double);
299 double __aeabi_dmul(double, double);
300 double __aeabi_ddiv(double, double);
301 #if LIB_PICO_DOUBLE_PICO
302 double __real___aeabi_i2d(int);
303 double __real___aeabi_ui2d(int);
304 double __real___aeabi_l2d(int64_t);
305 double __real___aeabi_ul2d(int64_t);
306 double __real___aeabi_dmul(double, double);
307 double __real___aeabi_ddiv(double, double);
308 int32_t __real___aeabi_d2iz(double);
309 int64_t __real___aeabi_d2lz(double);
310 double __real_sqrt(double);
311 double __real_cos(double);
312 double __real_sin(double);
313 double __real_tan(double);
314 double __real_exp(double);
315 double __real_log(double);
316 double __real_atan2(double, double);
317 double __real_pow(double, double);
318 double __real_trunc(double);
319 double __real_ldexp(double, int);
320 double __real_fmod(double, double);
321
322 #define FRAC ((double)(1ull << 50))
323 #define allowed_range(a) (fabs(a) / FRAC)
324 #define assert_close(a, b) test_assert((fabs(a - b) <= allowed_range(a) || ({ printf(" error: %f != %f\n", a, b); 0; })) || (isinf(a) && isinf(b) && (a < 0) == (b < 0)))
325 #define check1(func,p0) ({ typeof(p0) r = func(p0), r2 = __CONCAT(__real_, func)(p0); test_assert(r == r2); r; })
326 #define check2(func,p0,p1) ({ typeof(p0) r = func(p0,p1), r2 = __CONCAT(__real_, func)(p0,p1); test_assert(r == r2); r; })
327 #define check_close1(func,p0) ({ typeof(p0) r = func(p0), r2 = __CONCAT(__real_, func)(p0); if (isnan(p0)) assert_nan(r); else assert_close(r, r2); r; })
328 #define check_close2(func,p0,p1) ({ typeof(p0) r = func(p0,p1), r2 = __CONCAT(__real_, func)(p0,p1); if (isnan(p0) || isnan(p1)) assert_nan(r); else assert_close(r, r2); r; })
329 #else
330 #define check1(func,p0) func(p0)
331 #define check2(func,p0,p1) func(p0,p1)
332 #define check_close1(func,p0) func(p0)
333 #define check_close2(func,p0,p1) func(p0,p1)
334 #endif
335
336 double aa = 0.5;
337 double bb = 1;
338
main()339 int main() {
340 setup_default_uart();
341
342 bool fail = false;
343
344 printf("%d\n", aa < bb);
345 for(double a = -1; a <= 1; a++) {
346 for(double b = -1; b <= 1; b++) {
347 printf("%f < %f ? %d\n", a, b, a < b);
348 }
349 }
350 for(double a = -1; a <=1; a++) {
351 for(double b = -1; b <= 1; b++) {
352 printf("%f > %f ? %d\n", a, b, a > b);
353 }
354 }
355
356 #if 1
357 for (double x = 0; x < 3; x++) {
358 printf("\n ----- %g\n", x);
359 printf("SQRT %10.18g\n", check_close1(sqrt, x));
360 printf("COS %10.18g\n", check_close1(cos, x));
361 printf("SIN %10.18g\n", check_close1(sin, x));
362 printf("TAN %10.18g\n", check_close1(tan, x));
363 printf("ATAN2 %10.18g\n", check_close2(atan2, x, 10.0));
364 printf("ATAN2 %10.18g\n", check_close2(atan2, 10.0, x));
365 printf("EXP %10.18g\n", check_close1(exp, x));
366 printf("LN %10.18g\n", check_close1(log, x));
367 printf("POW %10.18f\n", check_close2(pow, x, x));
368 printf("TRUNC %10.18f\n", check_close1(trunc, x));
369 printf("LDEXP %10.18f\n", check_close2(ldexp, x, x));
370 // todo come pack
371 // printf("FMOD %10.18f\n", check_close2(fmod, x, 3.0f));
372 double s, c;
373 sincos(x, &s, &c);
374 printf("SINCOS %10.18f %10.18f\n", s, c);
375 if (s != sin(x) || c != cos(x)) {
376 printf("SINCOS mismatch\n");
377 fail = true;
378 }
379 }
380
381 #if PICO_DOUBLE_PROPAGATE_NANS
382 {
383 float x = NAN;
384 printf("SQRT %10.18g\n", check_close1(sqrt, x));
385 printf("COS %10.18g\n", check_close1(cos, x));
386 printf("SIN %10.18g\n", check_close1(sin, x));
387 printf("TAN %10.18g\n", check_close1(tan, x));
388 printf("ATAN2 %10.18g\n", check_close2(atan2, x, 10.0));
389 printf("ATAN2 %10.18g\n", check_close2(atan2, 10.0, x));
390 printf("EXP %10.18g\n", check_close1(exp, x));
391 printf("LN %10.18g\n", check_close1(log, x));
392 printf("POW %10.18f\n", check_nan(pow(x, x)));
393 printf("TRUNC %10.18f\n", check_nan(trunc(x)));
394 printf("LDEXP %10.18f\n", check_nan(ldexp(x, x)));
395 printf("FMOD %10.18f\n", check_nan(fmod(x, 3.0f)));
396 double s, c;
397 sincos(x, &s, &c);
398 printf("SINCOS %10.18f %10.18f\n", check_nan(s), check_nan(c));
399
400 for(int j=0;j<2;j++) {
401 for (int i = 1; i < 4; i++) {
402 char buf[4];
403 sprintf(buf, "%d", i);
404 float f0 = -nanf(buf);
405 double d0 = -nan(buf);
406 // hmm nanf/nan seem to ignore payload
407 *(uint64_t *) &d0 |= i;
408 *(uint32_t *) &f0 |= i;
409 if (j) {
410 // try without top bit set
411 *(uint64_t *) &d0 &= ~0x0008000000000000ull;
412 *(uint32_t *) &f0 &= ~0x00400000u;
413 }
414 float f = (float) d0;
415 double d = (double) f0;
416 printf("f2d %f %08"PRIx32" -> %g %016"PRIx64"\n", f0, *(uint32_t *) &f0, d, *(uint64_t *) &d);
417 printf("d2f %f %016"PRIx64" -> %f %08"PRIx32"\n", d0, *(uint64_t *) &d0, f, *(uint32_t *) &f);
418 }
419 }
420 }
421 #endif
422
423 {
424 int32_t y;
425 // for (int32_t x = 0; x>-512; x--) {
426 // printf("i %d->%f\n", (int)x, (float) x);
427 // }
428 for (int32_t x = -1; x; x <<= 1) {
429 printf("i %d->%f\n", x, (double) x);
430 check1(__aeabi_i2d, x);
431 }
432 for (int32_t x = 1; x; x <<= 1) {
433 printf("i %d->%f\n", x, (double) x);
434 check1(__aeabi_i2d, x);
435 y = x << 1;
436 }
437 for (int64_t x = 1; x; x <<= 1) {
438 printf("i %lld->%f\n", x, (double) x);
439 check1(__aeabi_l2d, x);
440 y = x << 1;
441 }
442 for (int64_t x = -1; x; x <<= 1) {
443 printf("i %lld->%f\n", x, (double) x);
444 check1(__aeabi_l2d, x);
445 y = x << 1;
446 }
447 printf("d %d->%f\n", y, (float) y);
448 }
449
450 {
451 uint32_t y;
452 for(uint32_t x = 1; x; x <<= 1) {
453 printf("u %u->%f\n", x, (double)x);
454 check1(__aeabi_ui2d, x);
455 y = x << 1;
456 }
457 printf("u %u->%f\n", y, (double)y);
458 }
459 for(int64_t x = 1; x !=0; x <<= 1u) {
460 printf("%lld->%f\n", x, (double)x);
461 check1(__aeabi_l2d, x);
462 }
463 for(double x = -4294967296.f * 4294967296.f * 2.f; x<=-0.5f; x/=2.f) {
464 printf("d2i64 %f->%lld\n", x, (int64_t)x);
465 if (x <= (double) INT64_MIN) {
466 // seems like there is a bug in the gcc version!
467 test_assert(__aeabi_d2lz(x) == INT64_MIN);
468 } else {
469 check1(__aeabi_d2lz, x);
470 }
471 }
472 for(double x = 4294967296.f * 4294967296.f * 2.f; x>=0.5f; x/=2.f) {
473 printf("d2i64 %f->%lld\n", x, (int64_t)x);
474 if (x >= (double)INT64_MAX) {
475 // seems like there is a bug in the clang and gcc versions!
476 test_assert(__aeabi_d2lz(x) == INT64_MAX);
477 } else {
478 check1(__aeabi_d2lz, x);
479 }
480 }
481 for(double x = -4294967296.f * 4294967296.f; x<=-0.5f; x/=2.f) {
482 printf("d2i32 %f->%d\n", x, (int32_t)x);
483 check1(__aeabi_d2iz, x);
484 }
485 for(double x = 4294967296.f * 4294967296.f; x>=0.5f; x/=2.f) {
486 printf("d2i32 %f->%d\n", x, (int32_t)x);
487 if (x >= (double) INT32_MAX - 1 && x <= (double) INT32_MAX + 1) {
488 // seems like there is a bug in the clang version!
489 test_assert(__aeabi_d2iz(x) == INT32_MAX);
490 } else {
491 check1(__aeabi_d2iz, x);
492 }
493 }
494 for (double x = 1; x < 11.0; x += 2.0) {
495 double f = x * x;
496 double g = 1.0 / x;
497 printf("%g %10.18g %10.18g, %10.18g, %10.18g %10.18g\n", x, f, x + 0.37777777777777777777777777777,
498 x - 0.377777777777777777777777777777, g, 123456789.0 / x);
499 check2(__aeabi_dmul, x, x);
500 check2(__aeabi_ddiv, 1.0, x);
501 }
502
503 if (fail ||
504 test_cdcmpeq() ||
505 test_cdcmple() ||
506 test_dcmpun() ||
507 test_cmple_gt() ||
508 test_cmplt_ge()) {
509 printf("FAILED\n");
510 return 1;
511 } else {
512 printf("PASSED\n");
513 return 0;
514 }
515 #endif
516 }
517