blob: 5d3d8c61814af79d15fbec14c75951b11c2505dd [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2013-2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#if ARM_WITH_VFP || ARCH_ARM64 || X86_WITH_FPU
24
25#include <stdio.h>
26#include <rand.h>
27#include <err.h>
28#include <lib/console.h>
29#include <app/tests.h>
30#include <kernel/thread.h>
31#include <kernel/mutex.h>
32#include <kernel/semaphore.h>
33#include <kernel/event.h>
34#include <platform.h>
35
36extern void float_vfp_arm_instruction_test(void);
37extern void float_vfp_thumb_instruction_test(void);
38extern void float_neon_arm_instruction_test(void);
39extern void float_neon_thumb_instruction_test(void);
40
41/* optimize this function to cause it to try to use a lot of registers */
42__OPTIMIZE("O3")
43static int float_thread(void *arg)
44{
45 double *val = arg;
46 uint i, j;
47
48 double a[16];
49
50 /* do a bunch of work with floating point to test context switching */
51 a[0] = *val;
52 for (i = 1; i < countof(a); i++) {
53 a[i] = a[i-1] * 1.01;
54 }
55
56 for (i = 0; i < 1000000; i++) {
57 a[0] += i;
58 for (j = 1; j < countof(a); j++) {
59 a[j] += a[j-1] * 0.00001;
60 }
61 }
62
63 *val = a[countof(a) - 1];
64
65 return 1;
66}
67
68#if ARCH_ARM
69static void arm_float_instruction_trap_test(void)
70{
71 printf("testing fpu trap\n");
72
73#if !ARM_ONLY_THUMB
74 float_vfp_arm_instruction_test();
75 float_neon_arm_instruction_test();
76#endif
77 float_vfp_thumb_instruction_test();
78 float_neon_thumb_instruction_test();
79
80 printf("if we got here, we probably decoded everything properly\n");
81}
82#endif
83
84static void float_tests(void)
85{
86 printf("floating point test:\n");
87
88 /* test lazy fpu load on separate thread */
89 thread_t *t[8];
90 double val[countof(t)];
91
92 printf("creating %u floating point threads\n", countof(t));
93 for (uint i = 0; i < countof(t); i++) {
94 val[i] = i;
95 t[i] = thread_create("float", &float_thread, &val[i], LOW_PRIORITY, DEFAULT_STACK_SIZE);
96 thread_resume(t[i]);
97 }
98
99 int res;
100 for (uint i = 0; i < countof(t); i++) {
101 thread_join(t[i], &res, INFINITE_TIME);
102 printf("float thread %u returns %d, val %f\n", i, res, val[i]);
103 }
104 printf("the above values should be close\n");
105
106#if ARCH_ARM
107 /* test all the instruction traps */
108 arm_float_instruction_trap_test();
109#endif
110}
111
112STATIC_COMMAND_START
113STATIC_COMMAND("float_tests", "floating point test", (console_cmd)&float_tests)
114STATIC_COMMAND_END(float_tests);
115
116#endif // ARM_WITH_VFP || ARCH_ARM64