diff options
Diffstat (limited to 'lib/libc/arm/aeabi')
-rw-r--r-- | lib/libc/arm/aeabi/Makefile.inc | 30 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/Symbol.map | 31 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_asm_double.S | 119 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_asm_float.S | 110 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_atexit.c | 37 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_double.c | 100 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_float.c | 100 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_int_div.S | 51 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_unwind_cpp.c | 60 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_unwind_exidx.c | 101 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_vfp.h | 131 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_vfp_double.S | 202 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_vfp_float.S | 189 |
13 files changed, 1261 insertions, 0 deletions
diff --git a/lib/libc/arm/aeabi/Makefile.inc b/lib/libc/arm/aeabi/Makefile.inc new file mode 100644 index 000000000000..ef9ff746060f --- /dev/null +++ b/lib/libc/arm/aeabi/Makefile.inc @@ -0,0 +1,30 @@ +.PATH: ${LIBC_SRCTOP}/arm/aeabi + +SRCS+= aeabi_atexit.c \ + aeabi_unwind_cpp.c \ + aeabi_unwind_exidx.c +.if defined(CPUTYPE) && ${CPUTYPE:M*soft*} != "" +SRCS+= aeabi_asm_double.S \ + aeabi_asm_float.S \ + aeabi_double.c \ + aeabi_float.c +.endif +.if !defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "" +SRCS+= aeabi_vfp_double.S \ + aeabi_vfp_float.S +.endif + +# Add the aeabi_mem* functions. While they live in compiler-rt they call into +# libc. This causes issues when other parts of libc call these functions. +# We work around this by including these functions in libc but mark them as +# hidden so users of libc will not pick up these versions. +.PATH: ${SRCTOP}/contrib/llvm-project/compiler-rt/lib/builtins/arm + +SRCS+= aeabi_memcmp.S \ + aeabi_memcpy.S \ + aeabi_memmove.S \ + aeabi_memset.S + +SRCS+= aeabi_int_div.S + +SYM_MAPS+=${LIBC_SRCTOP}/arm/aeabi/Symbol.map diff --git a/lib/libc/arm/aeabi/Symbol.map b/lib/libc/arm/aeabi/Symbol.map new file mode 100644 index 000000000000..515794004ba7 --- /dev/null +++ b/lib/libc/arm/aeabi/Symbol.map @@ -0,0 +1,31 @@ +/* + * This only needs to contain AEABI symbols that are not listed in + * symbol maps from other parts of libc (i.e., not found in + * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...). + */ +FBSDprivate_1.0 { + __aeabi_atexit; + + __aeabi_memclr; + __aeabi_memclr4; + __aeabi_memclr8; + __aeabi_memcmp; + __aeabi_memcmp4; + __aeabi_memcmp8; + __aeabi_memcpy; + __aeabi_memcpy4; + __aeabi_memcpy8; + __aeabi_memmove; + __aeabi_memmove4; + __aeabi_memmove8; + __aeabi_memset; + __aeabi_memset4; + __aeabi_memset8; + + /* + * A workaround for DEFINE_AEABI_FUNCTION_ALIAS() bug. + * - see aeabi_int_div.S + */ + __aeabi_idiv; + __aeabi_uidiv; +}; diff --git a/lib/libc/arm/aeabi/aeabi_asm_double.S b/lib/libc/arm/aeabi/aeabi_asm_double.S new file mode 100644 index 000000000000..767c62a7edf8 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_asm_double.S @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +#define PCR_Z (1 << 30) +#define PCR_C (1 << 29) + +/* + * These functions return the result in the CPSR register. + * + * For __aeabi_cdcmple: + * Z C + * LT 0 0 + * EQ 1 1 + * else 0 1 + * + * __aeabi_cdrcmple is the same as __aeabi_cdcmple, however the arguments + * have been swapped. + */ +ENTRY(__aeabi_cdcmple) + push {r4, r5, r6, r7, ip, lr} + + /* Backup the input registers */ + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + /* Is it less than? */ + bl __aeabi_dcmplt + cmp r0, #1 + bne 1f + /* Yes, clear Z and C */ + mov ip, #(0) + b 99f + +1: + /* Restore the input regsters for the next function call */ + mov r0, r4 + mov r1, r5 + mov r2, r6 + mov r3, r7 + /* Is it equal? */ + bl __aeabi_dcmpeq + cmp r0, #1 + bne 2f + /* Yes, set Z and C */ + mov ip, #(PCR_Z | PCR_C) + b 99f + +2: + /* Not less than or equal, set C and clear Z */ + mov ip, #(PCR_C) + +99: + msr cpsr_c, ip + pop {r4, r5, r6, r7, ip, pc} +END(__aeabi_cdcmple) + +ENTRY(__aeabi_cdrcmple) + /* Swap the first half of the arguments */ + mov ip, r0 + mov r0, r2 + mov r2, ip + + /* And the second half */ + mov ip, r1 + mov r1, r3 + mov r3, ip + + b __aeabi_cdcmple +END(__aeabi_cdrcmple) + +/* + * This is just like __aeabi_cdcmple except it will not throw an exception + * in the presence of a quiet NaN. If either argument is a signalling NaN we + * will still signal. + */ +ENTRY(__aeabi_cdcmpeq) + /* Check if we can call __aeabi_cfcmple safely */ + push {r0, r1, r2, r3, r4, lr} + bl __aeabi_cdcmpeq_helper + cmp r0, #1 + pop {r0, r1, r2, r3, r4, lr} + beq 1f + + bl __aeabi_cdcmple + RET + +1: + mov ip, #(PCR_C) + msr cpsr_c, ip + RET +END(__aeabi_cdcmpeq) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/aeabi/aeabi_asm_float.S b/lib/libc/arm/aeabi/aeabi_asm_float.S new file mode 100644 index 000000000000..f9dff9e0aec6 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_asm_float.S @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +#define PCR_Z (1 << 30) +#define PCR_C (1 << 29) + +/* + * These functions return the result in the CPSR register. + * + * For __aeabi_cfcmple: + * Z C + * LT 0 0 + * EQ 1 1 + * else 0 1 + * + * __aeabi_cfrcmple is the same as __aeabi_cfcmple, however the arguments + * have been swapped. + */ +ENTRY(__aeabi_cfcmple) + push {r4, r5, ip, lr} + + /* Backup the input registers */ + mov r4, r0 + mov r5, r1 + /* Is it less than? */ + bl __aeabi_fcmplt + cmp r0, #1 + bne 1f + /* Yes, clear Z and C */ + mov ip, #(0) + b 99f + +1: + /* Restore the input regsters for the next function call */ + mov r0, r4 + mov r1, r5 + /* Is it equal? */ + bl __aeabi_fcmpeq + cmp r0, #1 + bne 2f + /* Yes, set Z and C */ + mov ip, #(PCR_Z | PCR_C) + b 99f + +2: + /* Not less than or equal, set C and clear Z */ + mov ip, #(PCR_C) + +99: + msr cpsr_c, ip + pop {r4, r5, ip, pc} +END(__aeabi_cfcmple) + +ENTRY(__aeabi_cfrcmple) + /* Swap the arguments */ + mov ip, r0 + mov r0, r1 + mov r1, ip + + b __aeabi_cfcmple +END(__aeabi_cfrcmple) + +/* + * This is just like __aeabi_cfcmple except it will not throw an exception + * in the presence of a quiet NaN. If either argument is a signalling NaN we + * will still signal. + */ +ENTRY(__aeabi_cfcmpeq) + /* Check if we can call __aeabi_cfcmple safely */ + push {r0, r1, r2, lr} + bl __aeabi_cfcmpeq_helper + cmp r0, #1 + pop {r0, r1, r2, lr} + beq 1f + + bl __aeabi_cfcmple + RET + +1: + mov ip, #(PCR_C) + msr cpsr_c, ip + RET +END(__aeabi_cfcmpeq) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/aeabi/aeabi_atexit.c b/lib/libc/arm/aeabi/aeabi_atexit.c new file mode 100644 index 000000000000..d688edf9c4e9 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_atexit.c @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2012 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +int __cxa_atexit(void (*)(void *), void *, void *); + +int +__aeabi_atexit(void *object, void (*func)(void*), void *dso) +{ + return __cxa_atexit(func, object, dso); +} + diff --git a/lib/libc/arm/aeabi/aeabi_double.c b/lib/libc/arm/aeabi/aeabi_double.c new file mode 100644 index 000000000000..61f64678e795 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_double.c @@ -0,0 +1,100 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2012 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "softfloat-for-gcc.h" +#include "milieu.h" +#include "softfloat.h" + +#include "aeabi_vfp.h" + +extern int _libc_arm_fpu_present; + +flag __unorddf2(float64, float64); + +/* These are written in asm and are only called from this file */ +int __aeabi_dcmpeq_vfp(float64, float64); +int __aeabi_dcmplt_vfp(float64, float64); +int __aeabi_dcmple_vfp(float64, float64); +int __aeabi_dcmpgt_vfp(float64, float64); +int __aeabi_dcmpge_vfp(float64, float64); +int __aeabi_dcmpun_vfp(float64, float64); +int __aeabi_d2iz_vfp(float64); +float32 __aeabi_d2f_vfp(float64); +float64 __aeabi_i2d_vfp(int); +float64 __aeabi_dadd_vfp(float64, float64); +float64 __aeabi_ddiv_vfp(float64, float64); +float64 __aeabi_dmul_vfp(float64, float64); +float64 __aeabi_dsub_vfp(float64, float64); + +/* + * Depending on the target these will: + * On armv7 with a vfp call the above function, or + * Call the softfloat function in the 3rd argument. + */ +int AEABI_FUNC2(dcmpeq, float64, float64_eq) +int AEABI_FUNC2(dcmplt, float64, float64_lt) +int AEABI_FUNC2(dcmple, float64, float64_le) +int AEABI_FUNC2_REV(dcmpge, float64, float64_le) +int AEABI_FUNC2_REV(dcmpgt, float64, float64_lt) +int AEABI_FUNC2(dcmpun, float64, __unorddf2) + +int AEABI_FUNC(d2iz, float64, float64_to_int32_round_to_zero) +float32 AEABI_FUNC(d2f, float64, float64_to_float32) +float64 AEABI_FUNC(i2d, int, int32_to_float64) + +float64 AEABI_FUNC2(dadd, float64, float64_add) +float64 AEABI_FUNC2(ddiv, float64, float64_div) +float64 AEABI_FUNC2(dmul, float64, float64_mul) +float64 AEABI_FUNC2(dsub, float64, float64_sub) + +int +__aeabi_cdcmpeq_helper(float64 a, float64 b) +{ + int quiet = 0; + + /* Check if a is a NaN */ + if ((a << 1) > 0xffe0000000000000ull) { + /* If it's a signalling NaN we will always signal */ + if ((a & 0x0008000000000000ull) == 0) + return (0); + + quiet = 1; + } + + /* Check if b is a NaN */ + if ((b << 1) > 0xffe0000000000000ull) { + /* If it's a signalling NaN we will always signal */ + if ((b & 0x0008000000000000ull) == 0) + return (0); + + quiet = 1; + } + + return (quiet); +} diff --git a/lib/libc/arm/aeabi/aeabi_float.c b/lib/libc/arm/aeabi/aeabi_float.c new file mode 100644 index 000000000000..0e465754ecf0 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_float.c @@ -0,0 +1,100 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2012 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "softfloat-for-gcc.h" +#include "milieu.h" +#include "softfloat.h" + +#include "aeabi_vfp.h" + +extern int _libc_arm_fpu_present; + +flag __unordsf2(float32, float32); + +/* These are written in asm and are only called from this file */ +int __aeabi_fcmpeq_vfp(float32, float32); +int __aeabi_fcmplt_vfp(float32, float32); +int __aeabi_fcmple_vfp(float32, float32); +int __aeabi_fcmpgt_vfp(float32, float32); +int __aeabi_fcmpge_vfp(float32, float32); +int __aeabi_fcmpun_vfp(float32, float32); +int __aeabi_f2iz_vfp(float32); +float64 __aeabi_f2d_vfp(float32); +float32 __aeabi_i2f_vfp(int); +float32 __aeabi_fadd_vfp(float32, float32); +float32 __aeabi_fdiv_vfp(float32, float32); +float32 __aeabi_fmul_vfp(float32, float32); +float32 __aeabi_fsub_vfp(float32, float32); + +/* + * Depending on the target these will: + * On armv7 with a vfp call the above function, or + * Call the softfloat function in the 3rd argument. + */ +int AEABI_FUNC2(fcmpeq, float32, float32_eq) +int AEABI_FUNC2(fcmplt, float32, float32_lt) +int AEABI_FUNC2(fcmple, float32, float32_le) +int AEABI_FUNC2_REV(fcmpge, float32, float32_le) +int AEABI_FUNC2_REV(fcmpgt, float32, float32_lt) +int AEABI_FUNC2(fcmpun, float32, __unordsf2) + +int AEABI_FUNC(f2iz, float32, float32_to_int32_round_to_zero) +float64 AEABI_FUNC(f2d, float32, float32_to_float64) +float32 AEABI_FUNC(i2f, int, int32_to_float32) + +float32 AEABI_FUNC2(fadd, float32, float32_add) +float32 AEABI_FUNC2(fdiv, float32, float32_div) +float32 AEABI_FUNC2(fmul, float32, float32_mul) +float32 AEABI_FUNC2(fsub, float32, float32_sub) + +int +__aeabi_cfcmpeq_helper(float32 a, float32 b) +{ + int quiet = 0; + + /* Check if a is a NaN */ + if ((a << 1) > 0xff000000u) { + /* If it's a signalling NaN we will always signal */ + if ((a & 0x00400000u) == 0) + return (0); + + quiet = 1; + } + + /* Check if b is a NaN */ + if ((b << 1) > 0xff000000u) { + /* If it's a signalling NaN we will always signal */ + if ((b & 0x00400000u) == 0) + return (0); + + quiet = 1; + } + + return (quiet); +} diff --git a/lib/libc/arm/aeabi/aeabi_int_div.S b/lib/libc/arm/aeabi/aeabi_int_div.S new file mode 100644 index 000000000000..bb002c2716f7 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_int_div.S @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 Michal Meloun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +/* + * Due to bug in libcompiler_rt, all symbols declared by + * DEFINE_AEABI_FUNCTION_ALIAS() are not hidden. All these but + * __aeabi_uidiv_compat and/or __aeabi_idiv_compat are explicitly + * exported from libc and don't causes problems. + * + * As workaround, export these from libc as compatible symbols, + * in global namespace + */ + +ENTRY(__aeabi_uidiv_compat) + .hidden __aeabi_uidiv_compat + .symver __aeabi_uidiv_compat, __aeabi_uidiv@ + b __udivsi3 +END(__aeabi_uidiv_compat) + +ENTRY(__aeabi_idiv_compat) + .hidden __aeabi_idiv_compat + .symver __aeabi_idiv_compat, __aeabi_idiv@ + b __divsi3 +END(__aeabi_idiv_compat) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/aeabi/aeabi_unwind_cpp.c b/lib/libc/arm/aeabi/aeabi_unwind_cpp.c new file mode 100644 index 000000000000..efcace2c0675 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_unwind_cpp.c @@ -0,0 +1,60 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2011 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Provide an implementation of __aeabi_unwind_cpp_pr{0,1,2}. These are + * required by libc but are implemented in libgcc_eh.a which we don't link + * against. The libgcc_eh.a version will be called so we call abort to + * check this. + */ + +#include <stdlib.h> + +void __aeabi_unwind_cpp_pr0(void) __hidden; +void __aeabi_unwind_cpp_pr1(void) __hidden; +void __aeabi_unwind_cpp_pr2(void) __hidden; + +void +__aeabi_unwind_cpp_pr0(void) +{ + abort(); +} + +void +__aeabi_unwind_cpp_pr1(void) +{ + abort(); +} + +void +__aeabi_unwind_cpp_pr2(void) +{ + abort(); +} + diff --git a/lib/libc/arm/aeabi/aeabi_unwind_exidx.c b/lib/libc/arm/aeabi/aeabi_unwind_exidx.c new file mode 100644 index 000000000000..cf61922d4304 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_unwind_exidx.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2014 Ian Lepore <ian@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <machine/elf.h> +#include <link.h> +#include <stddef.h> + +/* + * ARM EABI unwind helper. + * + * This finds the exidx section address and size associated with a given code + * address. There are separate implementations for static and dynamic code. + * + * GCC expects this function to exist as __gnu_Unwind_Find_exidx(), clang and + * BSD tools expect it to be dl_unwind_find_exidx(). Both have the same API, so + * we set up an alias for GCC. + */ +__strong_reference(dl_unwind_find_exidx, __gnu_Unwind_Find_exidx); + +/* + * Each entry in the exidx section is a pair of 32-bit words. We don't + * interpret the contents of the entries here; this typedef is just a local + * convenience for using sizeof() and doing pointer math. + */ +typedef struct exidx_entry { + uint32_t data[2]; +} exidx_entry; + +#ifdef __PIC__ + +/* + * Unwind helper for dynamically linked code. + * + * This finds the shared object that contains the given address, and returns the + * address of the exidx section in that shared object along with the number of + * entries in that section, or NULL if it wasn't found. + */ +void * +dl_unwind_find_exidx(const void *pc, int *pcount) +{ + const Elf_Phdr *hdr; + struct dl_phdr_info info; + int i; + + if (_rtld_addr_phdr(pc, &info)) { + hdr = info.dlpi_phdr; + for (i = 0; i < info.dlpi_phnum; i++, hdr++) { + if (hdr->p_type == PT_ARM_EXIDX) { + *pcount = hdr->p_memsz / sizeof(exidx_entry); + return ((void *)(info.dlpi_addr + hdr->p_vaddr)); + } + } + } + return (NULL); +} + +#else /* !__PIC__ */ + +/* + * Unwind helper for statically linked code. + * + * In a statically linked program, the linker populates a pair of symbols with + * the addresses of the start and end of the exidx table, so returning the + * address and count of elements is pretty straighforward. + */ +void * +dl_unwind_find_exidx(const void *pc, int *pcount) +{ + extern struct exidx_entry __exidx_start; + extern struct exidx_entry __exidx_end; + + *pcount = (int)(&__exidx_end - &__exidx_start); + return (&__exidx_start); +} + +#endif /* __PIC__ */ + diff --git a/lib/libc/arm/aeabi/aeabi_vfp.h b/lib/libc/arm/aeabi/aeabi_vfp.h new file mode 100644 index 000000000000..4f3bb2ef969b --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_vfp.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2013 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef AEABI_VFP_H +#define AEABI_VFP_H + +#include <machine/acle-compat.h> + +/* + * ASM helper macros. These allow the functions to be changed depending on + * the endian-ness we are building for. + */ + +/* Allow the name of the function to be changed depending on the ABI */ +#ifndef __ARM_PCS_VFP +#define AEABI_ENTRY(x) ENTRY(__aeabi_ ## x ## _vfp) +#define AEABI_END(x) END(__aeabi_ ## x ## _vfp) +#else +#define AEABI_ENTRY(x) \ + ENTRY(__aeabi_ ## x) \ + .symver __aeabi_##x, __aeabi_##x##@FBSDprivate_1.0; +#define AEABI_END(x) END(__aeabi_ ## x) +#endif + +/* + * These should be used when a function either takes, or returns a floating + * point falue. They will load the data from an ARM to a VFP register(s), + * or from a VFP to an ARM register + */ +#ifdef __ARM_BIG_ENDIAN +#define LOAD_DREG(vreg, reg0, reg1) vmov vreg, reg1, reg0 +#define UNLOAD_DREG(reg0, reg1, vreg) vmov reg1, reg0, vreg +#else +#define LOAD_DREG(vreg, reg0, reg1) vmov vreg, reg0, reg1 +#define UNLOAD_DREG(reg0, reg1, vreg) vmov reg0, reg1, vreg +#endif + +#define LOAD_SREGS(vreg0, vreg1, reg0, reg1) vmov vreg0, vreg1, reg0, reg1 +#define LOAD_SREG(vreg, reg) vmov vreg, reg +#define UNLOAD_SREG(reg, vreg) vmov reg, vreg + +/* + * C Helper macros + */ + +#if !defined(SOFTFLOAT_FOR_GCC) +/* + * Generate a function that will either call into the VFP implementation, + * or the soft float version for a given __aeabi_* helper. The function + * will take a single argument of the type given by in_type. + */ +#define AEABI_FUNC(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a) \ +{ \ + if (_libc_arm_fpu_present) \ + return __aeabi_ ## name ## _vfp(a); \ + else \ + return soft_func (a); \ +} + +/* As above, but takes two arguments of the same type */ +#define AEABI_FUNC2(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a, in_type b) \ +{ \ + if (_libc_arm_fpu_present) \ + return __aeabi_ ## name ## _vfp(a, b); \ + else \ + return soft_func (a, b); \ +} + +/* As above, but with the soft float arguments reversed */ +#define AEABI_FUNC2_REV(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a, in_type b) \ +{ \ + if (_libc_arm_fpu_present) \ + return __aeabi_ ## name ## _vfp(a, b); \ + else \ + return soft_func (b, a); \ +} +#else +/* + * Helper macros for when we are only able to use the softfloat + * version of these functions, i.e. on arm before armv6. + */ +#define AEABI_FUNC(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a) \ +{ \ + return soft_func (a); \ +} + +/* As above, but takes two arguments of the same type */ +#define AEABI_FUNC2(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a, in_type b) \ +{ \ + return soft_func (a, b); \ +} + +/* As above, but with the soft float arguments reversed */ +#define AEABI_FUNC2_REV(name, in_type, soft_func) \ +__aeabi_ ## name(in_type a, in_type b) \ +{ \ + return soft_func (b, a); \ +} +#endif + +#endif + diff --git a/lib/libc/arm/aeabi/aeabi_vfp_double.S b/lib/libc/arm/aeabi/aeabi_vfp_double.S new file mode 100644 index 000000000000..89287d922f78 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_vfp_double.S @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2013 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +#include "aeabi_vfp.h" + +.fpu vfp +.syntax unified + +/* void __aeabi_cdcmpeq(double, double) */ +AEABI_ENTRY(cdcmpeq) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cdcmpeq) + +/* void __aeabi_cdcmple(double, double) */ +AEABI_ENTRY(cdcmple) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmpe.f64 d0, d1 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cdcmple) + +/* void __aeabi_cdrcmple(double, double) */ +AEABI_ENTRY(cdrcmple) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmpe.f64 d1, d0 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cdrcmple) + +/* int __aeabi_dcmpeq(double, double) */ +AEABI_ENTRY(dcmpeq) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite ne + movne r0, #0 + moveq r0, #1 + RET +AEABI_END(dcmpeq) + +/* int __aeabi_dcmplt(double, double) */ +AEABI_ENTRY(dcmplt) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite cs + movcs r0, #0 + movcc r0, #1 + RET +AEABI_END(dcmplt) + +/* int __aeabi_dcmple(double, double) */ +AEABI_ENTRY(dcmple) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite hi + movhi r0, #0 + movls r0, #1 + RET +AEABI_END(dcmple) + +/* int __aeabi_dcmpge(double, double) */ +AEABI_ENTRY(dcmpge) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite lt + movlt r0, #0 + movge r0, #1 + RET +AEABI_END(dcmpge) + +/* int __aeabi_dcmpgt(double, double) */ +AEABI_ENTRY(dcmpgt) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite le + movle r0, #0 + movgt r0, #1 + RET +AEABI_END(dcmpgt) + +/* int __aeabi_dcmpun(double, double) */ +AEABI_ENTRY(dcmpun) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vcmp.f64 d0, d1 + vmrs APSR_nzcv, fpscr + ite vc + movvc r0, #0 + movvs r0, #1 + RET +AEABI_END(dcmpun) + +/* int __aeabi_d2iz(double) */ +AEABI_ENTRY(d2iz) + LOAD_DREG(d0, r0, r1) +#if 0 + /* + * This should be the correct instruction, but binutils incorrectly + * encodes it as the version that used FPSCR to determine the rounding. + * When binutils is fixed we can use this again. + */ + vcvt.s32.f64 s0, d0 +#else + ftosizd s0, d0 +#endif + vmov r0, s0 + RET +AEABI_END(d2iz) + +/* float __aeabi_d2f(double) */ +AEABI_ENTRY(d2f) + LOAD_DREG(d0, r0, r1) + vcvt.f32.f64 s0, d0 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(d2f) + +/* double __aeabi_i2d(int) */ +AEABI_ENTRY(i2d) + vmov s0, r0 + vcvt.f64.s32 d0, s0 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(i2d) + +/* double __aeabi_dadd(double, double) */ +AEABI_ENTRY(dadd) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vadd.f64 d0, d0, d1 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(dadd) + +/* double __aeabi_ddiv(double, double) */ +AEABI_ENTRY(ddiv) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vdiv.f64 d0, d0, d1 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(ddiv) + +/* double __aeabi_dmul(double, double) */ +AEABI_ENTRY(dmul) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vmul.f64 d0, d0, d1 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(dmul) + +/* double __aeabi_dsub(double, double) */ +AEABI_ENTRY(dsub) + LOAD_DREG(d0, r0, r1) + LOAD_DREG(d1, r2, r3) + vsub.f64 d0, d0, d1 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(dsub) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/aeabi/aeabi_vfp_float.S b/lib/libc/arm/aeabi/aeabi_vfp_float.S new file mode 100644 index 000000000000..389e58935f89 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_vfp_float.S @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2013 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +#include "aeabi_vfp.h" + +.fpu vfp +.syntax unified + +/* void __aeabi_cfcmpeq(float, float) */ +AEABI_ENTRY(cfcmpeq) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cfcmpeq) + +/* void __aeabi_cfcmple(float, float) */ +AEABI_ENTRY(cfcmple) + LOAD_SREGS(s0, s1, r0, r1) + vcmpe.f32 s0, s1 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cfcmple) + +/* void __aeabi_cfrcmple(float, float) */ +AEABI_ENTRY(cfrcmple) + LOAD_SREGS(s0, s1, r0, r1) + vcmpe.f32 s1, s0 + vmrs APSR_nzcv, fpscr + RET +AEABI_END(cfrcmple) + +/* int __aeabi_fcmpeq(float, float) */ +AEABI_ENTRY(fcmpeq) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite ne + movne r0, #0 + moveq r0, #1 + RET +AEABI_END(fcmpeq) + +/* int __aeabi_fcmplt(float, float) */ +AEABI_ENTRY(fcmplt) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite cs + movcs r0, #0 + movcc r0, #1 + RET +AEABI_END(fcmplt) + +/* int __aeabi_fcmple(float, float) */ +AEABI_ENTRY(fcmple) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite hi + movhi r0, #0 + movls r0, #1 + RET +AEABI_END(fcmple) + +/* int __aeabi_fcmpge(float, float) */ +AEABI_ENTRY(fcmpge) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite lt + movlt r0, #0 + movge r0, #1 + RET +AEABI_END(fcmpge) + +/* int __aeabi_fcmpgt(float, float) */ +AEABI_ENTRY(fcmpgt) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite le + movle r0, #0 + movgt r0, #1 + RET +AEABI_END(fcmpgt) + +/* int __aeabi_fcmpun(float, float) */ +AEABI_ENTRY(fcmpun) + LOAD_SREGS(s0, s1, r0, r1) + vcmp.f32 s0, s1 + vmrs APSR_nzcv, fpscr + ite vc + movvc r0, #0 + movvs r0, #1 + RET +AEABI_END(fcmpun) + +/* int __aeabi_f2iz(float) */ +AEABI_ENTRY(f2iz) + LOAD_SREG(s0, r0) +#if 0 + /* + * This should be the correct instruction, but binutils incorrectly + * encodes it as the version that used FPSCR to determine the rounding. + * When binutils is fixed we can use this again. + */ + vcvt.s32.f32 s0, s0 +#else + ftosizs s0, s0 +#endif + vmov r0, s0 + RET +AEABI_END(f2iz) + +/* double __aeabi_f2d(float) */ +AEABI_ENTRY(f2d) + LOAD_SREG(s0, r0) + vcvt.f64.f32 d0, s0 + UNLOAD_DREG(r0, r1, d0) + RET +AEABI_END(f2d) + +/* float __aeabi_i2f(int) */ +AEABI_ENTRY(i2f) + vmov s0, r0 + vcvt.f32.s32 s0, s0 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(i2f) + +/* float __aeabi_fadd(float, float) */ +AEABI_ENTRY(fadd) + LOAD_SREGS(s0, s1, r0, r1) + vadd.f32 s0, s0, s1 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(fadd) + +/* float __aeabi_fmul(float, float) */ +AEABI_ENTRY(fdiv) + LOAD_SREGS(s0, s1, r0, r1) + vdiv.f32 s0, s0, s1 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(fdiv) + +/* float __aeabi_fmul(float, float) */ +AEABI_ENTRY(fmul) + LOAD_SREGS(s0, s1, r0, r1) + vmul.f32 s0, s0, s1 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(fmul) + +/* float __aeabi_fsub(float, float) */ +AEABI_ENTRY(fsub) + LOAD_SREGS(s0, s1, r0, r1) + vsub.f32 s0, s0, s1 + UNLOAD_SREG(r0, s0) + RET +AEABI_END(fsub) + + .section .note.GNU-stack,"",%progbits |