diff --git a/app/tests/float.c b/app/tests/float.c new file mode 100644 index 00000000..3402e97d --- /dev/null +++ b/app/tests/float.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013-2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#if ARM_WITH_VFP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void float_vfp_arm_instruction_test(void); +extern void float_vfp_thumb_instruction_test(void); +extern void float_neon_arm_instruction_test(void); +extern void float_neon_thumb_instruction_test(void); + +/* optimize this function to cause it to try to use a lot of registers */ +__OPTIMIZE("O3") +static int float_thread(void *arg) +{ + uint64_t *val = arg; + uint i, j; + + double a[16]; + + /* do a bunch of work with floating point to test context switching */ + a[0] = *val; + for (i = 1; i < countof(a); i++) { + a[i] = a[i-1] * 1.01; + } + + for (i = 0; i < 1000000; i++) { + a[0] += i; + for (j = 1; j < countof(a); j++) { + a[j] += a[j-1] * 0.00001; + } + } + + *val = a[countof(a) - 1]; + + return 1; +} + +static void float_instruction_trap_test(void) +{ + printf("testing fpu trap\n"); + + float_vfp_arm_instruction_test(); + float_neon_arm_instruction_test(); + float_vfp_thumb_instruction_test(); + float_neon_thumb_instruction_test(); +} + +void float_tests(void) +{ + printf("floating point test:\n"); + + /* test lazy fpu load on separate thread */ + printf("creating floating point threads\n"); + thread_t *t[8]; + uint64_t val[countof(t)]; + + for (uint i = 0; i < countof(t); i++) { + val[i] = i; + t[i] = thread_create("float", &float_thread, &val[i], DEFAULT_PRIORITY, DEFAULT_STACK_SIZE); + thread_resume(t[i]); + } + + int res; + for (uint i = 0; i < countof(t); i++) { + thread_join(t[i], &res, INFINITE_TIME); + printf("float thread %u returns %d, val 0x%llx\n", i, res, val[i]); + } + + /* test all the instruction traps */ + float_instruction_trap_test(); + + printf("if we got here, we probably decoded everything properly\n"); +} + +#endif // ARM_WITH_VFP diff --git a/app/tests/float_instructions.S b/app/tests/float_instructions.S new file mode 100644 index 00000000..d36dd4a1 --- /dev/null +++ b/app/tests/float_instructions.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include + +#if ARM_WITH_VFP + +.fpu neon +.syntax unified + +.macro disable + vmrs r0, fpexc + bic r0, #(1<<30) + vmsr fpexc, r0 +.endm + +.macro vfp_instructions + disable + vadd.f32 s0, s0, s0 + + disable + vadd.f64 d0, d0, d0 + + disable + vldr s0, [r0] +.endm + +.macro neon_instructions + disable + vadd.f32 q0, q0, q0 + + disable + vld1.f32 { q0 }, [r0] + + disable + vmov s0, r0 +.endm + +.arm + +FUNCTION(float_vfp_arm_instruction_test) + vfp_instructions + bx lr + +FUNCTION(float_neon_arm_instruction_test) + neon_instructions + bx lr + +.thumb + +FUNCTION(float_vfp_thumb_instruction_test) + vfp_instructions + bx lr + +FUNCTION(float_neon_thumb_instruction_test) + neon_instructions + bx lr + +#endif // ARM_WITH_VFP diff --git a/app/tests/include/app/tests.h b/app/tests/include/app/tests.h index dee80e9f..7950d95f 100644 --- a/app/tests/include/app/tests.h +++ b/app/tests/include/app/tests.h @@ -28,6 +28,7 @@ int thread_tests(void); void printf_tests(void); void clock_tests(void); +void float_tests(void); void benchmarks(void); int fibo(int argc, const cmd_args *argv); diff --git a/app/tests/rules.mk b/app/tests/rules.mk index 19f5bd25..b432e957 100644 --- a/app/tests/rules.mk +++ b/app/tests/rules.mk @@ -11,6 +11,8 @@ MODULE_SRCS += \ $(LOCAL_DIR)/clock_tests.c \ $(LOCAL_DIR)/cache_tests.c \ $(LOCAL_DIR)/benchmarks.c \ + $(LOCAL_DIR)/float.c \ + $(LOCAL_DIR)/float_instructions.S \ $(LOCAL_DIR)/fibo.c MODULE_COMPILEFLAGS += -Wno-format diff --git a/app/tests/tests.c b/app/tests/tests.c index d1179610..47580d97 100644 --- a/app/tests/tests.c +++ b/app/tests/tests.c @@ -32,6 +32,9 @@ STATIC_COMMAND_START STATIC_COMMAND("printf_tests", "test printf", (console_cmd)&printf_tests) STATIC_COMMAND("thread_tests", "test the scheduler", (console_cmd)&thread_tests) STATIC_COMMAND("clock_tests", "test clocks", (console_cmd)&clock_tests) +#if ARM_WITH_VFP +STATIC_COMMAND("float_tests", "floating point test", (console_cmd)&float_tests) +#endif STATIC_COMMAND("bench", "miscellaneous benchmarks", (console_cmd)&benchmarks) STATIC_COMMAND("fibo", "threaded fibonacci", (console_cmd)&fibo) STATIC_COMMAND_END(tests);