diff options
author | andrew <andrew@FreeBSD.org> | 2014-10-22 13:50:38 +0000 |
---|---|---|
committer | andrew <andrew@FreeBSD.org> | 2014-10-22 13:50:38 +0000 |
commit | 58b9da93f03431d6fcab3cd00dd912dbb9b13e20 (patch) | |
tree | 6bd00b106ee88f162bf7d09fc60afd27155dd062 /lib/libc/arm | |
parent | eb3582e16fc01e7c3e10471374605153ea6bd1f2 (diff) | |
download | FreeBSD-src-58b9da93f03431d6fcab3cd00dd912dbb9b13e20.zip FreeBSD-src-58b9da93f03431d6fcab3cd00dd912dbb9b13e20.tar.gz |
MFC r273088:
Add support for the __aeabi_c*cmp* functions. These are similar to the
existing functions with the exception they use the condition flags to
store the result.
Diffstat (limited to 'lib/libc/arm')
-rw-r--r-- | lib/libc/arm/aeabi/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/Symbol.map | 8 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_asm_double.S | 117 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_asm_float.S | 108 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_double.c | 25 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_float.c | 25 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_vfp_double.S | 27 | ||||
-rw-r--r-- | lib/libc/arm/aeabi/aeabi_vfp_float.S | 24 |
8 files changed, 337 insertions, 1 deletions
diff --git a/lib/libc/arm/aeabi/Makefile.inc b/lib/libc/arm/aeabi/Makefile.inc index b9fd3c0..ff74c61 100644 --- a/lib/libc/arm/aeabi/Makefile.inc +++ b/lib/libc/arm/aeabi/Makefile.inc @@ -2,7 +2,9 @@ .PATH: ${.CURDIR}/arm/aeabi -SRCS+= aeabi_atexit.c \ +SRCS+= aeabi_asm_double.S \ + aeabi_asm_float.S \ + aeabi_atexit.c \ aeabi_double.c \ aeabi_float.c \ aeabi_unwind_cpp.c \ diff --git a/lib/libc/arm/aeabi/Symbol.map b/lib/libc/arm/aeabi/Symbol.map index 9493427..164d3e7 100644 --- a/lib/libc/arm/aeabi/Symbol.map +++ b/lib/libc/arm/aeabi/Symbol.map @@ -17,6 +17,10 @@ FBSDprivate_1.0 { __aeabi_dcmpgt; __aeabi_dcmpun; + __aeabi_cdcmpeq; + __aeabi_cdcmple; + __aeabi_cdrcmple; + __aeabi_d2iz; __aeabi_d2f; @@ -33,6 +37,10 @@ FBSDprivate_1.0 { __aeabi_fcmpgt; __aeabi_fcmpun; + __aeabi_cfcmpeq; + __aeabi_cfcmple; + __aeabi_cfrcmple; + __aeabi_f2iz; __aeabi_f2d; 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 0000000..ab44362 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_asm_double.S @@ -0,0 +1,117 @@ +/* + * 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> +__FBSDID("$FreeBSD$"); + +#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 */ + msr cpsr_c, #(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 */ + msr cpsr_c, #(PCR_Z | PCR_C) + b 99f + +2: + /* Not less than or equal, set C and clear Z */ + msr cpsr_c, #(PCR_C) + +99: + 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: + msr cpsr_c, #(PCR_C) + RET +END(__aeabi_cdcmpeq) 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 0000000..bf32af7 --- /dev/null +++ b/lib/libc/arm/aeabi/aeabi_asm_float.S @@ -0,0 +1,108 @@ +/* + * 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> +__FBSDID("$FreeBSD$"); + +#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 */ + msr cpsr_c, #(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 */ + msr cpsr_c, #(PCR_Z | PCR_C) + b 99f + +2: + /* Not less than or equal, set C and clear Z */ + msr cpsr_c, #(PCR_C) + +99: + 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: + msreq cpsr_c, #(PCR_C) + RET +END(__aeabi_cfcmpeq) diff --git a/lib/libc/arm/aeabi/aeabi_double.c b/lib/libc/arm/aeabi/aeabi_double.c index 274279d..a69e8a7 100644 --- a/lib/libc/arm/aeabi/aeabi_double.c +++ b/lib/libc/arm/aeabi/aeabi_double.c @@ -74,3 +74,28 @@ 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 index be7a6d6..2e93594 100644 --- a/lib/libc/arm/aeabi/aeabi_float.c +++ b/lib/libc/arm/aeabi/aeabi_float.c @@ -74,3 +74,28 @@ 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_vfp_double.S b/lib/libc/arm/aeabi/aeabi_vfp_double.S index 842412b..62100d2 100644 --- a/lib/libc/arm/aeabi/aeabi_vfp_double.S +++ b/lib/libc/arm/aeabi/aeabi_vfp_double.S @@ -33,6 +33,33 @@ __FBSDID("$FreeBSD$"); .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) diff --git a/lib/libc/arm/aeabi/aeabi_vfp_float.S b/lib/libc/arm/aeabi/aeabi_vfp_float.S index d81b2b2..c9a9a7e 100644 --- a/lib/libc/arm/aeabi/aeabi_vfp_float.S +++ b/lib/libc/arm/aeabi/aeabi_vfp_float.S @@ -33,6 +33,30 @@ __FBSDID("$FreeBSD$"); .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) |