diff options
Diffstat (limited to 'lib/libc/arm')
57 files changed, 6211 insertions, 0 deletions
diff --git a/lib/libc/arm/Makefile.inc b/lib/libc/arm/Makefile.inc new file mode 100644 index 000000000000..70605ac1ac35 --- /dev/null +++ b/lib/libc/arm/Makefile.inc @@ -0,0 +1,16 @@ +# +# Machine dependent definitions for the arm architecture. +# + +SOFTFLOAT_BITS=32 + +# Long double is just double precision. +SRCS+=machdep_ldisd.c +SYM_MAPS+=${LIBC_SRCTOP}/arm/Symbol.map + +.include "${LIBC_SRCTOP}/arm/aeabi/Makefile.inc" + +.if !defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "" +SYM_MAPS+=${LIBC_SRCTOP}/arm/Symbol_vfp.map +.endif + diff --git a/lib/libc/arm/Symbol.map b/lib/libc/arm/Symbol.map new file mode 100644 index 000000000000..49476d2e176a --- /dev/null +++ b/lib/libc/arm/Symbol.map @@ -0,0 +1,37 @@ +/* + * This only needs to contain 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, ...). + */ +FBSD_1.0 { + __mcount; + alloca; + brk; + sbrk; +}; + +FBSD_1.3 { + __flt_rounds; +}; + +FBSD_1.4 { + __gnu_Unwind_Find_exidx; + dl_unwind_find_exidx; +}; + +FBSD_1.6 { + arm_drain_writebuf; + arm_sync_icache; +}; + +FBSDprivate_1.0 { + _brk; + __aeabi_read_tp; + ___longjmp; + __longjmp; + signalcontext; + __signalcontext; + __siglongjmp; + + _libc_arm_fpu_present; +}; diff --git a/lib/libc/arm/Symbol_vfp.map b/lib/libc/arm/Symbol_vfp.map new file mode 100644 index 000000000000..29d2b66af1bc --- /dev/null +++ b/lib/libc/arm/Symbol_vfp.map @@ -0,0 +1,14 @@ +/* + */ + +FBSD_1.0 { + fpgetmask; + fpgetround; + fpsetmask; + fpsetround; +}; + +FBSD_1.5 { + fpgetsticky; + fpsetsticky; +}; diff --git a/lib/libc/arm/_fpmath.h b/lib/libc/arm/_fpmath.h new file mode 100644 index 000000000000..51dd039641b0 --- /dev/null +++ b/lib/libc/arm/_fpmath.h @@ -0,0 +1,67 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2002, 2003 David Schultz <das@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. + */ + +#if defined(__VFP_FP__) || defined(__ARM_EABI__) +#define _IEEE_WORD_ORDER _BYTE_ORDER +#else +#define _IEEE_WORD_ORDER _BIG_ENDIAN +#endif + +union IEEEl2bits { + long double e; + struct { +#if _BYTE_ORDER == _LITTLE_ENDIAN +#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN + unsigned int manl :32; +#endif + unsigned int manh :20; + unsigned int exp :11; + unsigned int sign :1; +#if _IEEE_WORD_ORDER == _BIG_ENDIAN + unsigned int manl :32; +#endif +#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ + unsigned int sign :1; + unsigned int exp :11; + unsigned int manh :20; + unsigned int manl :32; +#endif + } bits; +}; + +#define LDBL_NBIT 0 +#define LDBL_IMPLICIT_NBIT +#define mask_nbit_l(u) ((void)0) + +#define LDBL_MANH_SIZE 20 +#define LDBL_MANL_SIZE 32 + +#define LDBL_TO_ARRAY32(u, a) do { \ + (a)[0] = (uint32_t)(u).bits.manl; \ + (a)[1] = (uint32_t)(u).bits.manh; \ +} while(0) 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 diff --git a/lib/libc/arm/arith.h b/lib/libc/arm/arith.h new file mode 100644 index 000000000000..418f83f64ccb --- /dev/null +++ b/lib/libc/arm/arith.h @@ -0,0 +1,15 @@ +/* + * MD header for contrib/gdtoa + * + * NOTE: The definitions in this file must be correct or strtod(3) and + * floating point formats in printf(3) will break! The file can be + * generated by running contrib/gdtoa/arithchk.c on the target + * architecture. See contrib/gdtoa/gdtoaimp.h for details. + * + * Generated on CA15, verified on CA9, CA7(with VFP lite) and on 32-bit ARMv9. + * + */ + +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Double_Align diff --git a/lib/libc/arm/gd_qnan.h b/lib/libc/arm/gd_qnan.h new file mode 100644 index 000000000000..acf13d0b7852 --- /dev/null +++ b/lib/libc/arm/gd_qnan.h @@ -0,0 +1,22 @@ +/* + * MD header for contrib/gdtoa + * + * This file can be generated by compiling and running contrib/gdtoa/qnan.c + * on the target architecture after arith.h has been generated. + * + * Generated on CA15, verified on CA9, CA7(with VFP lite) and on 32-bit ARMv9. + * + */ + +#define f_QNAN 0x7fc00000 +#define d_QNAN0 0x0 +#define d_QNAN1 0x7ff80000 +#define ld_QNAN0 0x0 +#define ld_QNAN1 0x7ff80000 +#define ld_QNAN2 0x0 +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0x0 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0x7ff8 +#define ldus_QNAN4 0x0 diff --git a/lib/libc/arm/gen/Makefile.inc b/lib/libc/arm/gen/Makefile.inc new file mode 100644 index 000000000000..dfb83da20a1f --- /dev/null +++ b/lib/libc/arm/gen/Makefile.inc @@ -0,0 +1,33 @@ +SRCS+= \ + __aeabi_read_tp.S \ + _ctx_start.S \ + _setjmp.S \ + alloca.S \ + arm_initfini.c \ + arm_drain_writebuf.c \ + arm_sync_icache.c \ + fabs.c \ + flt_rounds.c \ + getcontextx.c \ + infinity.c \ + ldexp.c \ + makecontext.c \ + setjmp.S \ + signalcontext.c \ + sigsetjmp.S \ + +MAN+= \ + arm_drain_writebuf.2 \ + arm_sync_icache.2 \ + +.if !defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "" + +SRCS+= \ + fpgetmask_vfp.c \ + fpgetround_vfp.c \ + fpgetsticky_vfp.c \ + fpsetmask_vfp.c \ + fpsetround_vfp.c \ + fpsetsticky_vfp.c \ + +.endif diff --git a/lib/libc/arm/gen/__aeabi_read_tp.S b/lib/libc/arm/gen/__aeabi_read_tp.S new file mode 100644 index 000000000000..066d92e2e956 --- /dev/null +++ b/lib/libc/arm/gen/__aeabi_read_tp.S @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2012 Oleksandr Tymoshenko + * 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 <machine/asm.h> +#include <machine/sysarch.h> + +ENTRY(__aeabi_read_tp) + mrc p15, 0, r0, c13, c0, 3 + RET +END(__aeabi_read_tp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/_ctx_start.S b/lib/libc/arm/gen/_ctx_start.S new file mode 100644 index 000000000000..cd8d25b9e583 --- /dev/null +++ b/lib/libc/arm/gen/_ctx_start.S @@ -0,0 +1,11 @@ +#include <machine/asm.h> + +ENTRY(_ctx_start) + mov lr, pc + mov pc, r4 + mov r0, r5 + bl _C_LABEL(ctx_done) + bl _C_LABEL(abort) +END(_ctx_start) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/_setjmp.S b/lib/libc/arm/gen/_setjmp.S new file mode 100644 index 000000000000..9e655d2e9e2e --- /dev/null +++ b/lib/libc/arm/gen/_setjmp.S @@ -0,0 +1,135 @@ +/* $NetBSD: _setjmp.S,v 1.12 2013/04/19 13:45:45 matt Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +#if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS) +#error FPA is not supported anymore +#endif + +#if !defined(_STANDALONE) + .fpu vfp +#endif + +#include <machine/asm.h> +#include <machine/setjmp.h> +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + * + * Note: r0 is the return value + * r1-r3,ip are scratch registers in functions + */ + +ENTRY(_setjmp) + ldr r1, .L_setjmp_magic + +#if !defined(_STANDALONE) && !defined(SOFTFLOAT_FOR_GCC) + add r2, r0, #(_JB_REG_D8 * 4) + vstmia r2, {d8-d15} + vmrs r2, fpscr + str r2, [r0, #(_JB_REG_FPSCR * 4)] +#endif /* !_STANDALONE && !SOFTFLOAT_FOR_GCC */ + + str r1, [r0] + + add r0, r0, #(_JB_REG_R4 * 4) + /* Store integer registers */ +#ifndef __thumb__ + stmia r0, {r4-r14} +#else + stmia r0, {r4-r12} + str r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)] + str r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)] +#endif + + mov r0, #0x00000000 + RET +END(_setjmp) + +.L_setjmp_magic: + .word _JB_MAGIC__SETJMP + +WEAK_ALIAS(___longjmp, _longjmp) +ENTRY(_longjmp) + ldr r2, [r0] /* get magic from jmp_buf */ + ldr ip, .L_setjmp_magic /* load magic */ + teq ip, r2 /* magic correct? */ + bne botch /* no, botch */ + +#if !defined(_STANDALONE) && !defined(SOFTFLOAT_FOR_GCC) + add ip, r0, #(_JB_REG_D8 * 4) + vldmia ip, {d8-d15} + ldr ip, [r0, #(_JB_REG_FPSCR * 4)] + vmsr fpscr, ip +#endif /* !_STANDALONE && !SOFTFLOAT_FOR_GCC */ + + add r0, r0, #(_JB_REG_R4 * 4) + /* Restore integer registers */ +#ifndef __thumb__ + ldmia r0, {r4-r14} +#else + ldmia r0, {r4-r12} + ldr r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)] + ldr r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)] +#endif + + /* Validate sp and r14 */ + teq sp, #0 + it ne + teqne r14, #0 + it eq + beq botch + + /* Set return value */ + movs r0, r1 + it eq + moveq r0, #0x00000001 + RET + + /* validation failed, die die die. */ +botch: +#if !defined(_STANDALONE) + bl PIC_SYM(_C_LABEL(longjmperror), PLT) + bl PIC_SYM(_C_LABEL(abort), PLT) +1: b 1b /* Cannot get here */ +#else + b . +#endif +END(_longjmp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/alloca.S b/lib/libc/arm/gen/alloca.S new file mode 100644 index 000000000000..3545cc642aad --- /dev/null +++ b/lib/libc/arm/gen/alloca.S @@ -0,0 +1,46 @@ +/* $NetBSD: alloca.S,v 1.3 2003/04/05 23:08:51 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +/* like alloc, but automatic automatic free in return */ + +#include <machine/asm.h> +ENTRY(alloca) + add r0, r0, #0x00000007 /* round up to next 8 byte alignment */ + bic r0, r0, #0x00000007 + sub sp, sp, r0 /* Adjust the stack pointer */ + mov r0, sp /* r0 = base of new space */ + RET +END(alloca) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/arm_drain_writebuf.2 b/lib/libc/arm/gen/arm_drain_writebuf.2 new file mode 100644 index 000000000000..613c35d39ef2 --- /dev/null +++ b/lib/libc/arm/gen/arm_drain_writebuf.2 @@ -0,0 +1,75 @@ +.\" Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org> +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.Dd July 10, 2019 +.Dt ARM_DRAIN_WRITEBUF 2 +.Os +.Sh NAME +.Nm arm_drain_writebuf +.Nd drain pending writes from cores and caches +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In machine/sysarch.h +.Ft int +.Fn arm_drain_writebuf void +.Sh DESCRIPTION +The +.Nm +system call causes all pending writes from ARM cores and caches to be +written out to main memory or memory-mapped I/O registers. +Not all hardware supports buffered writes; on such systems the +.Nm +function is a no-op. +.Pp +On ARMv5 systems, this executes a cp15 coprocessor +.Dq drain write buffer +operation. +On ARMv6 and ARMv7 systems, this executes a +.Dq DSB SY +synchronization barrier, followed by an L2 cache drain on +systems where the DSB does not include L2 automatically. +.Pp +.Nm +attempts to wait for the drain operation to complete, but cannot +guarantee the writes have reached their ultimate destination on all hardware. +For example, on an ARMv7 system, +.Nm +tells the L2 cache controller to drain its buffers, and it waits until +the controller indicates that operation is complete. +However, all the L2 controller knows is that the data was accepted for +delivery by the AXI bus. +If the ultimate destination of the write is a device on a subordinate +bus connected to the AXI bus, more buffering or other delays may occur +on that subordinate bus. +The only way to be certain a pending write has reached its +ultimate destination is to issue a read from that destination after +.Nm +returns. +.Sh RETURN VALUES +The +.Nm +system call cannot fail, and always returns 0. +.Sh AUTHORS +This man page was written by +.An Ian Lepore . diff --git a/lib/libc/arm/gen/arm_drain_writebuf.c b/lib/libc/arm/gen/arm_drain_writebuf.c new file mode 100644 index 000000000000..30c93718bfe6 --- /dev/null +++ b/lib/libc/arm/gen/arm_drain_writebuf.c @@ -0,0 +1,36 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org> + * + * 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/sysarch.h> +#include <stddef.h> + +int +arm_drain_writebuf(void) +{ + sysarch(ARM_DRAIN_WRITEBUF, NULL); + return (0); +} diff --git a/lib/libc/arm/gen/arm_initfini.c b/lib/libc/arm/gen/arm_initfini.c new file mode 100644 index 000000000000..31756aa852a4 --- /dev/null +++ b/lib/libc/arm/gen/arm_initfini.c @@ -0,0 +1,77 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * Copyright (c) 2013 Andrew Turner + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Bases on NetBSD lib/libc/arch/arm/misc/arm_initfini.c + * $NetBSD: arm_initfini.c,v 1.2 2013/01/31 06:47:55 matt Exp $ + */ + +/* + * To properly implement setjmp/longjmp for the ARM AAPCS ABI, it has to be + * aware of whether there is a FPU is present or not. Regardless of whether + * the hard-float ABI is being used, setjmp needs to save D8-D15. But it can + * only do this if those instructions won't cause an exception. + */ + +#include <sys/param.h> +#include <sys/sysctl.h> + +#include <stdbool.h> +#include <stddef.h> + +extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, + void *newp, size_t newlen); + +int _libc_arm_fpu_present; +static bool _libc_aapcs_initialized; + +void _libc_aapcs_init(void) __attribute__((__constructor__, __used__)); + +void +_libc_aapcs_init(void) +{ + int mib[2]; + size_t len; + + if (_libc_aapcs_initialized) + return; + + mib[0] = CTL_HW; + mib[1] = HW_FLOATINGPT; + + len = sizeof(_libc_arm_fpu_present); + if (__sysctl(mib, 2, &_libc_arm_fpu_present, &len, NULL, 0) == -1 || + len != sizeof(_libc_arm_fpu_present)) { + /* sysctl failed, assume no vfp */ + _libc_arm_fpu_present = 0; + } + + _libc_aapcs_initialized = true; +} diff --git a/lib/libc/arm/gen/arm_sync_icache.2 b/lib/libc/arm/gen/arm_sync_icache.2 new file mode 100644 index 000000000000..c91904aa55d6 --- /dev/null +++ b/lib/libc/arm/gen/arm_sync_icache.2 @@ -0,0 +1,77 @@ +.\" Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org> +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.Dd July 10, 2019 +.Dt ARM_sync_icache 2 +.Os +.Sh NAME +.Nm arm_sync_icache +.Nd synchronize the data and instruction caches +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In machine/sysarch.h +.Ft int +.Fn arm_sync_icache "u_int addr" "int len" +.Sh DESCRIPTION +The +.Nm +system call synchronizes the contents of any data and instructions caches +with the contents of main memory for the given range. +Use this after loading executable code or modifying existing code in memory, +before attempting to execute that code. +.Pp +The +.Va addr +and +.Va len +arguments do not need to be aligned to any particular boundary, but +cache operations will affect entire cache lines, even those which are only +partially overlapped by the given range. +.Pp +This takes one or more of the following actions, depending on the requirements +of the hardware: +.Bl -bullet +.It +Write dirty data cache lines within the range back to main memory. +.It +Invalidate existing instruction cache contents for the range. +.It +Invalidate branch prediction caches for the range. +.El +.Pp +On hardware which supports multiple synchronization points for cache +operations, the caches are maintained to the point of unification, +making the data in the range coherent amongst all cores. +.Sh RETURN VALUES +The +.Nm +system call always returns 0. +.Sh ERRORS +If a call refers to memory which the calling process does not have rights +to access, or if the +.Va len +argument is negative, a SIGSEGV signal is delivered to the calling thread. +.Sh AUTHORS +This man page was written by +.An Ian Lepore . diff --git a/lib/libc/arm/gen/arm_sync_icache.c b/lib/libc/arm/gen/arm_sync_icache.c new file mode 100644 index 000000000000..b5872fb8ef00 --- /dev/null +++ b/lib/libc/arm/gen/arm_sync_icache.c @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org> + * + * 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/sysarch.h> +#include <stddef.h> + +int +arm_sync_icache(u_int addr, int len) +{ + struct arm_sync_icache_args args; + + args.addr = addr; + args.len = len; + sysarch(ARM_SYNC_ICACHE, &args); + return (0); +} diff --git a/lib/libc/arm/gen/divsi3.S b/lib/libc/arm/gen/divsi3.S new file mode 100644 index 000000000000..9fddebaf96f3 --- /dev/null +++ b/lib/libc/arm/gen/divsi3.S @@ -0,0 +1,391 @@ +/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ + +/* + * 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> +/* + * stack is aligned as there's a possibility of branching to L_overflow + * which makes a C call + */ + +ENTRY(__umodsi3) + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_udivide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} +END(__umodsi3) + +ENTRY(__modsi3) + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_divide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} + +.L_overflow: +#if !defined(_KERNEL) && !defined(_STANDALONE) + mov r0, #8 /* SIGFPE */ + bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ + mov r0, #0 +#else + /* XXX should cause a fatal error */ + mvn r0, #0 +#endif + RET +END(__modsi3) + +ENTRY(__udivsi3) +.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + mov ip, #0 + movs r1, r1 + bpl .L_divide_l1 + orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ + movs r1, r1, lsr #1 + orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ + b .L_divide_l1 + +.L_divide_l0: /* r0 == 1 */ + mov r0, r1 + mov r1, #0 + RET +END(__udivsi3) + +ENTRY(__divsi3) +.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + ands ip, r0, #0x80000000 + rsbmi r0, r0, #0 + ands r2, r1, #0x80000000 + eor ip, ip, r2 + rsbmi r1, r1, #0 + orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ + /* ip bit 0x80000000 = -ve remainder */ + +.L_divide_l1: + mov r2, #1 + mov r3, #0 + + /* + * If the highest bit of the dividend is set, we have to be + * careful when shifting the divisor. Test this. + */ + movs r1,r1 + bpl .L_old_code + + /* + * At this point, the highest bit of r1 is known to be set. + * We abuse this below in the tst instructions. + */ + tst r1, r0 /*, lsl #0 */ + bmi .L_divide_b1 + tst r1, r0, lsl #1 + bmi .L_divide_b2 + tst r1, r0, lsl #2 + bmi .L_divide_b3 + tst r1, r0, lsl #3 + bmi .L_divide_b4 + tst r1, r0, lsl #4 + bmi .L_divide_b5 + tst r1, r0, lsl #5 + bmi .L_divide_b6 + tst r1, r0, lsl #6 + bmi .L_divide_b7 + tst r1, r0, lsl #7 + bmi .L_divide_b8 + tst r1, r0, lsl #8 + bmi .L_divide_b9 + tst r1, r0, lsl #9 + bmi .L_divide_b10 + tst r1, r0, lsl #10 + bmi .L_divide_b11 + tst r1, r0, lsl #11 + bmi .L_divide_b12 + tst r1, r0, lsl #12 + bmi .L_divide_b13 + tst r1, r0, lsl #13 + bmi .L_divide_b14 + tst r1, r0, lsl #14 + bmi .L_divide_b15 + tst r1, r0, lsl #15 + bmi .L_divide_b16 + tst r1, r0, lsl #16 + bmi .L_divide_b17 + tst r1, r0, lsl #17 + bmi .L_divide_b18 + tst r1, r0, lsl #18 + bmi .L_divide_b19 + tst r1, r0, lsl #19 + bmi .L_divide_b20 + tst r1, r0, lsl #20 + bmi .L_divide_b21 + tst r1, r0, lsl #21 + bmi .L_divide_b22 + tst r1, r0, lsl #22 + bmi .L_divide_b23 + tst r1, r0, lsl #23 + bmi .L_divide_b24 + tst r1, r0, lsl #24 + bmi .L_divide_b25 + tst r1, r0, lsl #25 + bmi .L_divide_b26 + tst r1, r0, lsl #26 + bmi .L_divide_b27 + tst r1, r0, lsl #27 + bmi .L_divide_b28 + tst r1, r0, lsl #28 + bmi .L_divide_b29 + tst r1, r0, lsl #29 + bmi .L_divide_b30 + tst r1, r0, lsl #30 + bmi .L_divide_b31 +/* + * instead of: + * tst r1, r0, lsl #31 + * bmi .L_divide_b32 + */ + b .L_divide_b32 + +.L_old_code: + cmp r1, r0 + bcc .L_divide_b0 + cmp r1, r0, lsl #1 + bcc .L_divide_b1 + cmp r1, r0, lsl #2 + bcc .L_divide_b2 + cmp r1, r0, lsl #3 + bcc .L_divide_b3 + cmp r1, r0, lsl #4 + bcc .L_divide_b4 + cmp r1, r0, lsl #5 + bcc .L_divide_b5 + cmp r1, r0, lsl #6 + bcc .L_divide_b6 + cmp r1, r0, lsl #7 + bcc .L_divide_b7 + cmp r1, r0, lsl #8 + bcc .L_divide_b8 + cmp r1, r0, lsl #9 + bcc .L_divide_b9 + cmp r1, r0, lsl #10 + bcc .L_divide_b10 + cmp r1, r0, lsl #11 + bcc .L_divide_b11 + cmp r1, r0, lsl #12 + bcc .L_divide_b12 + cmp r1, r0, lsl #13 + bcc .L_divide_b13 + cmp r1, r0, lsl #14 + bcc .L_divide_b14 + cmp r1, r0, lsl #15 + bcc .L_divide_b15 + cmp r1, r0, lsl #16 + bcc .L_divide_b16 + cmp r1, r0, lsl #17 + bcc .L_divide_b17 + cmp r1, r0, lsl #18 + bcc .L_divide_b18 + cmp r1, r0, lsl #19 + bcc .L_divide_b19 + cmp r1, r0, lsl #20 + bcc .L_divide_b20 + cmp r1, r0, lsl #21 + bcc .L_divide_b21 + cmp r1, r0, lsl #22 + bcc .L_divide_b22 + cmp r1, r0, lsl #23 + bcc .L_divide_b23 + cmp r1, r0, lsl #24 + bcc .L_divide_b24 + cmp r1, r0, lsl #25 + bcc .L_divide_b25 + cmp r1, r0, lsl #26 + bcc .L_divide_b26 + cmp r1, r0, lsl #27 + bcc .L_divide_b27 + cmp r1, r0, lsl #28 + bcc .L_divide_b28 + cmp r1, r0, lsl #29 + bcc .L_divide_b29 + cmp r1, r0, lsl #30 + bcc .L_divide_b30 +.L_divide_b32: + cmp r1, r0, lsl #31 + subhs r1, r1,r0, lsl #31 + addhs r3, r3,r2, lsl #31 +.L_divide_b31: + cmp r1, r0, lsl #30 + subhs r1, r1,r0, lsl #30 + addhs r3, r3,r2, lsl #30 +.L_divide_b30: + cmp r1, r0, lsl #29 + subhs r1, r1,r0, lsl #29 + addhs r3, r3,r2, lsl #29 +.L_divide_b29: + cmp r1, r0, lsl #28 + subhs r1, r1,r0, lsl #28 + addhs r3, r3,r2, lsl #28 +.L_divide_b28: + cmp r1, r0, lsl #27 + subhs r1, r1,r0, lsl #27 + addhs r3, r3,r2, lsl #27 +.L_divide_b27: + cmp r1, r0, lsl #26 + subhs r1, r1,r0, lsl #26 + addhs r3, r3,r2, lsl #26 +.L_divide_b26: + cmp r1, r0, lsl #25 + subhs r1, r1,r0, lsl #25 + addhs r3, r3,r2, lsl #25 +.L_divide_b25: + cmp r1, r0, lsl #24 + subhs r1, r1,r0, lsl #24 + addhs r3, r3,r2, lsl #24 +.L_divide_b24: + cmp r1, r0, lsl #23 + subhs r1, r1,r0, lsl #23 + addhs r3, r3,r2, lsl #23 +.L_divide_b23: + cmp r1, r0, lsl #22 + subhs r1, r1,r0, lsl #22 + addhs r3, r3,r2, lsl #22 +.L_divide_b22: + cmp r1, r0, lsl #21 + subhs r1, r1,r0, lsl #21 + addhs r3, r3,r2, lsl #21 +.L_divide_b21: + cmp r1, r0, lsl #20 + subhs r1, r1,r0, lsl #20 + addhs r3, r3,r2, lsl #20 +.L_divide_b20: + cmp r1, r0, lsl #19 + subhs r1, r1,r0, lsl #19 + addhs r3, r3,r2, lsl #19 +.L_divide_b19: + cmp r1, r0, lsl #18 + subhs r1, r1,r0, lsl #18 + addhs r3, r3,r2, lsl #18 +.L_divide_b18: + cmp r1, r0, lsl #17 + subhs r1, r1,r0, lsl #17 + addhs r3, r3,r2, lsl #17 +.L_divide_b17: + cmp r1, r0, lsl #16 + subhs r1, r1,r0, lsl #16 + addhs r3, r3,r2, lsl #16 +.L_divide_b16: + cmp r1, r0, lsl #15 + subhs r1, r1,r0, lsl #15 + addhs r3, r3,r2, lsl #15 +.L_divide_b15: + cmp r1, r0, lsl #14 + subhs r1, r1,r0, lsl #14 + addhs r3, r3,r2, lsl #14 +.L_divide_b14: + cmp r1, r0, lsl #13 + subhs r1, r1,r0, lsl #13 + addhs r3, r3,r2, lsl #13 +.L_divide_b13: + cmp r1, r0, lsl #12 + subhs r1, r1,r0, lsl #12 + addhs r3, r3,r2, lsl #12 +.L_divide_b12: + cmp r1, r0, lsl #11 + subhs r1, r1,r0, lsl #11 + addhs r3, r3,r2, lsl #11 +.L_divide_b11: + cmp r1, r0, lsl #10 + subhs r1, r1,r0, lsl #10 + addhs r3, r3,r2, lsl #10 +.L_divide_b10: + cmp r1, r0, lsl #9 + subhs r1, r1,r0, lsl #9 + addhs r3, r3,r2, lsl #9 +.L_divide_b9: + cmp r1, r0, lsl #8 + subhs r1, r1,r0, lsl #8 + addhs r3, r3,r2, lsl #8 +.L_divide_b8: + cmp r1, r0, lsl #7 + subhs r1, r1,r0, lsl #7 + addhs r3, r3,r2, lsl #7 +.L_divide_b7: + cmp r1, r0, lsl #6 + subhs r1, r1,r0, lsl #6 + addhs r3, r3,r2, lsl #6 +.L_divide_b6: + cmp r1, r0, lsl #5 + subhs r1, r1,r0, lsl #5 + addhs r3, r3,r2, lsl #5 +.L_divide_b5: + cmp r1, r0, lsl #4 + subhs r1, r1,r0, lsl #4 + addhs r3, r3,r2, lsl #4 +.L_divide_b4: + cmp r1, r0, lsl #3 + subhs r1, r1,r0, lsl #3 + addhs r3, r3,r2, lsl #3 +.L_divide_b3: + cmp r1, r0, lsl #2 + subhs r1, r1,r0, lsl #2 + addhs r3, r3,r2, lsl #2 +.L_divide_b2: + cmp r1, r0, lsl #1 + subhs r1, r1,r0, lsl #1 + addhs r3, r3,r2, lsl #1 +.L_divide_b1: + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 +.L_divide_b0: + + tst ip, #0x20000000 + bne .L_udivide_l1 + mov r0, r3 + cmp ip, #0 + rsbmi r1, r1, #0 + movs ip, ip, lsl #1 + bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ + rsbmi r0, r0, #0 + RET + +.L_udivide_l1: + tst ip, #0x10000000 + mov r1, r1, lsl #1 + orrne r1, r1, #1 + mov r3, r3, lsl #1 + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 + mov r0, r3 + RET +END(__divsi3) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/fabs.c b/lib/libc/arm/gen/fabs.c new file mode 100644 index 000000000000..2e0abbb8a42a --- /dev/null +++ b/lib/libc/arm/gen/fabs.c @@ -0,0 +1,45 @@ +/* $NetBSD: fabs.c,v 1.2 2002/05/26 11:48:01 wiz Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1996 Mark Brinicombe + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +/* + * fabs(x) returns the absolute value of x. + */ +double +fabs(double x) +{ + if (x < 0) + x = -x; + return(x); +} diff --git a/lib/libc/arm/gen/flt_rounds.c b/lib/libc/arm/gen/flt_rounds.c new file mode 100644 index 000000000000..7621262419a4 --- /dev/null +++ b/lib/libc/arm/gen/flt_rounds.c @@ -0,0 +1,68 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2012 Ian Lepore <freebsd@damnhippie.dyndns.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 <fenv.h> +#include <float.h> + +#ifndef __ARM_PCS_VFP +#include "softfloat-for-gcc.h" +#include "milieu.h" +#include "softfloat.h" +#endif + +int +__flt_rounds(void) +{ + int mode; + +#ifndef __ARM_PCS_VFP + /* + * Translate our rounding modes to the unnamed + * manifest constants required by C99 et. al. + */ + mode = __softfloat_float_rounding_mode; +#else /* __ARM_PCS_VFP */ + /* + * Read the floating-point status and control register + */ + __asm __volatile("vmrs %0, fpscr" : "=&r"(mode)); + mode &= _ROUND_MASK; +#endif /* __ARM_PCS_VFP */ + + switch (mode) { + case FE_TOWARDZERO: + return (0); + case FE_TONEAREST: + return (1); + case FE_UPWARD: + return (2); + case FE_DOWNWARD: + return (3); + } + return (-1); +} diff --git a/lib/libc/arm/gen/fpgetmask_vfp.c b/lib/libc/arm/gen/fpgetmask_vfp.c new file mode 100644 index 000000000000..5e73a274dafa --- /dev/null +++ b/lib/libc/arm/gen/fpgetmask_vfp.c @@ -0,0 +1,42 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#define FP_X_MASK (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP) + +fp_except_t +fpgetmask(void) +{ + fp_except mask; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(mask)); + + return ((mask >> 8) & FP_X_MASK); +} + diff --git a/lib/libc/arm/gen/fpgetround_vfp.c b/lib/libc/arm/gen/fpgetround_vfp.c new file mode 100644 index 000000000000..21debc0b028d --- /dev/null +++ b/lib/libc/arm/gen/fpgetround_vfp.c @@ -0,0 +1,44 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#ifdef __weak_alias +__weak_alias(fpgetround,_fpgetround) +#endif + +fp_rnd_t +fpgetround(void) +{ + uint32_t fpscr; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(fpscr)); + + return ((fpscr >> 22) & 3); +} + diff --git a/lib/libc/arm/gen/fpgetsticky_vfp.c b/lib/libc/arm/gen/fpgetsticky_vfp.c new file mode 100644 index 000000000000..651610dddf83 --- /dev/null +++ b/lib/libc/arm/gen/fpgetsticky_vfp.c @@ -0,0 +1,42 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#define FP_X_MASK (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP) + +fp_except +fpgetsticky(void) +{ + fp_except old; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(old)); + + return (old & FP_X_MASK); +} + diff --git a/lib/libc/arm/gen/fpsetmask_vfp.c b/lib/libc/arm/gen/fpsetmask_vfp.c new file mode 100644 index 000000000000..92ad97e6dfa2 --- /dev/null +++ b/lib/libc/arm/gen/fpsetmask_vfp.c @@ -0,0 +1,49 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#ifdef __weak_alias +__weak_alias(fpsetmask,_fpsetmask) +#endif + +#define FP_X_MASK (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP) + +fp_except_t +fpsetmask(fp_except_t mask) +{ + fp_except old, new; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(old)); + mask = (mask & FP_X_MASK) << 8; + new = (old & ~(FP_X_MASK << 8)) | mask; + __asm __volatile("vmsr fpscr, %0" : : "r"(new)); + + return ((old >> 8) & FP_X_MASK); +} + diff --git a/lib/libc/arm/gen/fpsetround_vfp.c b/lib/libc/arm/gen/fpsetround_vfp.c new file mode 100644 index 000000000000..4e55335f6a3b --- /dev/null +++ b/lib/libc/arm/gen/fpsetround_vfp.c @@ -0,0 +1,47 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#ifdef __weak_alias +__weak_alias(fpsetround,_fpsetround) +#endif + +fp_rnd_t +fpsetround(fp_rnd_t rnd_dir) +{ + uint32_t old, new; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(old)); + new = old & ~(3 << 22); + new |= rnd_dir << 22; + __asm __volatile("vmsr fpscr, %0" : : "r"(new)); + + return ((old >> 22) & 3); +} + diff --git a/lib/libc/arm/gen/fpsetsticky_vfp.c b/lib/libc/arm/gen/fpsetsticky_vfp.c new file mode 100644 index 000000000000..fb3a59b25178 --- /dev/null +++ b/lib/libc/arm/gen/fpsetsticky_vfp.c @@ -0,0 +1,49 @@ +/* + * 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 <sys/types.h> +#include <ieeefp.h> + +#ifdef __weak_alias +__weak_alias(fpsetsticky,_fpsetsticky) +#endif + +#define FP_X_MASK (FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_IMP) + +fp_except +fpsetsticky(fp_except except) +{ + fp_except old, new; + + __asm __volatile("vmrs %0, fpscr" : "=&r"(old)); + new = old & ~(FP_X_MASK); + new &= ~except; + __asm __volatile("vmsr fpscr, %0" : : "r"(new)); + + return (old & except); +} + diff --git a/lib/libc/arm/gen/getcontextx.c b/lib/libc/arm/gen/getcontextx.c new file mode 100644 index 000000000000..357d3a2a0416 --- /dev/null +++ b/lib/libc/arm/gen/getcontextx.c @@ -0,0 +1,98 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2017 Michal Meloun <mmel@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 ``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 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 <sys/ucontext.h> +#include <errno.h> +#include <stdlib.h> +#include <machine/sysarch.h> + +struct ucontextx { + ucontext_t ucontext; + mcontext_vfp_t mcontext_vfp; +}; + +int +__getcontextx_size(void) +{ + + return (sizeof(struct ucontextx)); +} + +int +__fillcontextx2(char *ctx) +{ + struct ucontextx *ucxp; + ucontext_t *ucp; + mcontext_vfp_t *mvp; + struct arm_get_vfpstate_args vfp_arg; + + ucxp = (struct ucontextx *)ctx; + ucp = &ucxp->ucontext; + mvp = &ucxp->mcontext_vfp; + + vfp_arg.mc_vfp_size = sizeof(mcontext_vfp_t); + vfp_arg.mc_vfp = mvp; + if (sysarch(ARM_GET_VFPSTATE, &vfp_arg) == -1) + return (-1); + ucp->uc_mcontext.mc_vfp_size = sizeof(mcontext_vfp_t); + ucp->uc_mcontext.mc_vfp_ptr = mvp; + return (0); +} + +int +__fillcontextx(char *ctx) +{ + struct ucontextx *ucxp; + + ucxp = (struct ucontextx *)ctx; + if (getcontext(&ucxp->ucontext) == -1) + return (-1); + __fillcontextx2(ctx); + return (0); +} + +__weak_reference(__getcontextx, getcontextx); + +ucontext_t * +__getcontextx(void) +{ + char *ctx; + int error; + + ctx = malloc(__getcontextx_size()); + if (ctx == NULL) + return (NULL); + if (__fillcontextx(ctx) == -1) { + error = errno; + free(ctx); + errno = error; + return (NULL); + } + return ((ucontext_t *)ctx); +} diff --git a/lib/libc/arm/gen/infinity.c b/lib/libc/arm/gen/infinity.c new file mode 100644 index 000000000000..1a78a03be2e3 --- /dev/null +++ b/lib/libc/arm/gen/infinity.c @@ -0,0 +1,23 @@ +/* + * infinity.c + */ + +#include <math.h> + +/* bytes for +Infinity on a 387 */ +const union __infinity_un __infinity = { +#if BYTE_ORDER == BIG_ENDIAN + { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +#else + { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +#endif +}; + +/* bytes for NaN */ +const union __nan_un __nan = { +#if BYTE_ORDER == BIG_ENDIAN + {0xff, 0xc0, 0, 0} +#else + { 0, 0, 0xc0, 0xff } +#endif +}; diff --git a/lib/libc/arm/gen/makecontext.c b/lib/libc/arm/gen/makecontext.c new file mode 100644 index 000000000000..ac338085f2ed --- /dev/null +++ b/lib/libc/arm/gen/makecontext.c @@ -0,0 +1,88 @@ +/* $NetBSD: makecontext.c,v 1.2 2003/01/18 11:06:24 thorpej Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <stdlib.h> +#include <stddef.h> +#include <inttypes.h> +#include <ucontext.h> + +#include <stdarg.h> + +extern void _ctx_start(void); + +void +ctx_done(ucontext_t *ucp) +{ + + if (ucp->uc_link == NULL) + exit(0); + else { + setcontext((const ucontext_t *)ucp->uc_link); + abort(); + } +} + +__weak_reference(__makecontext, makecontext); + +void +__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + __greg_t *gr = ucp->uc_mcontext.__gregs; + int i; + unsigned int *sp; + va_list ap; + + /* Compute and align stack pointer. */ + sp = (unsigned int *) + (((uintptr_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size - + sizeof(double)) & ~7); + /* Allocate necessary stack space for arguments exceeding r0-3. */ + if (argc > 4) + sp -= argc - 4; + gr[_REG_SP] = (__greg_t)sp; + /* Wipe out frame pointer. */ + gr[_REG_FP] = 0; + /* Arrange for return via the trampoline code. */ + gr[_REG_PC] = (__greg_t)_ctx_start; + gr[_REG_R4] = (__greg_t)func; + gr[_REG_R5] = (__greg_t)ucp; + + va_start(ap, argc); + /* Pass up to four arguments in r0-3. */ + for (i = 0; i < argc && i < 4; i++) + gr[_REG_R0 + i] = va_arg(ap, int); + /* Pass any additional arguments on the stack. */ + for (argc -= i; argc > 0; argc--) + *sp++ = va_arg(ap, int); + va_end(ap); +} diff --git a/lib/libc/arm/gen/setjmp.S b/lib/libc/arm/gen/setjmp.S new file mode 100644 index 000000000000..e7f8b788e878 --- /dev/null +++ b/lib/libc/arm/gen/setjmp.S @@ -0,0 +1,142 @@ +/* $NetBSD: setjmp.S,v 1.14 2013/04/19 13:45:45 matt Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + */ + +#if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS) +#error FPA is not supported anymore +#endif + + .fpu vfp + +#include <machine/asm.h> +#include <machine/setjmp.h> +/* + * C library -- setjmp, longjmp + * + * longjmp(a,v) + * will generate a "return(v)" from the last call to + * setjmp(a) + * by restoring registers from the stack. + * The previous signal state is restored. + */ + +ENTRY(setjmp) + /* Block all signals and retrieve the old signal mask */ + stmfd sp!, {r0, r14} + add r2, r0, #(_JB_SIGMASK * 4) /* oset */ + mov r1, #0x00000000 /* set */ + mov r0, #0x00000001 /* SIG_BLOCK */ + bl PIC_SYM(_C_LABEL(sigprocmask), PLT) + ldmfd sp!, {r0, r14} + + ldr r1, .Lsetjmp_magic + +#if !defined(SOFTFLOAT_FOR_GCC) + add r2, r0, #(_JB_REG_D8 * 4) + vstmia r2, {d8-d15} + vmrs r2, fpscr + str r2, [r0, #(_JB_REG_FPSCR * 4)] +#endif + + str r1, [r0] /* store magic */ + + /* Store integer registers */ + add r0, r0, #(_JB_REG_R4 * 4) +#ifndef __thumb__ + stmia r0, {r4-r14} +#else + stmia r0, {r4-r12} + str r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)] + str r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)] +#endif + mov r0, #0x00000000 + RET + +.Lsetjmp_magic: + .word _JB_MAGIC_SETJMP +END(setjmp) + +.weak _C_LABEL(longjmp) +.set _C_LABEL(longjmp), _C_LABEL(__longjmp) +ENTRY(__longjmp) + ldr r2, [r0] + ldr ip, .Lsetjmp_magic + teq r2, ip + bne .Lbotch + + /* Restore the signal mask. */ + stmfd sp!, {r0-r2, r14} + mov r2, #0x00000000 + add r1, r0, #(_JB_SIGMASK * 4) /* Signal mask */ + mov r0, #3 /* SIG_SETMASK */ + bl PIC_SYM(_C_LABEL(sigprocmask), PLT) + ldmfd sp!, {r0-r2, r14} + +#if !defined(SOFTFLOAT_FOR_GCC) + add ip, r0, #(_JB_REG_D8 * 4) + vldmia ip, {d8-d15} + ldr ip, [r0, #(_JB_REG_FPSCR * 4)] + vmsr fpscr, ip +#endif + + add r0, r0, #(_JB_REG_R4 * 4) + /* Restore integer registers */ +#ifndef __thumb__ + ldmia r0, {r4-r14} +#else + ldmia r0, {r4-r12} + ldr r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)] + ldr r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)] +#endif + + /* Validate sp and r14 */ + teq sp, #0 + it ne + teqne r14, #0 + it eq + beq .Lbotch + + /* Set return value */ + movs r0, r1 + it eq + moveq r0, #0x00000001 + RET + + /* validation failed, die die die. */ +.Lbotch: + bl PIC_SYM(_C_LABEL(longjmperror), PLT) + bl PIC_SYM(_C_LABEL(abort), PLT) +1: b 1b /* Cannot get here */ +END(__longjmp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/gen/signalcontext.c b/lib/libc/arm/gen/signalcontext.c new file mode 100644 index 000000000000..e66a08928355 --- /dev/null +++ b/lib/libc/arm/gen/signalcontext.c @@ -0,0 +1,77 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2004 Olivier Houchard + * 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/param.h> +#include <sys/signal.h> +#include <sys/ucontext.h> + +#include <machine/frame.h> +#include <machine/sigframe.h> + +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <signal.h> + +__weak_reference(__signalcontext, signalcontext); + +extern void _ctx_start(void); + +int +__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) +{ + struct sigframe *sfp; + __greg_t *gr = ucp->uc_mcontext.__gregs; + unsigned int *sp; + + sp = (unsigned int *)gr[_REG_SP]; + + sfp = (struct sigframe *)sp - 1; + + bzero(sfp, sizeof(*sfp)); + bcopy(ucp, &sfp->sf_uc, sizeof(*ucp)); + sfp->sf_si.si_signo = sig; + + gr[_REG_SP] = (__greg_t)sfp; + /* Wipe out frame pointer. */ + gr[_REG_FP] = 0; + /* Arrange for return via the trampoline code. */ + gr[_REG_PC] = (__greg_t)_ctx_start; + gr[_REG_R4] = (__greg_t)func; + gr[_REG_R5] = (__greg_t)ucp; + gr[_REG_R0] = (__greg_t)sig; + gr[_REG_R1] = (__greg_t)&sfp->sf_si; + gr[_REG_R2] = (__greg_t)&sfp->sf_uc; + + ucp->uc_link = &sfp->sf_uc; + sigdelset(&ucp->uc_sigmask, sig); + + return (0); +} diff --git a/lib/libc/arm/gen/sigsetjmp.S b/lib/libc/arm/gen/sigsetjmp.S new file mode 100644 index 000000000000..a4e2e974c945 --- /dev/null +++ b/lib/libc/arm/gen/sigsetjmp.S @@ -0,0 +1,68 @@ +/* $NetBSD: sigsetjmp.S,v 1.6 2013/04/19 16:50:22 matt Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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 <machine/setjmp.h> + +/* + * C library -- sigsetjmp, siglongjmp + * + * longjmp(a,v) + * will generate a "return(v)" from the last call to + * setjmp(a, m) + * by restoring registers from the stack. + * The previous signal state is restored. + */ + +ENTRY(sigsetjmp) + teq r1, #0 + beq PIC_SYM(_C_LABEL(_setjmp), PLT) + b PIC_SYM(_C_LABEL(setjmp), PLT) +END(sigsetjmp) + +.L_setjmp_magic: + .word _JB_MAGIC__SETJMP +WEAK_ALIAS(__siglongjmp, siglongjmp) + +ENTRY(siglongjmp) + ldr r2, .L_setjmp_magic /* load magic */ + ldr r3, [r0] /* get magic from jmp_buf */ + bic r3, r3, #(_JB_MAGIC__SETJMP ^ _JB_MAGIC__SETJMP_VFP) + /* ignore VFP-ness of magic */ + teq r2, r3 /* magic correct? */ + beq PIC_SYM(_C_LABEL(_longjmp), PLT) + b PIC_SYM(_C_LABEL(longjmp), PLT) +END(siglongjmp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/softfloat/arm-gcc.h b/lib/libc/arm/softfloat/arm-gcc.h new file mode 100644 index 000000000000..00ee99a5af3e --- /dev/null +++ b/lib/libc/arm/softfloat/arm-gcc.h @@ -0,0 +1,100 @@ +/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */ + +/* +------------------------------------------------------------------------------- +One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. +------------------------------------------------------------------------------- +*/ +#ifdef __ARMEB__ +#define BIGENDIAN +#else +#define LITTLEENDIAN +#endif + +/* +------------------------------------------------------------------------------- +The macro `BITS64' can be defined to indicate that 64-bit integer types are +supported by the compiler. +------------------------------------------------------------------------------- +*/ +#define BITS64 + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines the most convenient type that holds +integers of at least as many bits as specified. For example, `uint8' should +be the most convenient type that can hold unsigned integers of as many as +8 bits. The `flag' type must be able to hold either a 0 or 1. For most +implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed +to the same as `int'. +------------------------------------------------------------------------------- +*/ +typedef int flag; +typedef int uint8; +typedef int int8; +typedef int uint16; +typedef int int16; +typedef unsigned int uint32; +typedef signed int int32; +#ifdef BITS64 +typedef unsigned long long int uint64; +typedef signed long long int int64; +#endif + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines a type that holds integers +of _exactly_ the number of bits specified. For instance, for most +implementation of C, `bits16' and `sbits16' should be `typedef'ed to +`unsigned short int' and `signed short int' (or `short int'), respectively. +------------------------------------------------------------------------------- +*/ +typedef unsigned char bits8; +typedef signed char sbits8; +typedef unsigned short int bits16; +typedef signed short int sbits16; +typedef unsigned int bits32; +typedef signed int sbits32; +#ifdef BITS64 +typedef unsigned long long int bits64; +typedef signed long long int sbits64; +#endif + +#ifdef BITS64 +/* +------------------------------------------------------------------------------- +The `LIT64' macro takes as its argument a textual integer literal and +if necessary ``marks'' the literal as having a 64-bit integer type. +For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +appended with the letters `LL' standing for `long long', which is `gcc's +name for the 64-bit integer type. Some compilers may allow `LIT64' to be +defined as the identity macro: `#define LIT64( a ) a'. +------------------------------------------------------------------------------- +*/ +#define LIT64( a ) a##LL +#endif + +/* +------------------------------------------------------------------------------- +The macro `INLINE' can be used before functions that should be inlined. If +a compiler does not support explicit inlining, this macro should be defined +to be `static'. +------------------------------------------------------------------------------- +*/ +#define INLINE static __inline + +/* +------------------------------------------------------------------------------- +The ARM FPA is odd in that it stores doubles high-order word first, no matter +what the endianness of the CPU. VFP is sane. +------------------------------------------------------------------------------- +*/ +#if defined(SOFTFLOAT_FOR_GCC) +#if defined (__ARM_EABI__) || defined(__VFP_FP__) || defined(__ARMEB__) +#define FLOAT64_DEMANGLE(a) (a) +#define FLOAT64_MANGLE(a) (a) +#else +#define FLOAT64_DEMANGLE(a) ((((a) & 0xfffffffful) << 32) | ((a) >> 32)) +#define FLOAT64_MANGLE(a) FLOAT64_DEMANGLE(a) +#endif +#endif diff --git a/lib/libc/arm/softfloat/milieu.h b/lib/libc/arm/softfloat/milieu.h new file mode 100644 index 000000000000..a3f829c4281b --- /dev/null +++ b/lib/libc/arm/softfloat/milieu.h @@ -0,0 +1,48 @@ +/* $NetBSD: milieu.h,v 1.1 2000/12/29 20:13:54 bjh21 Exp $ */ + +/* +=============================================================================== + +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Include common integer types and flags. +------------------------------------------------------------------------------- +*/ +#include "arm-gcc.h" + +/* +------------------------------------------------------------------------------- +Symbolic Boolean literals. +------------------------------------------------------------------------------- +*/ +enum { + FALSE = 0, + TRUE = 1 +}; diff --git a/lib/libc/arm/softfloat/softfloat.h b/lib/libc/arm/softfloat/softfloat.h new file mode 100644 index 000000000000..d202a1f7f420 --- /dev/null +++ b/lib/libc/arm/softfloat/softfloat.h @@ -0,0 +1,314 @@ +/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */ + +/* This is a derivative work. */ + +/* +=============================================================================== + +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +The macro `FLOATX80' must be defined to enable the extended double-precision +floating-point format `floatx80'. If this macro is not defined, the +`floatx80' type will not be defined, and none of the functions that either +input or output the `floatx80' type will be defined. The same applies to +the `FLOAT128' macro and the quadruple-precision format `float128'. +------------------------------------------------------------------------------- +*/ +/* #define FLOATX80 */ +/* #define FLOAT128 */ + +#include <fenv.h> + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point types. +------------------------------------------------------------------------------- +*/ +typedef unsigned int float32; +typedef unsigned long long float64; +#ifdef FLOATX80 +typedef struct { + unsigned short high; + unsigned long long low; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + unsigned long long high, low; +} float128; +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point underflow tininess-detection mode. +------------------------------------------------------------------------------- +*/ +#ifndef SOFTFLOAT_FOR_GCC +extern int float_detect_tininess; +#endif +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point rounding mode. +------------------------------------------------------------------------------- +*/ +extern int float_rounding_mode; +enum { + float_round_nearest_even = FE_TONEAREST, + float_round_to_zero = FE_TOWARDZERO, + float_round_down = FE_DOWNWARD, + float_round_up = FE_UPWARD +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point exception flags. +------------------------------------------------------------------------------- +*/ +extern int float_exception_flags; +extern int float_exception_mask; +enum { + float_flag_inexact = FE_INEXACT, + float_flag_underflow = FE_UNDERFLOW, + float_flag_overflow = FE_OVERFLOW, + float_flag_divbyzero = FE_DIVBYZERO, + float_flag_invalid = FE_INVALID +}; + +/* +------------------------------------------------------------------------------- +Routine to raise any or all of the software IEC/IEEE floating-point +exception flags. +------------------------------------------------------------------------------- +*/ +void float_raise( int ); + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE integer-to-floating-point conversion routines. +------------------------------------------------------------------------------- +*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */ +float32 int64_to_float32( long long ); +float64 int64_to_float64( long long ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( long long ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( long long ); +#endif +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS) +unsigned int float32_to_uint32_round_to_zero( float32 ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +long long float32_to_int64( float32 ); +long long float32_to_int64_round_to_zero( float32 ); +#endif +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision operations. +------------------------------------------------------------------------------- +*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +int float32_eq( float32, float32 ); +int float32_le( float32, float32 ); +int float32_lt( float32, float32 ); +int float32_eq_signaling( float32, float32 ); +int float32_le_quiet( float32, float32 ); +int float32_lt_quiet( float32, float32 ); +#ifndef SOFTFLOAT_FOR_GCC +int float32_is_signaling_nan( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS) +unsigned int float64_to_uint32_round_to_zero( float64 ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +long long float64_to_int64( float64 ); +long long float64_to_int64_round_to_zero( float64 ); +#endif +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision operations. +------------------------------------------------------------------------------- +*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +int float64_eq( float64, float64 ); +int float64_le( float64, float64 ); +int float64_lt( float64, float64 ); +int float64_eq_signaling( float64, float64 ); +int float64_le_quiet( float64, float64 ); +int float64_lt_quiet( float64, float64 ); +#ifndef SOFTFLOAT_FOR_GCC +int float64_is_signaling_nan( float64 ); +#endif + +#ifdef FLOATX80 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +long long floatx80_to_int64( floatx80 ); +long long floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision rounding precision. Valid +values are 32, 64, and 80. +------------------------------------------------------------------------------- +*/ +extern int floatx80_rounding_precision; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision operations. +------------------------------------------------------------------------------- +*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +int floatx80_eq( floatx80, floatx80 ); +int floatx80_le( floatx80, floatx80 ); +int floatx80_lt( floatx80, floatx80 ); +int floatx80_eq_signaling( floatx80, floatx80 ); +int floatx80_le_quiet( floatx80, floatx80 ); +int floatx80_lt_quiet( floatx80, floatx80 ); +int floatx80_is_signaling_nan( floatx80 ); + +#endif + +#ifdef FLOAT128 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +long long float128_to_int64( float128 ); +long long float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision operations. +------------------------------------------------------------------------------- +*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +int float128_eq( float128, float128 ); +int float128_le( float128, float128 ); +int float128_lt( float128, float128 ); +int float128_eq_signaling( float128, float128 ); +int float128_le_quiet( float128, float128 ); +int float128_lt_quiet( float128, float128 ); +int float128_is_signaling_nan( float128 ); + +#endif + diff --git a/lib/libc/arm/string/Makefile.inc b/lib/libc/arm/string/Makefile.inc new file mode 100644 index 000000000000..fc886645b0c8 --- /dev/null +++ b/lib/libc/arm/string/Makefile.inc @@ -0,0 +1,10 @@ +MDSRCS+= \ + bcopy.S \ + bzero.S \ + memcmp.S \ + memcpy.S \ + memmove.S \ + memset.S \ + strcmp.S \ + strlen.S \ + strncmp.S diff --git a/lib/libc/arm/string/bcopy.S b/lib/libc/arm/string/bcopy.S new file mode 100644 index 000000000000..dbe9efc06194 --- /dev/null +++ b/lib/libc/arm/string/bcopy.S @@ -0,0 +1,5 @@ +/* $NetBSD: bcopy.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */ + +#include <machine/asm.h> +#define _BCOPY +#include "memmove.S" diff --git a/lib/libc/arm/string/bzero.S b/lib/libc/arm/string/bzero.S new file mode 100644 index 000000000000..db524c3529ad --- /dev/null +++ b/lib/libc/arm/string/bzero.S @@ -0,0 +1,34 @@ +/* $NetBSD: bzero.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _BZERO +#include "memset.S" diff --git a/lib/libc/arm/string/memcmp.S b/lib/libc/arm/string/memcmp.S new file mode 100644 index 000000000000..2dbb1831c724 --- /dev/null +++ b/lib/libc/arm/string/memcmp.S @@ -0,0 +1,182 @@ +/* $NetBSD: memcmp.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/* + * Copyright (c) 2002 ARM Ltd + * 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. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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> +.syntax unified + +ENTRY(memcmp) + mov ip, r0 +#if defined(_KERNEL) && !defined(_STANDALONE) + cmp r2, #0x06 + beq .Lmemcmp_6bytes +#endif + mov r0, #0x00 + + /* Are both addresses aligned the same way? */ + cmp r2, #0x00 + eorsne r3, ip, r1 + RETeq /* len == 0, or same addresses! */ + tst r3, #0x03 + subne r2, r2, #0x01 + bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */ + + /* Word-align the addresses, if necessary */ + sub r3, r1, #0x05 + ands r3, r3, #0x03 + add r3, r3, r3, lsl #1 + addne pc, pc, r3, lsl #3 + nop + + /* Compare up to 3 bytes */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + RETne + subs r2, r2, #0x01 + RETeq + + /* Compare up to 2 bytes */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + RETne + subs r2, r2, #0x01 + RETeq + + /* Compare 1 byte */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + RETne + subs r2, r2, #0x01 + RETeq + + /* Compare 4 bytes at a time, if possible */ + subs r2, r2, #0x04 + bcc .Lmemcmp_bytewise +.Lmemcmp_word_aligned: + ldr r0, [ip], #0x04 + ldr r3, [r1], #0x04 + subs r2, r2, #0x04 + cmpcs r0, r3 + beq .Lmemcmp_word_aligned + sub r0, r0, r3 + + /* Correct for extra subtraction, and check if done */ + adds r2, r2, #0x04 + cmpeq r0, #0x00 /* If done, did all bytes match? */ + RETeq /* Yup. Just return */ + + /* Re-do the final word byte-wise */ + sub ip, ip, #0x04 + sub r1, r1, #0x04 + +.Lmemcmp_bytewise: + add r2, r2, #0x03 +.Lmemcmp_bytewise2: + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r2, r2, #0x01 + cmpcs r0, r3 + beq .Lmemcmp_bytewise2 + sub r0, r0, r3 + RET + +#if defined(_KERNEL) && !defined(_STANDALONE) + /* + * 6 byte compares are very common, thanks to the network stack. + * This code is hand-scheduled to reduce the number of stalls for + * load results. Everything else being equal, this will be ~32% + * faster than a byte-wise memcmp. + */ + .align 5 +.Lmemcmp_6bytes: + ldrb r3, [r1, #0x00] /* r3 = b2#0 */ + ldrb r0, [ip, #0x00] /* r0 = b1#0 */ + ldrb r2, [r1, #0x01] /* r2 = b2#1 */ + subs r0, r0, r3 /* r0 = b1#0 - b2#0 */ + ldreqb r3, [ip, #0x01] /* r3 = b1#1 */ + RETne /* Return if mismatch on #0 */ + subs r0, r3, r2 /* r0 = b1#1 - b2#1 */ + ldreqb r3, [r1, #0x02] /* r3 = b2#2 */ + ldreqb r0, [ip, #0x02] /* r0 = b1#2 */ + RETne /* Return if mismatch on #1 */ + ldrb r2, [r1, #0x03] /* r2 = b2#3 */ + subs r0, r0, r3 /* r0 = b1#2 - b2#2 */ + ldreqb r3, [ip, #0x03] /* r3 = b1#3 */ + RETne /* Return if mismatch on #2 */ + subs r0, r3, r2 /* r0 = b1#3 - b2#3 */ + ldreqb r3, [r1, #0x04] /* r3 = b2#4 */ + ldreqb r0, [ip, #0x04] /* r0 = b1#4 */ + RETne /* Return if mismatch on #3 */ + ldrb r2, [r1, #0x05] /* r2 = b2#5 */ + subs r0, r0, r3 /* r0 = b1#4 - b2#4 */ + ldreqb r3, [ip, #0x05] /* r3 = b1#5 */ + RETne /* Return if mismatch on #4 */ + sub r0, r3, r2 /* r0 = b1#5 - b2#5 */ + RET +#endif +END(memcmp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/memcpy.S b/lib/libc/arm/string/memcpy.S new file mode 100644 index 000000000000..6ea7bec7e9cc --- /dev/null +++ b/lib/libc/arm/string/memcpy.S @@ -0,0 +1,1373 @@ +/* $NetBSD: memcpy_xscale.S,v 1.1 2003/10/14 07:51:45 scw Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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> +.syntax unified + +/* LINTSTUB: Func: void *memcpy(void *dst, const void *src, size_t len) */ +ENTRY(memcpy) + pld [r1] + cmp r2, #0x0c + ble .Lmemcpy_short /* <= 12 bytes */ + mov r3, r0 /* We must not clobber r0 */ + + /* Word-align the destination buffer */ + ands ip, r3, #0x03 /* Already word aligned? */ + beq .Lmemcpy_wordaligned /* Yup */ + cmp ip, #0x02 + ldrb ip, [r1], #0x01 + sub r2, r2, #0x01 + strb ip, [r3], #0x01 + ldrble ip, [r1], #0x01 + suble r2, r2, #0x01 + strble ip, [r3], #0x01 + ldrblt ip, [r1], #0x01 + sublt r2, r2, #0x01 + strblt ip, [r3], #0x01 + + /* Destination buffer is now word aligned */ +.Lmemcpy_wordaligned: + ands ip, r1, #0x03 /* Is src also word-aligned? */ + bne .Lmemcpy_bad_align /* Nope. Things just got bad */ + + /* Quad-align the destination buffer */ + tst r3, #0x07 /* Already quad aligned? */ + ldrne ip, [r1], #0x04 + stmfd sp!, {r4-r9} /* Free up some registers */ + subne r2, r2, #0x04 + strne ip, [r3], #0x04 + + /* Destination buffer quad aligned, source is at least word aligned */ + subs r2, r2, #0x80 + blt .Lmemcpy_w_lessthan128 + + /* Copy 128 bytes at a time */ +.Lmemcpy_w_loop128: + ldr r4, [r1], #0x04 /* LD:00-03 */ + ldr r5, [r1], #0x04 /* LD:04-07 */ + pld [r1, #0x18] /* Prefetch 0x20 */ + ldr r6, [r1], #0x04 /* LD:08-0b */ + ldr r7, [r1], #0x04 /* LD:0c-0f */ + ldr r8, [r1], #0x04 /* LD:10-13 */ + ldr r9, [r1], #0x04 /* LD:14-17 */ + strd r4, [r3], #0x08 /* ST:00-07 */ + ldr r4, [r1], #0x04 /* LD:18-1b */ + ldr r5, [r1], #0x04 /* LD:1c-1f */ + strd r6, [r3], #0x08 /* ST:08-0f */ + ldr r6, [r1], #0x04 /* LD:20-23 */ + ldr r7, [r1], #0x04 /* LD:24-27 */ + pld [r1, #0x18] /* Prefetch 0x40 */ + strd r8, [r3], #0x08 /* ST:10-17 */ + ldr r8, [r1], #0x04 /* LD:28-2b */ + ldr r9, [r1], #0x04 /* LD:2c-2f */ + strd r4, [r3], #0x08 /* ST:18-1f */ + ldr r4, [r1], #0x04 /* LD:30-33 */ + ldr r5, [r1], #0x04 /* LD:34-37 */ + strd r6, [r3], #0x08 /* ST:20-27 */ + ldr r6, [r1], #0x04 /* LD:38-3b */ + ldr r7, [r1], #0x04 /* LD:3c-3f */ + strd r8, [r3], #0x08 /* ST:28-2f */ + ldr r8, [r1], #0x04 /* LD:40-43 */ + ldr r9, [r1], #0x04 /* LD:44-47 */ + pld [r1, #0x18] /* Prefetch 0x60 */ + strd r4, [r3], #0x08 /* ST:30-37 */ + ldr r4, [r1], #0x04 /* LD:48-4b */ + ldr r5, [r1], #0x04 /* LD:4c-4f */ + strd r6, [r3], #0x08 /* ST:38-3f */ + ldr r6, [r1], #0x04 /* LD:50-53 */ + ldr r7, [r1], #0x04 /* LD:54-57 */ + strd r8, [r3], #0x08 /* ST:40-47 */ + ldr r8, [r1], #0x04 /* LD:58-5b */ + ldr r9, [r1], #0x04 /* LD:5c-5f */ + strd r4, [r3], #0x08 /* ST:48-4f */ + ldr r4, [r1], #0x04 /* LD:60-63 */ + ldr r5, [r1], #0x04 /* LD:64-67 */ + pld [r1, #0x18] /* Prefetch 0x80 */ + strd r6, [r3], #0x08 /* ST:50-57 */ + ldr r6, [r1], #0x04 /* LD:68-6b */ + ldr r7, [r1], #0x04 /* LD:6c-6f */ + strd r8, [r3], #0x08 /* ST:58-5f */ + ldr r8, [r1], #0x04 /* LD:70-73 */ + ldr r9, [r1], #0x04 /* LD:74-77 */ + strd r4, [r3], #0x08 /* ST:60-67 */ + ldr r4, [r1], #0x04 /* LD:78-7b */ + ldr r5, [r1], #0x04 /* LD:7c-7f */ + strd r6, [r3], #0x08 /* ST:68-6f */ + strd r8, [r3], #0x08 /* ST:70-77 */ + subs r2, r2, #0x80 + strd r4, [r3], #0x08 /* ST:78-7f */ + bge .Lmemcpy_w_loop128 + +.Lmemcpy_w_lessthan128: + adds r2, r2, #0x80 /* Adjust for extra sub */ + ldmfdeq sp!, {r4-r9} + bxeq lr /* Return now if done */ + subs r2, r2, #0x20 + blt .Lmemcpy_w_lessthan32 + + /* Copy 32 bytes at a time */ +.Lmemcpy_w_loop32: + ldr r4, [r1], #0x04 + ldr r5, [r1], #0x04 + pld [r1, #0x18] + ldr r6, [r1], #0x04 + ldr r7, [r1], #0x04 + ldr r8, [r1], #0x04 + ldr r9, [r1], #0x04 + strd r4, [r3], #0x08 + ldr r4, [r1], #0x04 + ldr r5, [r1], #0x04 + strd r6, [r3], #0x08 + strd r8, [r3], #0x08 + subs r2, r2, #0x20 + strd r4, [r3], #0x08 + bge .Lmemcpy_w_loop32 + +.Lmemcpy_w_lessthan32: + adds r2, r2, #0x20 /* Adjust for extra sub */ + ldmfdeq sp!, {r4-r9} + bxeq lr /* Return now if done */ + + and r4, r2, #0x18 + rsbs r4, r4, #0x18 + addne pc, pc, r4, lsl #1 + nop + + /* At least 24 bytes remaining */ + ldr r4, [r1], #0x04 + ldr r5, [r1], #0x04 + sub r2, r2, #0x08 + strd r4, [r3], #0x08 + + /* At least 16 bytes remaining */ + ldr r4, [r1], #0x04 + ldr r5, [r1], #0x04 + sub r2, r2, #0x08 + strd r4, [r3], #0x08 + + /* At least 8 bytes remaining */ + ldr r4, [r1], #0x04 + ldr r5, [r1], #0x04 + subs r2, r2, #0x08 + strd r4, [r3], #0x08 + + /* Less than 8 bytes remaining */ + ldmfd sp!, {r4-r9} + bxeq lr /* Return now if done */ + subs r2, r2, #0x04 + ldrge ip, [r1], #0x04 + strge ip, [r3], #0x04 + bxeq lr /* Return now if done */ + addlt r2, r2, #0x04 + ldrb ip, [r1], #0x01 + cmp r2, #0x02 + ldrbge r2, [r1], #0x01 + strb ip, [r3], #0x01 + ldrbgt ip, [r1] + strbge r2, [r3], #0x01 + strbgt ip, [r3] + bx lr + + +/* + * At this point, it has not been possible to word align both buffers. + * The destination buffer is word aligned, but the source buffer is not. + */ +.Lmemcpy_bad_align: + stmfd sp!, {r4-r7} + bic r1, r1, #0x03 + cmp ip, #2 + ldr ip, [r1], #0x04 + bgt .Lmemcpy_bad3 + beq .Lmemcpy_bad2 + b .Lmemcpy_bad1 + +.Lmemcpy_bad1_loop16: + mov r4, ip, lsr #8 + ldr r5, [r1], #0x04 + pld [r1, #0x018] + ldr r6, [r1], #0x04 + ldr r7, [r1], #0x04 + ldr ip, [r1], #0x04 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + mov r7, r7, lsr #8 + orr r7, r7, ip, lsl #24 + str r4, [r3], #0x04 + str r5, [r3], #0x04 + str r6, [r3], #0x04 + str r7, [r3], #0x04 +.Lmemcpy_bad1: + subs r2, r2, #0x10 + bge .Lmemcpy_bad1_loop16 + + adds r2, r2, #0x10 + ldmfdeq sp!, {r4-r7} + bxeq lr /* Return now if done */ + subs r2, r2, #0x04 + sublt r1, r1, #0x03 + blt .Lmemcpy_bad_done + +.Lmemcpy_bad1_loop4: + mov r4, ip, lsr #8 + ldr ip, [r1], #0x04 + subs r2, r2, #0x04 + orr r4, r4, ip, lsl #24 + str r4, [r3], #0x04 + bge .Lmemcpy_bad1_loop4 + sub r1, r1, #0x03 + b .Lmemcpy_bad_done + +.Lmemcpy_bad2_loop16: + mov r4, ip, lsr #16 + ldr r5, [r1], #0x04 + pld [r1, #0x018] + ldr r6, [r1], #0x04 + ldr r7, [r1], #0x04 + ldr ip, [r1], #0x04 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + mov r7, r7, lsr #16 + orr r7, r7, ip, lsl #16 + str r4, [r3], #0x04 + str r5, [r3], #0x04 + str r6, [r3], #0x04 + str r7, [r3], #0x04 +.Lmemcpy_bad2: + subs r2, r2, #0x10 + bge .Lmemcpy_bad2_loop16 + + adds r2, r2, #0x10 + ldmfdeq sp!, {r4-r7} + bxeq lr /* Return now if done */ + subs r2, r2, #0x04 + sublt r1, r1, #0x02 + blt .Lmemcpy_bad_done + +.Lmemcpy_bad2_loop4: + mov r4, ip, lsr #16 + ldr ip, [r1], #0x04 + subs r2, r2, #0x04 + orr r4, r4, ip, lsl #16 + str r4, [r3], #0x04 + bge .Lmemcpy_bad2_loop4 + sub r1, r1, #0x02 + b .Lmemcpy_bad_done + +.Lmemcpy_bad3_loop16: + mov r4, ip, lsr #24 + ldr r5, [r1], #0x04 + pld [r1, #0x018] + ldr r6, [r1], #0x04 + ldr r7, [r1], #0x04 + ldr ip, [r1], #0x04 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + mov r7, r7, lsr #24 + orr r7, r7, ip, lsl #8 + str r4, [r3], #0x04 + str r5, [r3], #0x04 + str r6, [r3], #0x04 + str r7, [r3], #0x04 +.Lmemcpy_bad3: + subs r2, r2, #0x10 + bge .Lmemcpy_bad3_loop16 + + adds r2, r2, #0x10 + ldmfdeq sp!, {r4-r7} + bxeq lr /* Return now if done */ + subs r2, r2, #0x04 + sublt r1, r1, #0x01 + blt .Lmemcpy_bad_done + +.Lmemcpy_bad3_loop4: + mov r4, ip, lsr #24 + ldr ip, [r1], #0x04 + subs r2, r2, #0x04 + orr r4, r4, ip, lsl #8 + str r4, [r3], #0x04 + bge .Lmemcpy_bad3_loop4 + sub r1, r1, #0x01 + +.Lmemcpy_bad_done: + ldmfd sp!, {r4-r7} + adds r2, r2, #0x04 + bxeq lr + ldrb ip, [r1], #0x01 + cmp r2, #0x02 + ldrbge r2, [r1], #0x01 + strb ip, [r3], #0x01 + ldrbgt ip, [r1] + strbge r2, [r3], #0x01 + strbgt ip, [r3] + bx lr + + +/* + * Handle short copies (less than 16 bytes), possibly misaligned. + * Some of these are *very* common, thanks to the network stack, + * and so are handled specially. + */ +.Lmemcpy_short: +#ifndef _STANDALONE + add pc, pc, r2, lsl #2 + nop + bx lr /* 0x00 */ + b .Lmemcpy_bytewise /* 0x01 */ + b .Lmemcpy_bytewise /* 0x02 */ + b .Lmemcpy_bytewise /* 0x03 */ + b .Lmemcpy_4 /* 0x04 */ + b .Lmemcpy_bytewise /* 0x05 */ + b .Lmemcpy_6 /* 0x06 */ + b .Lmemcpy_bytewise /* 0x07 */ + b .Lmemcpy_8 /* 0x08 */ + b .Lmemcpy_bytewise /* 0x09 */ + b .Lmemcpy_bytewise /* 0x0a */ + b .Lmemcpy_bytewise /* 0x0b */ + b .Lmemcpy_c /* 0x0c */ +#endif +.Lmemcpy_bytewise: + mov r3, r0 /* We must not clobber r0 */ + ldrb ip, [r1], #0x01 +1: subs r2, r2, #0x01 + strb ip, [r3], #0x01 + ldrbne ip, [r1], #0x01 + bne 1b + bx lr + +#ifndef _STANDALONE +/****************************************************************************** + * Special case for 4 byte copies + */ +#define LMEMCPY_4_LOG2 6 /* 64 bytes */ +#define LMEMCPY_4_PAD .align LMEMCPY_4_LOG2 + LMEMCPY_4_PAD +.Lmemcpy_4: + and r2, r1, #0x03 + orr r2, r2, r0, lsl #2 + ands r2, r2, #0x0f + sub r3, pc, #0x14 + addne pc, r3, r2, lsl #LMEMCPY_4_LOG2 + +/* + * 0000: dst is 32-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + str r2, [r0] + bx lr + LMEMCPY_4_PAD + +/* + * 0001: dst is 32-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */ + ldr r2, [r1, #3] /* BE:r2 = 3xxx LE:r2 = xxx3 */ + mov r3, r3, lsr #8 /* r3 = .210 */ + orr r3, r3, r2, lsl #24 /* r3 = 3210 */ + str r3, [r0] + bx lr + LMEMCPY_4_PAD + +/* + * 0010: dst is 32-bit aligned, src is 16-bit aligned + */ + ldrh r3, [r1, #0x02] + ldrh r2, [r1] + orr r3, r2, r3, lsl #16 + str r3, [r0] + bx lr + LMEMCPY_4_PAD + +/* + * 0011: dst is 32-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #-3] /* BE:r3 = xxx0 LE:r3 = 0xxx */ + ldr r2, [r1, #1] /* BE:r2 = 123x LE:r2 = x321 */ + mov r3, r3, lsr #24 /* r3 = ...0 */ + orr r3, r3, r2, lsl #8 /* r3 = 3210 */ + str r3, [r0] + bx lr + LMEMCPY_4_PAD + +/* + * 0100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + strb r2, [r0] + mov r3, r2, lsr #8 + mov r1, r2, lsr #24 + strb r1, [r0, #0x03] + strh r3, [r0, #0x01] + bx lr + LMEMCPY_4_PAD + +/* + * 0101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrb r1, [r1, #0x03] + strb r2, [r0] + strh r3, [r0, #0x01] + strb r1, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 0110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldrh r3, [r1, #0x02] /* LE:r3 = ..23 LE:r3 = ..32 */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = ...1 */ + orr r2, r2, r3, lsl #8 /* r2 = .321 */ + mov r3, r3, lsr #8 /* r3 = ...3 */ + strh r2, [r0, #0x01] + strb r3, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 0111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrb r1, [r1, #0x03] + strb r2, [r0] + strh r3, [r0, #0x01] + strb r1, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 1000: dst is 16-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + strh r2, [r0] + mov r3, r2, lsr #16 + strh r3, [r0, #0x02] + bx lr + LMEMCPY_4_PAD + +/* + * 1001: dst is 16-bit aligned, src is 8-bit aligned + */ + ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */ + ldr r3, [r1, #3] /* BE:r3 = 3xxx LE:r3 = xxx3 */ + mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */ + strh r1, [r0] + mov r2, r2, lsr #24 /* r2 = ...2 */ + orr r2, r2, r3, lsl #8 /* r2 = xx32 */ + strh r2, [r0, #0x02] + bx lr + LMEMCPY_4_PAD + +/* + * 1010: dst is 16-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] + ldrh r3, [r1, #0x02] + strh r2, [r0] + strh r3, [r0, #0x02] + bx lr + LMEMCPY_4_PAD + +/* + * 1011: dst is 16-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #1] /* BE:r3 = 123x LE:r3 = x321 */ + ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */ + mov r1, r3, lsr #8 /* BE:r1 = .123 LE:r1 = .x32 */ + strh r1, [r0, #0x02] + mov r3, r3, lsl #8 /* r3 = 321. */ + orr r3, r3, r2, lsr #24 /* r3 = 3210 */ + strh r3, [r0] + bx lr + LMEMCPY_4_PAD + +/* + * 1100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + strb r2, [r0] + mov r3, r2, lsr #8 + mov r1, r2, lsr #24 + strh r3, [r0, #0x01] + strb r1, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 1101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrb r1, [r1, #0x03] + strb r2, [r0] + strh r3, [r0, #0x01] + strb r1, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 1110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldrh r3, [r1, #0x02] /* BE:r3 = ..23 LE:r3 = ..32 */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = ...1 */ + orr r2, r2, r3, lsl #8 /* r2 = .321 */ + strh r2, [r0, #0x01] + mov r3, r3, lsr #8 /* r3 = ...3 */ + strb r3, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + +/* + * 1111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrb r1, [r1, #0x03] + strb r2, [r0] + strh r3, [r0, #0x01] + strb r1, [r0, #0x03] + bx lr + LMEMCPY_4_PAD + + +/****************************************************************************** + * Special case for 6 byte copies + */ +#define LMEMCPY_6_LOG2 6 /* 64 bytes */ +#define LMEMCPY_6_PAD .align LMEMCPY_6_LOG2 + LMEMCPY_6_PAD +.Lmemcpy_6: + and r2, r1, #0x03 + orr r2, r2, r0, lsl #2 + ands r2, r2, #0x0f + sub r3, pc, #0x14 + addne pc, r3, r2, lsl #LMEMCPY_6_LOG2 + +/* + * 0000: dst is 32-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + ldrh r3, [r1, #0x04] + str r2, [r0] + strh r3, [r0, #0x04] + bx lr + LMEMCPY_6_PAD + +/* + * 0001: dst is 32-bit aligned, src is 8-bit aligned + */ + ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */ + ldr r3, [r1, #0x03] /* BE:r3 = 345x LE:r3 = x543 */ + mov r2, r2, lsr #8 /* r2 = .210 */ + orr r2, r2, r3, lsl #24 /* r2 = 3210 */ + mov r3, r3, lsr #8 /* BE:r3 = .345 LE:r3 = .x54 */ + str r2, [r0] + strh r3, [r0, #0x04] + bx lr + LMEMCPY_6_PAD + +/* + * 0010: dst is 32-bit aligned, src is 16-bit aligned + */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + mov r1, r3, lsr #16 /* r1 = ..54 */ + orr r2, r2, r3, lsl #16 /* r2 = 3210 */ + str r2, [r0] + strh r1, [r0, #0x04] + bx lr + LMEMCPY_6_PAD + +/* + * 0011: dst is 32-bit aligned, src is 8-bit aligned + */ + ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */ + ldr r3, [r1, #1] /* BE:r3 = 1234 LE:r3 = 4321 */ + ldr r1, [r1, #5] /* BE:r1 = 5xxx LE:r3 = xxx5 */ + mov r2, r2, lsr #24 /* r2 = ...0 */ + orr r2, r2, r3, lsl #8 /* r2 = 3210 */ + mov r1, r1, lsl #8 /* r1 = xx5. */ + orr r1, r1, r3, lsr #24 /* r1 = xx54 */ + str r2, [r0] + strh r1, [r0, #0x04] + bx lr + LMEMCPY_6_PAD + +/* + * 0100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */ + ldrh r2, [r1, #0x04] /* BE:r2 = ..45 LE:r2 = ..54 */ + mov r1, r3, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */ + strh r1, [r0, #0x01] + strb r3, [r0] + mov r3, r3, lsr #24 /* r3 = ...3 */ + orr r3, r3, r2, lsl #8 /* r3 = .543 */ + mov r2, r2, lsr #8 /* r2 = ...5 */ + strh r3, [r0, #0x03] + strb r2, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 0101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrh ip, [r1, #0x03] + ldrb r1, [r1, #0x05] + strb r2, [r0] + strh r3, [r0, #0x01] + strh ip, [r0, #0x03] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 0110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */ + strb r2, [r0] + mov r3, r1, lsr #24 + strb r3, [r0, #0x05] + mov r3, r1, lsr #8 /* r3 = .543 */ + strh r3, [r0, #0x03] + mov r3, r2, lsr #8 /* r3 = ...1 */ + orr r3, r3, r1, lsl #8 /* r3 = 4321 */ + strh r3, [r0, #0x01] + bx lr + LMEMCPY_6_PAD + +/* + * 0111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrh ip, [r1, #0x03] + ldrb r1, [r1, #0x05] + strb r2, [r0] + strh r3, [r0, #0x01] + strh ip, [r0, #0x03] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 1000: dst is 16-bit aligned, src is 32-bit aligned + */ + ldrh r2, [r1, #0x04] /* r2 = ..54 */ + ldr r3, [r1] /* r3 = 3210 */ + mov r2, r2, lsl #16 /* r2 = 54.. */ + orr r2, r2, r3, lsr #16 /* r2 = 5432 */ + strh r3, [r0] + str r2, [r0, #0x02] + bx lr + LMEMCPY_6_PAD + +/* + * 1001: dst is 16-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */ + ldr r2, [r1, #3] /* BE:r2 = 345x LE:r2 = x543 */ + mov r1, r3, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */ + mov r2, r2, lsl #8 /* r2 = 543. */ + orr r2, r2, r3, lsr #24 /* r2 = 5432 */ + strh r1, [r0] + str r2, [r0, #0x02] + bx lr + LMEMCPY_6_PAD + +/* + * 1010: dst is 16-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] + ldr r3, [r1, #0x02] + strh r2, [r0] + str r3, [r0, #0x02] + bx lr + LMEMCPY_6_PAD + +/* + * 1011: dst is 16-bit aligned, src is 8-bit aligned + */ + ldrb r3, [r1] /* r3 = ...0 */ + ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */ + ldrb r1, [r1, #0x05] /* r1 = ...5 */ + orr r3, r3, r2, lsl #8 /* r3 = 3210 */ + mov r1, r1, lsl #24 /* r1 = 5... */ + orr r1, r1, r2, lsr #8 /* r1 = 5432 */ + strh r3, [r0] + str r1, [r0, #0x02] + bx lr + LMEMCPY_6_PAD + +/* + * 1100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + ldrh r1, [r1, #0x04] /* BE:r1 = ..45 LE:r1 = ..54 */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = .321 */ + orr r2, r2, r1, lsl #24 /* r2 = 4321 */ + mov r1, r1, lsr #8 /* r1 = ...5 */ + str r2, [r0, #0x01] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 1101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldrh ip, [r1, #0x03] + ldrb r1, [r1, #0x05] + strb r2, [r0] + strh r3, [r0, #0x01] + strh ip, [r0, #0x03] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 1110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = ...1 */ + orr r2, r2, r1, lsl #8 /* r2 = 4321 */ + mov r1, r1, lsr #24 /* r1 = ...5 */ + str r2, [r0, #0x01] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + +/* + * 1111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldr r3, [r1, #0x01] + ldrb r1, [r1, #0x05] + strb r2, [r0] + str r3, [r0, #0x01] + strb r1, [r0, #0x05] + bx lr + LMEMCPY_6_PAD + + +/****************************************************************************** + * Special case for 8 byte copies + */ +#define LMEMCPY_8_LOG2 6 /* 64 bytes */ +#define LMEMCPY_8_PAD .align LMEMCPY_8_LOG2 + LMEMCPY_8_PAD +.Lmemcpy_8: + and r2, r1, #0x03 + orr r2, r2, r0, lsl #2 + ands r2, r2, #0x0f + sub r3, pc, #0x14 + addne pc, r3, r2, lsl #LMEMCPY_8_LOG2 + +/* + * 0000: dst is 32-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + ldr r3, [r1, #0x04] + str r2, [r0] + str r3, [r0, #0x04] + bx lr + LMEMCPY_8_PAD + +/* + * 0001: dst is 32-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */ + ldr r2, [r1, #0x03] /* BE:r2 = 3456 LE:r2 = 6543 */ + ldrb r1, [r1, #0x07] /* r1 = ...7 */ + mov r3, r3, lsr #8 /* r3 = .210 */ + orr r3, r3, r2, lsl #24 /* r3 = 3210 */ + mov r1, r1, lsl #24 /* r1 = 7... */ + orr r2, r1, r2, lsr #8 /* r2 = 7654 */ + str r3, [r0] + str r2, [r0, #0x04] + bx lr + LMEMCPY_8_PAD + +/* + * 0010: dst is 32-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */ + orr r2, r2, r3, lsl #16 /* r2 = 3210 */ + mov r3, r3, lsr #16 /* r3 = ..54 */ + orr r3, r3, r1, lsl #16 /* r3 = 7654 */ + str r2, [r0] + str r3, [r0, #0x04] + bx lr + LMEMCPY_8_PAD + +/* + * 0011: dst is 32-bit aligned, src is 8-bit aligned + */ + ldrb r3, [r1] /* r3 = ...0 */ + ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */ + ldr r1, [r1, #0x05] /* BE:r1 = 567x LE:r1 = x765 */ + orr r3, r3, r2, lsl #8 /* r3 = 3210 */ + mov r2, r2, lsr #24 /* r2 = ...4 */ + orr r2, r2, r1, lsl #8 /* r2 = 7654 */ + str r3, [r0] + str r2, [r0, #0x04] + bx lr + LMEMCPY_8_PAD + +/* + * 0100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */ + ldr r2, [r1, #0x04] /* BE:r2 = 4567 LE:r2 = 7654 */ + strb r3, [r0] + mov r1, r2, lsr #24 /* r1 = ...7 */ + strb r1, [r0, #0x07] + mov r1, r3, lsr #8 /* r1 = .321 */ + mov r3, r3, lsr #24 /* r3 = ...3 */ + orr r3, r3, r2, lsl #8 /* r3 = 6543 */ + strh r1, [r0, #0x01] + str r3, [r0, #0x03] + bx lr + LMEMCPY_8_PAD + +/* + * 0101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldr ip, [r1, #0x03] + ldrb r1, [r1, #0x07] + strb r2, [r0] + strh r3, [r0, #0x01] + str ip, [r0, #0x03] + strb r1, [r0, #0x07] + bx lr + LMEMCPY_8_PAD + +/* + * 0110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */ + strb r2, [r0] /* 0 */ + mov ip, r1, lsr #8 /* ip = ...7 */ + strb ip, [r0, #0x07] /* 7 */ + mov ip, r2, lsr #8 /* ip = ...1 */ + orr ip, ip, r3, lsl #8 /* ip = 4321 */ + mov r3, r3, lsr #8 /* r3 = .543 */ + orr r3, r3, r1, lsl #24 /* r3 = 6543 */ + strh ip, [r0, #0x01] + str r3, [r0, #0x03] + bx lr + LMEMCPY_8_PAD + +/* + * 0111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r3, [r1] /* r3 = ...0 */ + ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */ + ldrh r2, [r1, #0x05] /* BE:r2 = ..56 LE:r2 = ..65 */ + ldrb r1, [r1, #0x07] /* r1 = ...7 */ + strb r3, [r0] + mov r3, ip, lsr #16 /* BE:r3 = ..12 LE:r3 = ..43 */ + strh ip, [r0, #0x01] + orr r2, r3, r2, lsl #16 /* r2 = 6543 */ + str r2, [r0, #0x03] + strb r1, [r0, #0x07] + bx lr + LMEMCPY_8_PAD + +/* + * 1000: dst is 16-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */ + mov r1, r2, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */ + strh r2, [r0] + orr r2, r1, r3, lsl #16 /* r2 = 5432 */ + mov r3, r3, lsr #16 /* r3 = ..76 */ + str r2, [r0, #0x02] + strh r3, [r0, #0x06] + bx lr + LMEMCPY_8_PAD + +/* + * 1001: dst is 16-bit aligned, src is 8-bit aligned + */ + ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */ + ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */ + ldrb ip, [r1, #0x07] /* ip = ...7 */ + mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */ + strh r1, [r0] + mov r1, r2, lsr #24 /* r1 = ...2 */ + orr r1, r1, r3, lsl #8 /* r1 = 5432 */ + mov r3, r3, lsr #24 /* r3 = ...6 */ + orr r3, r3, ip, lsl #8 /* r3 = ..76 */ + str r1, [r0, #0x02] + strh r3, [r0, #0x06] + bx lr + LMEMCPY_8_PAD + +/* + * 1010: dst is 16-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] + ldr ip, [r1, #0x02] + ldrh r3, [r1, #0x06] + strh r2, [r0] + str ip, [r0, #0x02] + strh r3, [r0, #0x06] + bx lr + LMEMCPY_8_PAD + +/* + * 1011: dst is 16-bit aligned, src is 8-bit aligned + */ + ldr r3, [r1, #0x05] /* BE:r3 = 567x LE:r3 = x765 */ + ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */ + ldrb ip, [r1] /* ip = ...0 */ + mov r1, r3, lsr #8 /* BE:r1 = .567 LE:r1 = .x76 */ + strh r1, [r0, #0x06] + mov r3, r3, lsl #24 /* r3 = 5... */ + orr r3, r3, r2, lsr #8 /* r3 = 5432 */ + orr r2, ip, r2, lsl #8 /* r2 = 3210 */ + str r3, [r0, #0x02] + strh r2, [r0] + bx lr + LMEMCPY_8_PAD + +/* + * 1100: dst is 8-bit aligned, src is 32-bit aligned + */ + ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + mov r1, r3, lsr #8 /* BE:r1 = .456 LE:r1 = .765 */ + strh r1, [r0, #0x05] + strb r2, [r0] + mov r1, r3, lsr #24 /* r1 = ...7 */ + strb r1, [r0, #0x07] + mov r2, r2, lsr #8 /* r2 = .321 */ + orr r2, r2, r3, lsl #24 /* r2 = 4321 */ + str r2, [r0, #0x01] + bx lr + LMEMCPY_8_PAD + +/* + * 1101: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r3, [r1] /* r3 = ...0 */ + ldrh r2, [r1, #0x01] /* BE:r2 = ..12 LE:r2 = ..21 */ + ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */ + ldrb r1, [r1, #0x07] /* r1 = ...7 */ + strb r3, [r0] + mov r3, ip, lsr #16 /* BE:r3 = ..34 LE:r3 = ..65 */ + strh r3, [r0, #0x05] + orr r2, r2, ip, lsl #16 /* r2 = 4321 */ + str r2, [r0, #0x01] + strb r1, [r0, #0x07] + bx lr + LMEMCPY_8_PAD + +/* + * 1110: dst is 8-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */ + strb r2, [r0] + mov ip, r2, lsr #8 /* ip = ...1 */ + orr ip, ip, r3, lsl #8 /* ip = 4321 */ + mov r2, r1, lsr #8 /* r2 = ...7 */ + strb r2, [r0, #0x07] + mov r1, r1, lsl #8 /* r1 = .76. */ + orr r1, r1, r3, lsr #24 /* r1 = .765 */ + str ip, [r0, #0x01] + strh r1, [r0, #0x05] + bx lr + LMEMCPY_8_PAD + +/* + * 1111: dst is 8-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] + ldr ip, [r1, #0x01] + ldrh r3, [r1, #0x05] + ldrb r1, [r1, #0x07] + strb r2, [r0] + str ip, [r0, #0x01] + strh r3, [r0, #0x05] + strb r1, [r0, #0x07] + bx lr + LMEMCPY_8_PAD + +/****************************************************************************** + * Special case for 12 byte copies + */ +#define LMEMCPY_C_LOG2 7 /* 128 bytes */ +#define LMEMCPY_C_PAD .align LMEMCPY_C_LOG2 + LMEMCPY_C_PAD +.Lmemcpy_c: + and r2, r1, #0x03 + orr r2, r2, r0, lsl #2 + ands r2, r2, #0x0f + sub r3, pc, #0x14 + addne pc, r3, r2, lsl #LMEMCPY_C_LOG2 + +/* + * 0000: dst is 32-bit aligned, src is 32-bit aligned + */ + ldr r2, [r1] + ldr r3, [r1, #0x04] + ldr r1, [r1, #0x08] + str r2, [r0] + str r3, [r0, #0x04] + str r1, [r0, #0x08] + bx lr + LMEMCPY_C_PAD + +/* + * 0001: dst is 32-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1, #0xb] /* r2 = ...B */ + ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */ + ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */ + ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */ + mov r2, r2, lsl #24 /* r2 = B... */ + orr r2, r2, ip, lsr #8 /* r2 = BA98 */ + str r2, [r0, #0x08] + mov r2, ip, lsl #24 /* r2 = 7... */ + orr r2, r2, r3, lsr #8 /* r2 = 7654 */ + mov r1, r1, lsr #8 /* r1 = .210 */ + orr r1, r1, r3, lsl #24 /* r1 = 3210 */ + str r2, [r0, #0x04] + str r1, [r0] + bx lr + LMEMCPY_C_PAD + +/* + * 0010: dst is 32-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */ + ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */ + orr r2, r2, r3, lsl #16 /* r2 = 3210 */ + str r2, [r0] + mov r3, r3, lsr #16 /* r3 = ..54 */ + orr r3, r3, ip, lsl #16 /* r3 = 7654 */ + mov r1, r1, lsl #16 /* r1 = BA.. */ + orr r1, r1, ip, lsr #16 /* r1 = BA98 */ + str r3, [r0, #0x04] + str r1, [r0, #0x08] + bx lr + LMEMCPY_C_PAD + +/* + * 0011: dst is 32-bit aligned, src is 8-bit aligned + */ + ldrb r2, [r1] /* r2 = ...0 */ + ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */ + ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */ + ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */ + orr r2, r2, r3, lsl #8 /* r2 = 3210 */ + str r2, [r0] + mov r3, r3, lsr #24 /* r3 = ...4 */ + orr r3, r3, ip, lsl #8 /* r3 = 7654 */ + mov r1, r1, lsl #8 /* r1 = BA9. */ + orr r1, r1, ip, lsr #24 /* r1 = BA98 */ + str r3, [r0, #0x04] + str r1, [r0, #0x08] + bx lr + LMEMCPY_C_PAD + +/* + * 0100: dst is 8-bit aligned (byte 1), src is 32-bit aligned + */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */ + ldr ip, [r1, #0x08] /* BE:ip = 89AB LE:ip = BA98 */ + mov r1, r2, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */ + strh r1, [r0, #0x01] + strb r2, [r0] + mov r1, r2, lsr #24 /* r1 = ...3 */ + orr r2, r1, r3, lsl #8 /* r1 = 6543 */ + mov r1, r3, lsr #24 /* r1 = ...7 */ + orr r1, r1, ip, lsl #8 /* r1 = A987 */ + mov ip, ip, lsr #24 /* ip = ...B */ + str r2, [r0, #0x03] + str r1, [r0, #0x07] + strb ip, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 0101: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 1) + */ + ldrb r2, [r1] + ldrh r3, [r1, #0x01] + ldr ip, [r1, #0x03] + strb r2, [r0] + ldr r2, [r1, #0x07] + ldrb r1, [r1, #0x0b] + strh r3, [r0, #0x01] + str ip, [r0, #0x03] + str r2, [r0, #0x07] + strb r1, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 0110: dst is 8-bit aligned (byte 1), src is 16-bit aligned + */ + ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */ + ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */ + ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */ + ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = ...1 */ + orr r2, r2, r3, lsl #8 /* r2 = 4321 */ + strh r2, [r0, #0x01] + mov r2, r3, lsr #8 /* r2 = .543 */ + orr r3, r2, ip, lsl #24 /* r3 = 6543 */ + mov r2, ip, lsr #8 /* r2 = .987 */ + orr r2, r2, r1, lsl #24 /* r2 = A987 */ + mov r1, r1, lsr #8 /* r1 = ...B */ + str r3, [r0, #0x03] + str r2, [r0, #0x07] + strb r1, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 0111: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 3) + */ + ldrb r2, [r1] + ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */ + ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */ + ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */ + strb r2, [r0] + strh r3, [r0, #0x01] + mov r3, r3, lsr #16 /* r3 = ..43 */ + orr r3, r3, ip, lsl #16 /* r3 = 6543 */ + mov ip, ip, lsr #16 /* ip = ..87 */ + orr ip, ip, r1, lsl #16 /* ip = A987 */ + mov r1, r1, lsr #16 /* r1 = ..xB */ + str r3, [r0, #0x03] + str ip, [r0, #0x07] + strb r1, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 1000: dst is 16-bit aligned, src is 32-bit aligned + */ + ldr ip, [r1] /* BE:ip = 0123 LE:ip = 3210 */ + ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */ + ldr r2, [r1, #0x08] /* BE:r2 = 89AB LE:r2 = BA98 */ + mov r1, ip, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */ + strh ip, [r0] + orr r1, r1, r3, lsl #16 /* r1 = 5432 */ + mov r3, r3, lsr #16 /* r3 = ..76 */ + orr r3, r3, r2, lsl #16 /* r3 = 9876 */ + mov r2, r2, lsr #16 /* r2 = ..BA */ + str r1, [r0, #0x02] + str r3, [r0, #0x06] + strh r2, [r0, #0x0a] + bx lr + LMEMCPY_C_PAD + +/* + * 1001: dst is 16-bit aligned, src is 8-bit aligned (byte 1) + */ + ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */ + ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */ + mov ip, r2, lsr #8 /* BE:ip = .x01 LE:ip = .210 */ + strh ip, [r0] + ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */ + ldrb r1, [r1, #0x0b] /* r1 = ...B */ + mov r2, r2, lsr #24 /* r2 = ...2 */ + orr r2, r2, r3, lsl #8 /* r2 = 5432 */ + mov r3, r3, lsr #24 /* r3 = ...6 */ + orr r3, r3, ip, lsl #8 /* r3 = 9876 */ + mov r1, r1, lsl #8 /* r1 = ..B. */ + orr r1, r1, ip, lsr #24 /* r1 = ..BA */ + str r2, [r0, #0x02] + str r3, [r0, #0x06] + strh r1, [r0, #0x0a] + bx lr + LMEMCPY_C_PAD + +/* + * 1010: dst is 16-bit aligned, src is 16-bit aligned + */ + ldrh r2, [r1] + ldr r3, [r1, #0x02] + ldr ip, [r1, #0x06] + ldrh r1, [r1, #0x0a] + strh r2, [r0] + str r3, [r0, #0x02] + str ip, [r0, #0x06] + strh r1, [r0, #0x0a] + bx lr + LMEMCPY_C_PAD + +/* + * 1011: dst is 16-bit aligned, src is 8-bit aligned (byte 3) + */ + ldr r2, [r1, #0x09] /* BE:r2 = 9ABx LE:r2 = xBA9 */ + ldr r3, [r1, #0x05] /* BE:r3 = 5678 LE:r3 = 8765 */ + mov ip, r2, lsr #8 /* BE:ip = .9AB LE:ip = .xBA */ + strh ip, [r0, #0x0a] + ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */ + ldrb r1, [r1] /* r1 = ...0 */ + mov r2, r2, lsl #24 /* r2 = 9... */ + orr r2, r2, r3, lsr #8 /* r2 = 9876 */ + mov r3, r3, lsl #24 /* r3 = 5... */ + orr r3, r3, ip, lsr #8 /* r3 = 5432 */ + orr r1, r1, ip, lsl #8 /* r1 = 3210 */ + str r2, [r0, #0x06] + str r3, [r0, #0x02] + strh r1, [r0] + bx lr + LMEMCPY_C_PAD + +/* + * 1100: dst is 8-bit aligned (byte 3), src is 32-bit aligned + */ + ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */ + ldr ip, [r1, #0x04] /* BE:ip = 4567 LE:ip = 7654 */ + ldr r1, [r1, #0x08] /* BE:r1 = 89AB LE:r1 = BA98 */ + strb r2, [r0] + mov r3, r2, lsr #8 /* r3 = .321 */ + orr r3, r3, ip, lsl #24 /* r3 = 4321 */ + str r3, [r0, #0x01] + mov r3, ip, lsr #8 /* r3 = .765 */ + orr r3, r3, r1, lsl #24 /* r3 = 8765 */ + str r3, [r0, #0x05] + mov r1, r1, lsr #8 /* r1 = .BA9 */ + strh r1, [r0, #0x09] + mov r1, r1, lsr #16 /* r1 = ...B */ + strb r1, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 1101: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 1) + */ + ldrb r2, [r1, #0x0b] /* r2 = ...B */ + ldr r3, [r1, #0x07] /* BE:r3 = 789A LE:r3 = A987 */ + ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */ + ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */ + strb r2, [r0, #0x0b] + mov r2, r3, lsr #16 /* r2 = ..A9 */ + strh r2, [r0, #0x09] + mov r3, r3, lsl #16 /* r3 = 87.. */ + orr r3, r3, ip, lsr #16 /* r3 = 8765 */ + mov ip, ip, lsl #16 /* ip = 43.. */ + orr ip, ip, r1, lsr #16 /* ip = 4321 */ + mov r1, r1, lsr #8 /* r1 = .210 */ + str r3, [r0, #0x05] + str ip, [r0, #0x01] + strb r1, [r0] + bx lr + LMEMCPY_C_PAD + +/* + * 1110: dst is 8-bit aligned (byte 3), src is 16-bit aligned + */ + ldrh r2, [r1] /* r2 = ..10 */ + ldr r3, [r1, #0x02] /* r3 = 5432 */ + ldr ip, [r1, #0x06] /* ip = 9876 */ + ldrh r1, [r1, #0x0a] /* r1 = ..BA */ + strb r2, [r0] + mov r2, r2, lsr #8 /* r2 = ...1 */ + orr r2, r2, r3, lsl #8 /* r2 = 4321 */ + mov r3, r3, lsr #24 /* r3 = ...5 */ + orr r3, r3, ip, lsl #8 /* r3 = 8765 */ + mov ip, ip, lsr #24 /* ip = ...9 */ + orr ip, ip, r1, lsl #8 /* ip = .BA9 */ + mov r1, r1, lsr #8 /* r1 = ...B */ + str r2, [r0, #0x01] + str r3, [r0, #0x05] + strh ip, [r0, #0x09] + strb r1, [r0, #0x0b] + bx lr + LMEMCPY_C_PAD + +/* + * 1111: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 3) + */ + ldrb r2, [r1] + ldr r3, [r1, #0x01] + ldr ip, [r1, #0x05] + strb r2, [r0] + ldrh r2, [r1, #0x09] + ldrb r1, [r1, #0x0b] + str r3, [r0, #0x01] + str ip, [r0, #0x05] + strh r2, [r0, #0x09] + strb r1, [r0, #0x0b] + bx lr +#endif /* !_STANDALONE */ +END(memcpy) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/memmove.S b/lib/libc/arm/string/memmove.S new file mode 100644 index 000000000000..fa871d9274e9 --- /dev/null +++ b/lib/libc/arm/string/memmove.S @@ -0,0 +1,479 @@ +/* $NetBSD: memmove.S,v 1.4 2003/10/14 07:51:45 scw Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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> +.syntax unified + +#ifndef _BCOPY +/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */ +ENTRY(memmove) +#else +/* bcopy = memcpy/memmove with arguments reversed. */ +/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */ +ENTRY(bcopy) + /* switch the source and destination registers */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 +#endif + /* Do the buffers overlap? */ + cmp r0, r1 + it eq + RETeq /* Bail now if src/dst are the same */ + ite cc + subcc r3, r0, r1 /* if (dst > src) r3 = dst - src */ + subcs r3, r1, r0 /* if (src > dsr) r3 = src - dst */ + cmp r3, r2 /* if (r3 < len) we have an overlap */ + bcc PIC_SYM(_C_LABEL(memcpy), PLT) + + /* Determine copy direction */ + cmp r1, r0 + it cc + bcc .Lmemmove_backwards + + itt eq + moveq r0, #0 /* Quick abort for len=0 */ + RETeq + + stmdb sp!, {r0, lr} /* memmove() returns dest addr */ + subs r2, r2, #4 + blt .Lmemmove_fl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemmove_fdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemmove_fsrcul /* oh unaligned source addr */ + +.Lmemmove_ft8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemmove_fl12 /* less than 12 bytes (4 from above) */ + subs r2, r2, #0x14 + blt .Lmemmove_fl32 /* less than 32 bytes (12 from above) */ + stmdb sp!, {r4} /* borrow r4 */ + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemmove_floop32: + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemmove_floop32 + + cmn r2, #0x10 + ittt ge + ldmiage r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ + stmiage r0!, {r3, r4, r12, lr} + subge r2, r2, #0x10 + ldmia sp!, {r4} /* return r4 */ + +.Lmemmove_fl32: + adds r2, r2, #0x14 + + /* blat 12 bytes at a time */ +.Lmemmove_floop12: + ittt ge + ldmiage r1!, {r3, r12, lr} + stmiage r0!, {r3, r12, lr} + subsge r2, r2, #0x0c + bge .Lmemmove_floop12 + +.Lmemmove_fl12: + adds r2, r2, #8 + blt .Lmemmove_fl4 + + subs r2, r2, #4 + itt lt + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + ittt ge + ldmiage r1!, {r3, r12} + stmiage r0!, {r3, r12} + subge r2, r2, #4 + +.Lmemmove_fl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + it eq + ldmiaeq sp!, {r0, pc} /* done */ + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 + ldmia sp!, {r0, pc} + + /* erg - unaligned destination */ +.Lmemmove_fdestul: + rsb r12, r12, #4 + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1], #1 + strb r3, [r0], #1 + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 + subs r2, r2, r12 + blt .Lmemmove_fl4 /* less the 4 bytes */ + + ands r12, r1, #3 + beq .Lmemmove_ft8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemmove_fsrcul: + bic r1, r1, #3 + ldr lr, [r1], #4 + cmp r12, #2 + bgt .Lmemmove_fsrcul3 + beq .Lmemmove_fsrcul2 + cmp r2, #0x0c + blt .Lmemmove_fsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemmove_fsrcul1loop16: + mov r3, lr, lsr #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, lr, lsl #24 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemmove_fsrcul1loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemmove_fsrcul1l4 + +.Lmemmove_fsrcul1loop4: + mov r12, lr, lsr #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #24 + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemmove_fsrcul1loop4 + +.Lmemmove_fsrcul1l4: + sub r1, r1, #3 + b .Lmemmove_fl4 + +.Lmemmove_fsrcul2: + cmp r2, #0x0c + blt .Lmemmove_fsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemmove_fsrcul2loop16: + mov r3, lr, lsr #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, lr, lsl #16 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemmove_fsrcul2loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemmove_fsrcul2l4 + +.Lmemmove_fsrcul2loop4: + mov r12, lr, lsr #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #16 + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemmove_fsrcul2loop4 + +.Lmemmove_fsrcul2l4: + sub r1, r1, #2 + b .Lmemmove_fl4 + +.Lmemmove_fsrcul3: + cmp r2, #0x0c + blt .Lmemmove_fsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemmove_fsrcul3loop16: + mov r3, lr, lsr #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, lr, lsl #8 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemmove_fsrcul3loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemmove_fsrcul3l4 + +.Lmemmove_fsrcul3loop4: + mov r12, lr, lsr #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #8 + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemmove_fsrcul3loop4 + +.Lmemmove_fsrcul3l4: + sub r1, r1, #1 + b .Lmemmove_fl4 + +.Lmemmove_backwards: + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt .Lmemmove_bl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemmove_bdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemmove_bsrcul /* oh unaligned source addr */ + +.Lmemmove_bt8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemmove_bl12 /* less than 12 bytes (4 from above) */ + stmdb sp!, {r4, lr} + subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */ + blt .Lmemmove_bl32 + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemmove_bloop32: + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemmove_bloop32 + +.Lmemmove_bl32: + cmn r2, #0x10 + ittt ge + ldmdbge r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ + stmdbge r0!, {r3, r4, r12, lr} + subge r2, r2, #0x10 + adds r2, r2, #0x14 + ittt ge + ldmdbge r1!, {r3, r12, lr} /* blat a remaining 12 bytes */ + stmdbge r0!, {r3, r12, lr} + subge r2, r2, #0x0c + ldmia sp!, {r4, lr} + +.Lmemmove_bl12: + adds r2, r2, #8 + blt .Lmemmove_bl4 + subs r2, r2, #4 + itt lt + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + ittt ge + ldmdbge r1!, {r3, r12} + stmdbge r0!, {r3, r12} + subge r2, r2, #4 + +.Lmemmove_bl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + it eq + RETeq /* done */ + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! + RET + + /* erg - unaligned destination */ +.Lmemmove_bdestul: + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! + subs r2, r2, r12 + blt .Lmemmove_bl4 /* less than 4 bytes to go */ + ands r12, r1, #3 + beq .Lmemmove_bt8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemmove_bsrcul: + bic r1, r1, #3 + ldr r3, [r1, #0] + cmp r12, #2 + blt .Lmemmove_bsrcul1 + beq .Lmemmove_bsrcul2 + cmp r2, #0x0c + blt .Lmemmove_bsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemmove_bsrcul3loop16: + mov lr, r3, lsl #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemmove_bsrcul3loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemmove_bsrcul3l4 + +.Lmemmove_bsrcul3loop4: + mov r12, r3, lsl #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #24 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemmove_bsrcul3loop4 + +.Lmemmove_bsrcul3l4: + add r1, r1, #3 + b .Lmemmove_bl4 + +.Lmemmove_bsrcul2: + cmp r2, #0x0c + blt .Lmemmove_bsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemmove_bsrcul2loop16: + mov lr, r3, lsl #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemmove_bsrcul2loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemmove_bsrcul2l4 + +.Lmemmove_bsrcul2loop4: + mov r12, r3, lsl #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #16 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemmove_bsrcul2loop4 + +.Lmemmove_bsrcul2l4: + add r1, r1, #2 + b .Lmemmove_bl4 + +.Lmemmove_bsrcul1: + cmp r2, #0x0c + blt .Lmemmove_bsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemmove_bsrcul1loop32: + mov lr, r3, lsl #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemmove_bsrcul1loop32 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemmove_bsrcul1l4 + +.Lmemmove_bsrcul1loop4: + mov r12, r3, lsl #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #8 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemmove_bsrcul1loop4 + +.Lmemmove_bsrcul1l4: + add r1, r1, #1 + b .Lmemmove_bl4 +#ifndef _BCOPY +END(memmove) +#else +END(bcopy) +#endif + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/memset.S b/lib/libc/arm/string/memset.S new file mode 100644 index 000000000000..40e0e567668b --- /dev/null +++ b/lib/libc/arm/string/memset.S @@ -0,0 +1,224 @@ +/* $NetBSD: memset.S,v 1.4 2003/10/14 07:51:45 scw Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/* + * Copyright (c) 1995 Mark Brinicombe. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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> +.syntax unified + +/* + * memset: Sets a block of memory to the specified value + * + * On entry: + * r0 - dest address + * r1 - byte to write + * r2 - number of bytes to write + * + * On exit: + * r0 - dest address + */ +#ifdef _BZERO +/* LINTSTUB: Func: void bzero(void *, size_t) */ +ENTRY(bzero) + mov r3, #0x00 +#else +/* LINTSTUB: Func: void *memset(void *, int, size_t) */ +ENTRY(memset) + and r3, r1, #0xff /* We deal with bytes */ + mov r1, r2 +#endif + cmp r1, #0x04 /* Do we have less than 4 bytes */ + mov ip, r0 + blt .Lmemset_lessthanfour + + /* Ok first we will word align the address */ + ands r2, ip, #0x03 /* Get the bottom two bits */ + bne .Lmemset_wordunaligned /* The address is not word aligned */ + + /* We are now word aligned */ +.Lmemset_wordaligned: +#ifndef _BZERO + orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */ +#endif + tst ip, #0x04 /* Quad-align for armv5e */ +#ifndef _BZERO + orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */ +#endif + itt ne + subne r1, r1, #0x04 /* Quad-align if necessary */ + strne r3, [ip], #0x04 + cmp r1, #0x10 + blt .Lmemset_loop4 /* If less than 16 then use words */ + mov r2, r3 /* Duplicate data */ + cmp r1, #0x80 /* If < 128 then skip the big loop */ + blt .Lmemset_loop32 + + /* Do 128 bytes at a time */ +.Lmemset_loop128: + subs r1, r1, #0x80 + itttt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + itttt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + itttt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + itttt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + bgt .Lmemset_loop128 + it eq + RETeq /* Zero length so just exit */ + + add r1, r1, #0x80 /* Adjust for extra sub */ + + /* Do 32 bytes at a time */ +.Lmemset_loop32: + subs r1, r1, #0x20 + itttt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + bgt .Lmemset_loop32 + it eq + RETeq /* Zero length so just exit */ + + adds r1, r1, #0x10 /* Partially adjust for extra sub */ + + /* Deal with 16 bytes or more */ + itt ge + strdge r2, [ip], #0x08 + strdge r2, [ip], #0x08 + it eq + RETeq /* Zero length so just exit */ + + it lt + addlt r1, r1, #0x10 /* Possibly adjust for extra sub */ + + /* We have at least 4 bytes so copy as words */ +.Lmemset_loop4: + subs r1, r1, #0x04 + it ge + strge r3, [ip], #0x04 + bgt .Lmemset_loop4 + it eq + RETeq /* Zero length so just exit */ + + /* Compensate for 64-bit alignment check */ + adds r1, r1, #0x04 + it eq + RETeq + cmp r1, #2 + + strb r3, [ip], #0x01 /* Set 1 byte */ + it ge + strbge r3, [ip], #0x01 /* Set another byte */ + it gt + strbgt r3, [ip] /* and a third */ + RET /* Exit */ + +.Lmemset_wordunaligned: + rsb r2, r2, #0x004 + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r2, #0x02 + it ge + strbge r3, [ip], #0x01 /* Set another byte */ + sub r1, r1, r2 + it gt + strbgt r3, [ip], #0x01 /* and a third */ + cmp r1, #0x04 /* More than 4 bytes left? */ + it ge + bge .Lmemset_wordaligned /* Yup */ + +.Lmemset_lessthanfour: + cmp r1, #0x00 + it eq + RETeq /* Zero length so exit */ + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r1, #0x02 + it ge + strbge r3, [ip], #0x01 /* Set another byte */ + it gt + strbgt r3, [ip] /* and a third */ + RET /* Exit */ +#ifdef _BZERO +END(bzero) +#else +END(memset) +#endif + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/strcmp.S b/lib/libc/arm/string/strcmp.S new file mode 100644 index 000000000000..19145c61ebd8 --- /dev/null +++ b/lib/libc/arm/string/strcmp.S @@ -0,0 +1,44 @@ +/* $NetBSD: strcmp.S,v 1.3 2003/04/05 23:08:52 bjh21 Exp $ */ + +/* + * Copyright (c) 2002 ARM Ltd + * 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. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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> +ENTRY(strcmp) +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp r2, #1 + it cs + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 + RET +END(strcmp) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/strlen.S b/lib/libc/arm/string/strlen.S new file mode 100644 index 000000000000..5b68e51b8a25 --- /dev/null +++ b/lib/libc/arm/string/strlen.S @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2005 Olivier Houchard + * 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> +.syntax unified + +ENTRY(strlen) + mov r1, #0 + /* Check that the pointer is aligned on 32 bits. */ + ands r3, r0, #3 + beq .Loop + sub r0, r0, r3 + ldr r2, [r0] + add r0, r0, #4 + cmp r3, #2 + blt .Ldo_3 + bgt .Ldo_1 + /* So that the N bit is set. */ + cmp r3, #0 + b .Ldo_2 + +.Loop: + ldr r2, [r0] + add r0, r0, #4 + ands r3, r2, #0x000000ff + it ne + addne r1, r1, #1 +.Ldo_3: + itt ne + andsne r3, r2, #0x0000ff00 + addne r1, r1, #1 +.Ldo_2: + itt ne + andsne r3, r2, #0x00ff0000 + addne r1, r1, #1 +.Ldo_1: + ittt ne + andsne r3, r2, #0xff000000 + addne r1, r1, #1 + bne .Loop +.Lexit: + mov r0, r1 + RET +END(strlen) + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libc/arm/string/strncmp.S b/lib/libc/arm/string/strncmp.S new file mode 100644 index 000000000000..d3d6ce08e0c3 --- /dev/null +++ b/lib/libc/arm/string/strncmp.S @@ -0,0 +1,57 @@ +/* $NetBSD: strncmp.S,v 1.2 2003/04/05 23:08:52 bjh21 Exp $ */ + +/* + * Copyright (c) 2002 ARM Ltd + * 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. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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> +ENTRY(strncmp) +/* if (len == 0) return 0 */ + cmp r2, #0 + itt eq + moveq r0, #0 + moveq pc, lr + +/* ip == last src address to compare */ + adds ip, r0, r2 +/* Use last possible address on overflow. */ + it cs + movcs ip, #0 + sub ip, ip, #1 +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp ip, r0 + itt cs + cmpcs r2, #1 + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 + RET +END(strncmp) + + .section .note.GNU-stack,"",%progbits |