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