From 0bea89508c6be2b1a76650108d759d389e99bbf3 Mon Sep 17 00:00:00 2001
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
Date: Wed, 13 Apr 2022 16:32:02 +0800
|
Subject: [PATCH] libc: string: arm: Support using glibc-neon version of APIs
|
|
Set USE_GLIBC_NEON to enable.
|
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
---
|
Makerules | 1 +
|
libc/string/Makefile.in | 10 +-
|
libc/string/arm/Makefile.in | 13 +
|
libc/string/arm/glibc-neon/README | 4 +
|
libc/string/arm/glibc-neon/arm-features.h | 59 ++
|
libc/string/arm/glibc-neon/bcopy.c | 24 +
|
libc/string/arm/glibc-neon/bzero.c | 28 +
|
libc/string/arm/glibc-neon/glibc_wrap.h | 29 +
|
libc/string/arm/glibc-neon/memcmp.S | 1 +
|
libc/string/arm/glibc-neon/memcpy.S | 728 ++++++++++++++++++
|
libc/string/arm/glibc-neon/memmove.S | 332 ++++++++
|
libc/string/arm/glibc-neon/memset.S | 68 ++
|
libc/string/arm/glibc-neon/strcmp.S | 504 ++++++++++++
|
libc/string/arm/glibc-neon/strlen.S | 76 ++
|
libc/string/arm/glibc-neon/sysdep.h | 339 ++++++++
|
.../arm/glibc-neon/sysdeps/generic/dwarf2.h | 590 ++++++++++++++
|
.../arm/glibc-neon/sysdeps/generic/sysdep.h | 97 +++
|
17 files changed, 2901 insertions(+), 2 deletions(-)
|
create mode 100644 libc/string/arm/Makefile.in
|
create mode 100644 libc/string/arm/glibc-neon/README
|
create mode 100644 libc/string/arm/glibc-neon/arm-features.h
|
create mode 100644 libc/string/arm/glibc-neon/bcopy.c
|
create mode 100644 libc/string/arm/glibc-neon/bzero.c
|
create mode 100644 libc/string/arm/glibc-neon/glibc_wrap.h
|
create mode 120000 libc/string/arm/glibc-neon/memcmp.S
|
create mode 100644 libc/string/arm/glibc-neon/memcpy.S
|
create mode 100644 libc/string/arm/glibc-neon/memmove.S
|
create mode 100644 libc/string/arm/glibc-neon/memset.S
|
create mode 100644 libc/string/arm/glibc-neon/strcmp.S
|
create mode 100644 libc/string/arm/glibc-neon/strlen.S
|
create mode 100644 libc/string/arm/glibc-neon/sysdep.h
|
create mode 100644 libc/string/arm/glibc-neon/sysdeps/generic/dwarf2.h
|
create mode 100644 libc/string/arm/glibc-neon/sysdeps/generic/sysdep.h
|
|
diff --git a/Makerules b/Makerules
|
index fd40e6c..2013ba9 100644
|
--- a/Makerules
|
+++ b/Makerules
|
@@ -255,6 +255,7 @@ CFLAGS_gen.dep = -MT $@ -MD -MP -MF $(dir $@).$(notdir $@).dep
|
|
cmd_compile.c = $(CC) -c $< -o $@ \
|
$(filter-out $(CFLAGS-OMIT-$(notdir $<)), \
|
+ $(CFLAGS-extra-$(subst $(top_srcdir),,$(<D))) \
|
$(CFLAGS) \
|
$(CFLAGS-for-library-members) \
|
$(CFLAGS-$(suffix $@)) \
|
diff --git a/libc/string/Makefile.in b/libc/string/Makefile.in
|
index e7f2ccd..975b395 100644
|
--- a/libc/string/Makefile.in
|
+++ b/libc/string/Makefile.in
|
@@ -5,6 +5,12 @@
|
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
#
|
|
+ifeq ($(TARGET_ARCH),arm)
|
+ifneq ($(USE_GLIBC_NEON),)
|
+include $(top_srcdir)libc/string/$(TARGET_ARCH)/Makefile.in
|
+endif
|
+endif
|
+
|
subdirs += libc/string/$(TARGET_ARCH) libc/string/generic
|
|
#
|
@@ -25,8 +31,8 @@ STRING_SUBARCH_OBJS := $(STRING_SUBARCH_SOBJ) $(STRING_SUBARCH_COBJ)
|
endif
|
|
# Collect the arch specific implementation (asm, c files)
|
-STRING_ARCH_DIR := $(top_srcdir)libc/string/$(TARGET_ARCH)
|
-STRING_ARCH_OUT := $(top_builddir)libc/string/$(TARGET_ARCH)
|
+STRING_ARCH_DIR ?= $(top_srcdir)libc/string/$(TARGET_ARCH)
|
+STRING_ARCH_OUT ?= $(top_builddir)libc/string/$(TARGET_ARCH)
|
|
STRING_ARCH_SRC := $(wildcard $(STRING_ARCH_DIR)/*.c)
|
STRING_ARCH_OBJ := $(patsubst $(STRING_ARCH_DIR)/%.c,$(STRING_ARCH_OUT)/%.o,$(STRING_ARCH_SRC))
|
diff --git a/libc/string/arm/Makefile.in b/libc/string/arm/Makefile.in
|
new file mode 100644
|
index 0000000..4cd7e24
|
--- /dev/null
|
+++ b/libc/string/arm/Makefile.in
|
@@ -0,0 +1,13 @@
|
+# Makefile for uClibc
|
+#
|
+# Copyright (C) 2022 Jeffy Chen <jeffy.chen@rock-chips.com>
|
+#
|
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
+#
|
+
|
+SUBDIR := libc/string/arm/glibc-neon
|
+
|
+STRING_ARCH_DIR := $(top_srcdir)$(SUBDIR)
|
+STRING_ARCH_OUT := $(top_builddir)$(SUBDIR)
|
+
|
+CFLAGS-extra-$(SUBDIR) := -include glibc_wrap.h -I$(top_srcdir)$(SUBDIR)
|
diff --git a/libc/string/arm/glibc-neon/README b/libc/string/arm/glibc-neon/README
|
new file mode 100644
|
index 0000000..ad72f05
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/README
|
@@ -0,0 +1,4 @@
|
+NOTE:
|
+1/ Ported from glibc-2.34.9.
|
+2/ glibc doesn't have an arm arch version of memcmp.
|
+3/ uClibc is using strcmp as strcoll when locale disabled.
|
diff --git a/libc/string/arm/glibc-neon/arm-features.h b/libc/string/arm/glibc-neon/arm-features.h
|
new file mode 100644
|
index 0000000..4a86e00
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/arm-features.h
|
@@ -0,0 +1,59 @@
|
+/* Macros to test for CPU features on ARM. Generic ARM version.
|
+ Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#ifndef _ARM_ARM_FEATURES_H
|
+#define _ARM_ARM_FEATURES_H 1
|
+
|
+/* An OS-specific arm-features.h file should define ARM_HAVE_VFP to
|
+ an appropriate expression for testing at runtime whether the VFP
|
+ hardware is present. We'll then redefine it to a constant if we
|
+ know at compile time that we can assume VFP. */
|
+
|
+#ifndef __SOFTFP__
|
+/* The compiler is generating VFP instructions, so we're already
|
+ assuming the hardware exists. */
|
+# undef ARM_HAVE_VFP
|
+# define ARM_HAVE_VFP 1
|
+#endif
|
+
|
+/* An OS-specific arm-features.h file may define ARM_ASSUME_NO_IWMMXT
|
+ to indicate at compile time that iWMMXt hardware is never present
|
+ at runtime (or that we never care about its state) and so need not
|
+ be checked for. */
|
+
|
+/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate
|
+ that instructions using pc as a destination register must never be used,
|
+ so a "bx" (or "blx") instruction is always required. */
|
+
|
+/* The log2 of the minimum alignment required for an address that
|
+ is the target of a computed branch (i.e. a "bx" instruction).
|
+ A more-specific arm-features.h file may define this to set a more
|
+ stringent requirement.
|
+
|
+ Using this only makes sense for code in ARM mode (where instructions
|
+ always have a fixed size of four bytes), or for Thumb-mode code that is
|
+ specifically aligning all the related branch targets to match (since
|
+ Thumb instructions might be either two or four bytes). */
|
+#ifndef ARM_BX_ALIGN_LOG2
|
+# define ARM_BX_ALIGN_LOG2 2
|
+#endif
|
+
|
+/* An OS-specific arm-features.h file may define ARM_NO_INDEX_REGISTER to
|
+ indicate that the two-register addressing modes must never be used. */
|
+
|
+#endif /* arm-features.h */
|
diff --git a/libc/string/arm/glibc-neon/bcopy.c b/libc/string/arm/glibc-neon/bcopy.c
|
new file mode 100644
|
index 0000000..302bbbd
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/bcopy.c
|
@@ -0,0 +1,24 @@
|
+/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library; if not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#include <string.h>
|
+
|
+void
|
+bcopy (const void *src, void *dest, size_t len)
|
+{
|
+ memmove (dest, src, len);
|
+}
|
diff --git a/libc/string/arm/glibc-neon/bzero.c b/libc/string/arm/glibc-neon/bzero.c
|
new file mode 100644
|
index 0000000..4391dad
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/bzero.c
|
@@ -0,0 +1,28 @@
|
+/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library; if not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#include <string.h>
|
+
|
+#undef __bzero
|
+
|
+/* Set N bytes of S to 0. */
|
+void
|
+__bzero (void *s, size_t len)
|
+{
|
+ memset (s, '\0', len);
|
+}
|
+weak_alias (__bzero, bzero)
|
diff --git a/libc/string/arm/glibc-neon/glibc_wrap.h b/libc/string/arm/glibc-neon/glibc_wrap.h
|
new file mode 100644
|
index 0000000..f00d50d
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/glibc_wrap.h
|
@@ -0,0 +1,29 @@
|
+/* Macros to adapt glibc version of string APIs.
|
+ Copyright (C) 2022 Jeffy Chen <jeffy.chen@rock-chips.com>
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#ifndef GLIBC_WRAP_H
|
+#define GLIBC_WRAP_H
|
+
|
+#define IS_IN(lib) 1
|
+
|
+#define libc_hidden_builtin_def(fn) libc_hidden_def(fn)
|
+
|
+#define C_SYMBOL_NAME(name) name
|
+#define MEMCPY_NEON
|
+
|
+#endif // GLIBC_WRAP_H
|
diff --git a/libc/string/arm/glibc-neon/memcmp.S b/libc/string/arm/glibc-neon/memcmp.S
|
new file mode 120000
|
index 0000000..7c28a09
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/memcmp.S
|
@@ -0,0 +1 @@
|
+../memcmp.S
|
\ No newline at end of file
|
diff --git a/libc/string/arm/glibc-neon/memcpy.S b/libc/string/arm/glibc-neon/memcpy.S
|
new file mode 100644
|
index 0000000..ee562e8
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/memcpy.S
|
@@ -0,0 +1,728 @@
|
+/* NEON/VFP/ARM version of memcpy optimized for Cortex-A15.
|
+ Copyright (C) 2013-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library; if not, see
|
+ <https://www.gnu.org/licenses/>.
|
+
|
+ This memcpy routine is optimised for Cortex-A15 cores and takes advantage
|
+ of VFP or NEON when built with the appropriate flags.
|
+
|
+ Assumptions:
|
+
|
+ ARMv6 (ARMv7-a if using Neon)
|
+ ARM state
|
+ Unaligned accesses
|
+
|
+ */
|
+
|
+/* Thumb cannot encode negative immediate offsets in memory operations. */
|
+#ifndef NO_THUMB
|
+#define NO_THUMB
|
+#endif
|
+#include <sysdep.h>
|
+#include <arm-features.h>
|
+
|
+ .syntax unified
|
+ /* This implementation requires ARM state. */
|
+ .arm
|
+
|
+#ifdef MEMCPY_NEON
|
+
|
+ .fpu neon
|
+ .arch armv7-a
|
+# define FRAME_SIZE 4
|
+# define USE_VFP
|
+# define USE_NEON
|
+
|
+#elif defined (MEMCPY_VFP)
|
+
|
+ .arch armv6
|
+ .fpu vfpv2
|
+# define FRAME_SIZE 32
|
+# define USE_VFP
|
+
|
+#else
|
+ .arch armv6
|
+# define FRAME_SIZE 32
|
+
|
+#endif
|
+
|
+#define ALIGN(addr, align) addr:align
|
+
|
+#define INSN_SIZE 4
|
+
|
+/* Call parameters. */
|
+#define dstin r0
|
+#define src r1
|
+#define count r2
|
+
|
+/* Locals. */
|
+#define tmp1 r3
|
+#define dst ip
|
+#define tmp2 r8
|
+
|
+/* These two macros both work by repeated invocation of the macro
|
+ dispatch_step (not defined here). That macro performs one "step",
|
+ doing one load instruction and one store instruction to copy one
|
+ "unit". On entry, TMP1 contains the number of bytes to be copied,
|
+ a multiple of the unit size. The macro clobbers TMP1 in the
|
+ process of doing a computed jump to the tail containing the
|
+ appropriate number of steps.
|
+
|
+ In dispatch_7_dword, dispatch_step is invoked seven times, with an
|
+ argument that is 7 for the first and 1 for the last. Units are
|
+ double-words (8 bytes). TMP1 is at most 56.
|
+
|
+ In dispatch_15_word, dispatch_step is invoked fifteen times,
|
+ with an argument that is 15 for the first and 1 for the last.
|
+ Units are words (4 bytes). TMP1 is at most 60. */
|
+
|
+#ifndef ARM_ALWAYS_BX
|
+# if ARM_BX_ALIGN_LOG2 != 2
|
+# error case not handled
|
+# endif
|
+ .macro dispatch_7_dword
|
+ rsb tmp1, tmp1, #((7 * 8) - PC_OFS + INSN_SIZE)
|
+ add pc, pc, tmp1
|
+ dispatch_step 7
|
+ dispatch_step 6
|
+ dispatch_step 5
|
+ dispatch_step 4
|
+ dispatch_step 3
|
+ dispatch_step 2
|
+ dispatch_step 1
|
+ .purgem dispatch_step
|
+ .endm
|
+
|
+ .macro dispatch_15_word
|
+ rsb tmp1, tmp1, #((15 * 4) - PC_OFS/2 + INSN_SIZE/2)
|
+ add pc, pc, tmp1, lsl #1
|
+ dispatch_step 15
|
+ dispatch_step 14
|
+ dispatch_step 13
|
+ dispatch_step 12
|
+ dispatch_step 11
|
+ dispatch_step 10
|
+ dispatch_step 9
|
+ dispatch_step 8
|
+ dispatch_step 7
|
+ dispatch_step 6
|
+ dispatch_step 5
|
+ dispatch_step 4
|
+ dispatch_step 3
|
+ dispatch_step 2
|
+ dispatch_step 1
|
+ .purgem dispatch_step
|
+ .endm
|
+#else
|
+# if ARM_BX_ALIGN_LOG2 < 3
|
+# error case not handled
|
+# endif
|
+ .macro dispatch_helper steps, log2_bytes_per_step
|
+ /* TMP1 gets (max_bytes - bytes_to_copy), where max_bytes is
|
+ (STEPS << LOG2_BYTES_PER_STEP).
|
+ So this is (steps_to_skip << LOG2_BYTES_PER_STEP).
|
+ Then it needs further adjustment to compensate for the
|
+ distance between the PC value taken below (0f + PC_OFS)
|
+ and the first step's instructions (1f). */
|
+ rsb tmp1, tmp1, #((\steps << \log2_bytes_per_step) \
|
+ + ((1f - PC_OFS - 0f) \
|
+ >> (ARM_BX_ALIGN_LOG2 - \log2_bytes_per_step)))
|
+ /* Shifting down LOG2_BYTES_PER_STEP gives us the number of
|
+ steps to skip, then shifting up ARM_BX_ALIGN_LOG2 gives us
|
+ the (byte) distance to add to the PC. */
|
+0: add tmp1, pc, tmp1, lsl #(ARM_BX_ALIGN_LOG2 - \log2_bytes_per_step)
|
+ bx tmp1
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+1:
|
+ .endm
|
+
|
+ .macro dispatch_7_dword
|
+ dispatch_helper 7, 3
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 7
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 6
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 5
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 4
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 3
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 2
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 1
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ .purgem dispatch_step
|
+ .endm
|
+
|
+ .macro dispatch_15_word
|
+ dispatch_helper 15, 2
|
+ dispatch_step 15
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 14
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 13
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 12
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 11
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 10
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 9
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 8
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 7
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 6
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 5
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 4
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 3
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 2
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ dispatch_step 1
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ .purgem dispatch_step
|
+ .endm
|
+
|
+#endif
|
+
|
+#ifndef USE_NEON
|
+/* For bulk copies using GP registers. */
|
+#define A_l r2 /* Call-clobbered. */
|
+#define A_h r3 /* Call-clobbered. */
|
+#define B_l r4
|
+#define B_h r5
|
+#define C_l r6
|
+#define C_h r7
|
+/* Don't use the pair r8,r9 because in some EABI variants r9 is reserved. */
|
+#define D_l r10
|
+#define D_h r11
|
+#endif
|
+
|
+/* Number of lines ahead to pre-fetch data. If you change this the code
|
+ below will need adjustment to compensate. */
|
+
|
+#define prefetch_lines 5
|
+
|
+#ifdef USE_VFP
|
+ .macro cpy_line_vfp vreg, base
|
+ vstr \vreg, [dst, #\base]
|
+ vldr \vreg, [src, #\base]
|
+ vstr d0, [dst, #\base + 8]
|
+ vldr d0, [src, #\base + 8]
|
+ vstr d1, [dst, #\base + 16]
|
+ vldr d1, [src, #\base + 16]
|
+ vstr d2, [dst, #\base + 24]
|
+ vldr d2, [src, #\base + 24]
|
+ vstr \vreg, [dst, #\base + 32]
|
+ vldr \vreg, [src, #\base + prefetch_lines * 64 - 32]
|
+ vstr d0, [dst, #\base + 40]
|
+ vldr d0, [src, #\base + 40]
|
+ vstr d1, [dst, #\base + 48]
|
+ vldr d1, [src, #\base + 48]
|
+ vstr d2, [dst, #\base + 56]
|
+ vldr d2, [src, #\base + 56]
|
+ .endm
|
+
|
+ .macro cpy_tail_vfp vreg, base
|
+ vstr \vreg, [dst, #\base]
|
+ vldr \vreg, [src, #\base]
|
+ vstr d0, [dst, #\base + 8]
|
+ vldr d0, [src, #\base + 8]
|
+ vstr d1, [dst, #\base + 16]
|
+ vldr d1, [src, #\base + 16]
|
+ vstr d2, [dst, #\base + 24]
|
+ vldr d2, [src, #\base + 24]
|
+ vstr \vreg, [dst, #\base + 32]
|
+ vstr d0, [dst, #\base + 40]
|
+ vldr d0, [src, #\base + 40]
|
+ vstr d1, [dst, #\base + 48]
|
+ vldr d1, [src, #\base + 48]
|
+ vstr d2, [dst, #\base + 56]
|
+ vldr d2, [src, #\base + 56]
|
+ .endm
|
+#endif
|
+
|
+ .p2align 6
|
+ENTRY(memcpy)
|
+
|
+ mov dst, dstin /* Preserve dstin, we need to return it. */
|
+ cmp count, #64
|
+ bhs .Lcpy_not_short
|
+ /* Deal with small copies quickly by dropping straight into the
|
+ exit block. */
|
+
|
+.Ltail63unaligned:
|
+#ifdef USE_NEON
|
+ /* These need an extra layer of macro just to work around a
|
+ bug in the assembler's parser when an operand starts with
|
+ a {...}. https://sourceware.org/bugzilla/show_bug.cgi?id=15647
|
+ tracks that bug; it was not fixed as of binutils-2.23.2. */
|
+ .macro neon_load_d0 reg
|
+ vld1.8 {d0}, [\reg]!
|
+ .endm
|
+ .macro neon_store_d0 reg
|
+ vst1.8 {d0}, [\reg]!
|
+ .endm
|
+
|
+ and tmp1, count, #0x38
|
+ .macro dispatch_step i
|
+ neon_load_d0 src
|
+ neon_store_d0 dst
|
+ .endm
|
+ dispatch_7_dword
|
+
|
+ tst count, #4
|
+ ldrne tmp1, [src], #4
|
+ strne tmp1, [dst], #4
|
+#else
|
+ /* Copy up to 15 full words of data. May not be aligned. */
|
+ /* Cannot use VFP for unaligned data. */
|
+ and tmp1, count, #0x3c
|
+ add dst, dst, tmp1
|
+ add src, src, tmp1
|
+ /* Jump directly into the sequence below at the correct offset. */
|
+ .macro dispatch_step i
|
+ ldr tmp1, [src, #-(\i * 4)]
|
+ str tmp1, [dst, #-(\i * 4)]
|
+ .endm
|
+ dispatch_15_word
|
+#endif
|
+
|
+ lsls count, count, #31
|
+ ldrhcs tmp1, [src], #2
|
+ ldrbne src, [src] /* Src is dead, use as a scratch. */
|
+ strhcs tmp1, [dst], #2
|
+ strbne src, [dst]
|
+ bx lr
|
+
|
+.Lcpy_not_short:
|
+ /* At least 64 bytes to copy, but don't know the alignment yet. */
|
+ str tmp2, [sp, #-FRAME_SIZE]!
|
+ cfi_adjust_cfa_offset (FRAME_SIZE)
|
+ cfi_rel_offset (tmp2, 0)
|
+ cfi_remember_state
|
+ and tmp2, src, #7
|
+ and tmp1, dst, #7
|
+ cmp tmp1, tmp2
|
+ bne .Lcpy_notaligned
|
+
|
+#ifdef USE_VFP
|
+ /* Magic dust alert! Force VFP on Cortex-A9. Experiments show
|
+ that the FP pipeline is much better at streaming loads and
|
+ stores. This is outside the critical loop. */
|
+ vmov.f32 s0, s0
|
+#endif
|
+
|
+ /* SRC and DST have the same mutual 64-bit alignment, but we may
|
+ still need to pre-copy some bytes to get to natural alignment.
|
+ We bring SRC and DST into full 64-bit alignment. */
|
+ lsls tmp2, dst, #29
|
+ beq 1f
|
+ rsbs tmp2, tmp2, #0
|
+ sub count, count, tmp2, lsr #29
|
+ ldrmi tmp1, [src], #4
|
+ strmi tmp1, [dst], #4
|
+ lsls tmp2, tmp2, #2
|
+ ldrhcs tmp1, [src], #2
|
+ ldrbne tmp2, [src], #1
|
+ strhcs tmp1, [dst], #2
|
+ strbne tmp2, [dst], #1
|
+
|
+1:
|
+ subs tmp2, count, #64 /* Use tmp2 for count. */
|
+ blo .Ltail63aligned
|
+
|
+ cmp tmp2, #512
|
+ bhs .Lcpy_body_long
|
+
|
+.Lcpy_body_medium: /* Count in tmp2. */
|
+#ifdef USE_VFP
|
+1:
|
+ vldr d0, [src, #0]
|
+ subs tmp2, tmp2, #64
|
+ vldr d1, [src, #8]
|
+ vstr d0, [dst, #0]
|
+ vldr d0, [src, #16]
|
+ vstr d1, [dst, #8]
|
+ vldr d1, [src, #24]
|
+ vstr d0, [dst, #16]
|
+ vldr d0, [src, #32]
|
+ vstr d1, [dst, #24]
|
+ vldr d1, [src, #40]
|
+ vstr d0, [dst, #32]
|
+ vldr d0, [src, #48]
|
+ vstr d1, [dst, #40]
|
+ vldr d1, [src, #56]
|
+ vstr d0, [dst, #48]
|
+ add src, src, #64
|
+ vstr d1, [dst, #56]
|
+ add dst, dst, #64
|
+ bhs 1b
|
+ tst tmp2, #0x3f
|
+ beq .Ldone
|
+
|
+.Ltail63aligned: /* Count in tmp2. */
|
+ and tmp1, tmp2, #0x38
|
+ add dst, dst, tmp1
|
+ add src, src, tmp1
|
+ .macro dispatch_step i
|
+ vldr d0, [src, #-(\i * 8)]
|
+ vstr d0, [dst, #-(\i * 8)]
|
+ .endm
|
+ dispatch_7_dword
|
+#else
|
+ sub src, src, #8
|
+ sub dst, dst, #8
|
+1:
|
+ ldrd A_l, A_h, [src, #8]
|
+ strd A_l, A_h, [dst, #8]
|
+ ldrd A_l, A_h, [src, #16]
|
+ strd A_l, A_h, [dst, #16]
|
+ ldrd A_l, A_h, [src, #24]
|
+ strd A_l, A_h, [dst, #24]
|
+ ldrd A_l, A_h, [src, #32]
|
+ strd A_l, A_h, [dst, #32]
|
+ ldrd A_l, A_h, [src, #40]
|
+ strd A_l, A_h, [dst, #40]
|
+ ldrd A_l, A_h, [src, #48]
|
+ strd A_l, A_h, [dst, #48]
|
+ ldrd A_l, A_h, [src, #56]
|
+ strd A_l, A_h, [dst, #56]
|
+ ldrd A_l, A_h, [src, #64]!
|
+ strd A_l, A_h, [dst, #64]!
|
+ subs tmp2, tmp2, #64
|
+ bhs 1b
|
+ tst tmp2, #0x3f
|
+ bne 1f
|
+ ldr tmp2,[sp], #FRAME_SIZE
|
+ cfi_adjust_cfa_offset (-FRAME_SIZE)
|
+ cfi_restore (tmp2)
|
+ bx lr
|
+
|
+ cfi_restore_state
|
+ cfi_remember_state
|
+1:
|
+ add src, src, #8
|
+ add dst, dst, #8
|
+
|
+.Ltail63aligned: /* Count in tmp2. */
|
+ /* Copy up to 7 d-words of data. Similar to Ltail63unaligned, but
|
+ we know that the src and dest are 64-bit aligned so we can use
|
+ LDRD/STRD to improve efficiency. */
|
+ /* TMP2 is now negative, but we don't care about that. The bottom
|
+ six bits still tell us how many bytes are left to copy. */
|
+
|
+ and tmp1, tmp2, #0x38
|
+ add dst, dst, tmp1
|
+ add src, src, tmp1
|
+ .macro dispatch_step i
|
+ ldrd A_l, A_h, [src, #-(\i * 8)]
|
+ strd A_l, A_h, [dst, #-(\i * 8)]
|
+ .endm
|
+ dispatch_7_dword
|
+#endif
|
+
|
+ tst tmp2, #4
|
+ ldrne tmp1, [src], #4
|
+ strne tmp1, [dst], #4
|
+ lsls tmp2, tmp2, #31 /* Count (tmp2) now dead. */
|
+ ldrhcs tmp1, [src], #2
|
+ ldrbne tmp2, [src]
|
+ strhcs tmp1, [dst], #2
|
+ strbne tmp2, [dst]
|
+
|
+.Ldone:
|
+ ldr tmp2, [sp], #FRAME_SIZE
|
+ cfi_adjust_cfa_offset (-FRAME_SIZE)
|
+ cfi_restore (tmp2)
|
+ bx lr
|
+
|
+ cfi_restore_state
|
+ cfi_remember_state
|
+
|
+.Lcpy_body_long: /* Count in tmp2. */
|
+
|
+ /* Long copy. We know that there's at least (prefetch_lines * 64)
|
+ bytes to go. */
|
+#ifdef USE_VFP
|
+ /* Don't use PLD. Instead, read some data in advance of the current
|
+ copy position into a register. This should act like a PLD
|
+ operation but we won't have to repeat the transfer. */
|
+
|
+ vldr d3, [src, #0]
|
+ vldr d4, [src, #64]
|
+ vldr d5, [src, #128]
|
+ vldr d6, [src, #192]
|
+ vldr d7, [src, #256]
|
+
|
+ vldr d0, [src, #8]
|
+ vldr d1, [src, #16]
|
+ vldr d2, [src, #24]
|
+ add src, src, #32
|
+
|
+ subs tmp2, tmp2, #prefetch_lines * 64 * 2
|
+ blo 2f
|
+1:
|
+ cpy_line_vfp d3, 0
|
+ cpy_line_vfp d4, 64
|
+ cpy_line_vfp d5, 128
|
+ add dst, dst, #3 * 64
|
+ add src, src, #3 * 64
|
+ cpy_line_vfp d6, 0
|
+ cpy_line_vfp d7, 64
|
+ add dst, dst, #2 * 64
|
+ add src, src, #2 * 64
|
+ subs tmp2, tmp2, #prefetch_lines * 64
|
+ bhs 1b
|
+
|
+2:
|
+ cpy_tail_vfp d3, 0
|
+ cpy_tail_vfp d4, 64
|
+ cpy_tail_vfp d5, 128
|
+ add src, src, #3 * 64
|
+ add dst, dst, #3 * 64
|
+ cpy_tail_vfp d6, 0
|
+ vstr d7, [dst, #64]
|
+ vldr d7, [src, #64]
|
+ vstr d0, [dst, #64 + 8]
|
+ vldr d0, [src, #64 + 8]
|
+ vstr d1, [dst, #64 + 16]
|
+ vldr d1, [src, #64 + 16]
|
+ vstr d2, [dst, #64 + 24]
|
+ vldr d2, [src, #64 + 24]
|
+ vstr d7, [dst, #64 + 32]
|
+ add src, src, #96
|
+ vstr d0, [dst, #64 + 40]
|
+ vstr d1, [dst, #64 + 48]
|
+ vstr d2, [dst, #64 + 56]
|
+ add dst, dst, #128
|
+ add tmp2, tmp2, #prefetch_lines * 64
|
+ b .Lcpy_body_medium
|
+#else
|
+ /* Long copy. Use an SMS style loop to maximize the I/O
|
+ bandwidth of the core. We don't have enough spare registers
|
+ to synthesise prefetching, so use PLD operations. */
|
+ /* Pre-bias src and dst. */
|
+ sub src, src, #8
|
+ sub dst, dst, #8
|
+ pld [src, #8]
|
+ pld [src, #72]
|
+ subs tmp2, tmp2, #64
|
+ pld [src, #136]
|
+ ldrd A_l, A_h, [src, #8]
|
+ strd B_l, B_h, [sp, #8]
|
+ cfi_rel_offset (B_l, 8)
|
+ cfi_rel_offset (B_h, 12)
|
+ ldrd B_l, B_h, [src, #16]
|
+ strd C_l, C_h, [sp, #16]
|
+ cfi_rel_offset (C_l, 16)
|
+ cfi_rel_offset (C_h, 20)
|
+ ldrd C_l, C_h, [src, #24]
|
+ strd D_l, D_h, [sp, #24]
|
+ cfi_rel_offset (D_l, 24)
|
+ cfi_rel_offset (D_h, 28)
|
+ pld [src, #200]
|
+ ldrd D_l, D_h, [src, #32]!
|
+ b 1f
|
+ .p2align 6
|
+2:
|
+ pld [src, #232]
|
+ strd A_l, A_h, [dst, #40]
|
+ ldrd A_l, A_h, [src, #40]
|
+ strd B_l, B_h, [dst, #48]
|
+ ldrd B_l, B_h, [src, #48]
|
+ strd C_l, C_h, [dst, #56]
|
+ ldrd C_l, C_h, [src, #56]
|
+ strd D_l, D_h, [dst, #64]!
|
+ ldrd D_l, D_h, [src, #64]!
|
+ subs tmp2, tmp2, #64
|
+1:
|
+ strd A_l, A_h, [dst, #8]
|
+ ldrd A_l, A_h, [src, #8]
|
+ strd B_l, B_h, [dst, #16]
|
+ ldrd B_l, B_h, [src, #16]
|
+ strd C_l, C_h, [dst, #24]
|
+ ldrd C_l, C_h, [src, #24]
|
+ strd D_l, D_h, [dst, #32]
|
+ ldrd D_l, D_h, [src, #32]
|
+ bcs 2b
|
+ /* Save the remaining bytes and restore the callee-saved regs. */
|
+ strd A_l, A_h, [dst, #40]
|
+ add src, src, #40
|
+ strd B_l, B_h, [dst, #48]
|
+ ldrd B_l, B_h, [sp, #8]
|
+ cfi_restore (B_l)
|
+ cfi_restore (B_h)
|
+ strd C_l, C_h, [dst, #56]
|
+ ldrd C_l, C_h, [sp, #16]
|
+ cfi_restore (C_l)
|
+ cfi_restore (C_h)
|
+ strd D_l, D_h, [dst, #64]
|
+ ldrd D_l, D_h, [sp, #24]
|
+ cfi_restore (D_l)
|
+ cfi_restore (D_h)
|
+ add dst, dst, #72
|
+ tst tmp2, #0x3f
|
+ bne .Ltail63aligned
|
+ ldr tmp2, [sp], #FRAME_SIZE
|
+ cfi_adjust_cfa_offset (-FRAME_SIZE)
|
+ cfi_restore (tmp2)
|
+ bx lr
|
+#endif
|
+
|
+ cfi_restore_state
|
+ cfi_remember_state
|
+
|
+.Lcpy_notaligned:
|
+ pld [src, #0]
|
+ pld [src, #64]
|
+ /* There's at least 64 bytes to copy, but there is no mutual
|
+ alignment. */
|
+ /* Bring DST to 64-bit alignment. */
|
+ lsls tmp2, dst, #29
|
+ pld [src, #(2 * 64)]
|
+ beq 1f
|
+ rsbs tmp2, tmp2, #0
|
+ sub count, count, tmp2, lsr #29
|
+ ldrmi tmp1, [src], #4
|
+ strmi tmp1, [dst], #4
|
+ lsls tmp2, tmp2, #2
|
+ ldrbne tmp1, [src], #1
|
+ ldrhcs tmp2, [src], #2
|
+ strbne tmp1, [dst], #1
|
+ strhcs tmp2, [dst], #2
|
+1:
|
+ pld [src, #(3 * 64)]
|
+ subs count, count, #64
|
+ ldrlo tmp2, [sp], #FRAME_SIZE
|
+ blo .Ltail63unaligned
|
+ pld [src, #(4 * 64)]
|
+
|
+#ifdef USE_NEON
|
+ /* These need an extra layer of macro just to work around a
|
+ bug in the assembler's parser when an operand starts with
|
+ a {...}. */
|
+ .macro neon_load_multi reglist, basereg
|
+ vld1.8 {\reglist}, [\basereg]!
|
+ .endm
|
+ .macro neon_store_multi reglist, basereg
|
+ vst1.8 {\reglist}, [ALIGN (\basereg, 64)]!
|
+ .endm
|
+
|
+ neon_load_multi d0-d3, src
|
+ neon_load_multi d4-d7, src
|
+ subs count, count, #64
|
+ blo 2f
|
+1:
|
+ pld [src, #(4 * 64)]
|
+ neon_store_multi d0-d3, dst
|
+ neon_load_multi d0-d3, src
|
+ neon_store_multi d4-d7, dst
|
+ neon_load_multi d4-d7, src
|
+ subs count, count, #64
|
+ bhs 1b
|
+2:
|
+ neon_store_multi d0-d3, dst
|
+ neon_store_multi d4-d7, dst
|
+ ands count, count, #0x3f
|
+#else
|
+ /* Use an SMS style loop to maximize the I/O bandwidth. */
|
+ sub src, src, #4
|
+ sub dst, dst, #8
|
+ subs tmp2, count, #64 /* Use tmp2 for count. */
|
+ ldr A_l, [src, #4]
|
+ ldr A_h, [src, #8]
|
+ strd B_l, B_h, [sp, #8]
|
+ cfi_rel_offset (B_l, 8)
|
+ cfi_rel_offset (B_h, 12)
|
+ ldr B_l, [src, #12]
|
+ ldr B_h, [src, #16]
|
+ strd C_l, C_h, [sp, #16]
|
+ cfi_rel_offset (C_l, 16)
|
+ cfi_rel_offset (C_h, 20)
|
+ ldr C_l, [src, #20]
|
+ ldr C_h, [src, #24]
|
+ strd D_l, D_h, [sp, #24]
|
+ cfi_rel_offset (D_l, 24)
|
+ cfi_rel_offset (D_h, 28)
|
+ ldr D_l, [src, #28]
|
+ ldr D_h, [src, #32]!
|
+ b 1f
|
+ .p2align 6
|
+2:
|
+ pld [src, #(5 * 64) - (32 - 4)]
|
+ strd A_l, A_h, [dst, #40]
|
+ ldr A_l, [src, #36]
|
+ ldr A_h, [src, #40]
|
+ strd B_l, B_h, [dst, #48]
|
+ ldr B_l, [src, #44]
|
+ ldr B_h, [src, #48]
|
+ strd C_l, C_h, [dst, #56]
|
+ ldr C_l, [src, #52]
|
+ ldr C_h, [src, #56]
|
+ strd D_l, D_h, [dst, #64]!
|
+ ldr D_l, [src, #60]
|
+ ldr D_h, [src, #64]!
|
+ subs tmp2, tmp2, #64
|
+1:
|
+ strd A_l, A_h, [dst, #8]
|
+ ldr A_l, [src, #4]
|
+ ldr A_h, [src, #8]
|
+ strd B_l, B_h, [dst, #16]
|
+ ldr B_l, [src, #12]
|
+ ldr B_h, [src, #16]
|
+ strd C_l, C_h, [dst, #24]
|
+ ldr C_l, [src, #20]
|
+ ldr C_h, [src, #24]
|
+ strd D_l, D_h, [dst, #32]
|
+ ldr D_l, [src, #28]
|
+ ldr D_h, [src, #32]
|
+ bcs 2b
|
+
|
+ /* Save the remaining bytes and restore the callee-saved regs. */
|
+ strd A_l, A_h, [dst, #40]
|
+ add src, src, #36
|
+ strd B_l, B_h, [dst, #48]
|
+ ldrd B_l, B_h, [sp, #8]
|
+ cfi_restore (B_l)
|
+ cfi_restore (B_h)
|
+ strd C_l, C_h, [dst, #56]
|
+ ldrd C_l, C_h, [sp, #16]
|
+ cfi_restore (C_l)
|
+ cfi_restore (C_h)
|
+ strd D_l, D_h, [dst, #64]
|
+ ldrd D_l, D_h, [sp, #24]
|
+ cfi_restore (D_l)
|
+ cfi_restore (D_h)
|
+ add dst, dst, #72
|
+ ands count, tmp2, #0x3f
|
+#endif
|
+ ldr tmp2, [sp], #FRAME_SIZE
|
+ cfi_adjust_cfa_offset (-FRAME_SIZE)
|
+ cfi_restore (tmp2)
|
+ bne .Ltail63unaligned
|
+ bx lr
|
+
|
+END(memcpy)
|
+libc_hidden_builtin_def (memcpy)
|
diff --git a/libc/string/arm/glibc-neon/memmove.S b/libc/string/arm/glibc-neon/memmove.S
|
new file mode 100644
|
index 0000000..b01164a
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/memmove.S
|
@@ -0,0 +1,332 @@
|
+/* Copyright (C) 2006-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+/* Thumb requires excessive IT insns here. */
|
+#define NO_THUMB
|
+#include <sysdep.h>
|
+#include <arm-features.h>
|
+
|
+/*
|
+ * Data preload for architectures that support it (ARM V5TE and above)
|
+ */
|
+#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
|
+ && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
|
+ && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
|
+ && !defined (__ARM_ARCH_5T__))
|
+#define PLD(code...) code
|
+#else
|
+#define PLD(code...)
|
+#endif
|
+
|
+/*
|
+ * This can be used to enable code to cacheline align the source pointer.
|
+ * Experiments on tested architectures (StrongARM and XScale) didn't show
|
+ * this a worthwhile thing to do. That might be different in the future.
|
+ */
|
+//#define CALGN(code...) code
|
+#define CALGN(code...)
|
+
|
+/*
|
+ * Endian independent macros for shifting bytes within registers.
|
+ */
|
+#ifndef __ARMEB__
|
+#define PULL lsr
|
+#define PUSH lsl
|
+#else
|
+#define PULL lsl
|
+#define PUSH lsr
|
+#endif
|
+
|
+ .text
|
+ .syntax unified
|
+
|
+/*
|
+ * Prototype: void *memmove(void *dest, const void *src, size_t n);
|
+ *
|
+ * Note:
|
+ *
|
+ * If the memory regions don't overlap, we simply branch to memcpy which is
|
+ * normally a bit faster. Otherwise the copy is done going downwards.
|
+ */
|
+
|
+ENTRY(memmove)
|
+
|
+ subs ip, r0, r1
|
+ cmphi r2, ip
|
+#if !IS_IN (libc)
|
+ bls memcpy
|
+#else
|
+ bls HIDDEN_JUMPTARGET(memcpy)
|
+#endif
|
+
|
+ push {r0, r4, lr}
|
+ cfi_adjust_cfa_offset (12)
|
+ cfi_rel_offset (r4, 4)
|
+ cfi_rel_offset (lr, 8)
|
+
|
+ cfi_remember_state
|
+
|
+ add r1, r1, r2
|
+ add r0, r0, r2
|
+ subs r2, r2, #4
|
+ blo 8f
|
+ ands ip, r0, #3
|
+ PLD( pld [r1, #-4] )
|
+ bne 9f
|
+ ands ip, r1, #3
|
+ bne 10f
|
+
|
+1: subs r2, r2, #(28)
|
+ push {r5 - r8}
|
+ cfi_adjust_cfa_offset (16)
|
+ cfi_rel_offset (r5, 0)
|
+ cfi_rel_offset (r6, 4)
|
+ cfi_rel_offset (r7, 8)
|
+ cfi_rel_offset (r8, 12)
|
+ blo 5f
|
+
|
+ CALGN( ands ip, r1, #31 )
|
+ CALGN( sbcsne r4, ip, r2 ) @ C is always set here
|
+ CALGN( bcs 2f )
|
+ CALGN( adr r4, 6f )
|
+ CALGN( subs r2, r2, ip ) @ C is set here
|
+#ifndef ARM_ALWAYS_BX
|
+ CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
+#else
|
+ CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
|
+ CALGN( bx r4 )
|
+#endif
|
+
|
+ PLD( pld [r1, #-4] )
|
+2: PLD( cmp r2, #96 )
|
+ PLD( pld [r1, #-32] )
|
+ PLD( blo 4f )
|
+ PLD( pld [r1, #-64] )
|
+ PLD( pld [r1, #-96] )
|
+
|
+3: PLD( pld [r1, #-128] )
|
+4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
+ subs r2, r2, #32
|
+ stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
+ bhs 3b
|
+
|
+5: ands ip, r2, #28
|
+ rsb ip, ip, #32
|
+#ifndef ARM_ALWAYS_BX
|
+ /* C is always clear here. */
|
+ addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
+ b 7f
|
+#else
|
+ beq 7f
|
+ push {r10}
|
+ cfi_adjust_cfa_offset (4)
|
+ cfi_rel_offset (r10, 0)
|
+0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
+ /* If alignment is not perfect, then there will be some
|
+ padding (nop) instructions between this BX and label 6.
|
+ The computation above assumed that two instructions
|
+ later is exactly the right spot. */
|
+ add r10, #(6f - (0b + PC_OFS))
|
+ bx r10
|
+#endif
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+6: nop
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r3, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r4, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r5, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r6, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r7, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr r8, [r1, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ ldr lr, [r1, #-4]!
|
+
|
+#ifndef ARM_ALWAYS_BX
|
+ add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
+ nop
|
+#else
|
+0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
|
+ /* If alignment is not perfect, then there will be some
|
+ padding (nop) instructions between this BX and label 66.
|
+ The computation above assumed that two instructions
|
+ later is exactly the right spot. */
|
+ add r10, #(66f - (0b + PC_OFS))
|
+ bx r10
|
+#endif
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+66: nop
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r3, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r4, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r5, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r6, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r7, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str r8, [r0, #-4]!
|
+ .p2align ARM_BX_ALIGN_LOG2
|
+ str lr, [r0, #-4]!
|
+
|
+#ifdef ARM_ALWAYS_BX
|
+ pop {r10}
|
+ cfi_adjust_cfa_offset (-4)
|
+ cfi_restore (r10)
|
+#endif
|
+
|
+ CALGN( bcs 2b )
|
+
|
+7: pop {r5 - r8}
|
+ cfi_adjust_cfa_offset (-16)
|
+ cfi_restore (r5)
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ cfi_restore (r8)
|
+
|
+8: movs r2, r2, lsl #31
|
+ ldrbne r3, [r1, #-1]!
|
+ ldrbcs r4, [r1, #-1]!
|
+ ldrbcs ip, [r1, #-1]
|
+ strbne r3, [r0, #-1]!
|
+ strbcs r4, [r0, #-1]!
|
+ strbcs ip, [r0, #-1]
|
+
|
+#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
|
+ || defined (ARM_ALWAYS_BX))
|
+ pop {r0, r4, lr}
|
+ cfi_adjust_cfa_offset (-12)
|
+ cfi_restore (r4)
|
+ cfi_restore (lr)
|
+ bx lr
|
+#else
|
+ pop {r0, r4, pc}
|
+#endif
|
+
|
+ cfi_restore_state
|
+
|
+9: cmp ip, #2
|
+ ldrbgt r3, [r1, #-1]!
|
+ ldrbge r4, [r1, #-1]!
|
+ ldrb lr, [r1, #-1]!
|
+ strbgt r3, [r0, #-1]!
|
+ strbge r4, [r0, #-1]!
|
+ subs r2, r2, ip
|
+ strb lr, [r0, #-1]!
|
+ blo 8b
|
+ ands ip, r1, #3
|
+ beq 1b
|
+
|
+10: bic r1, r1, #3
|
+ cmp ip, #2
|
+ ldr r3, [r1, #0]
|
+ beq 17f
|
+ blt 18f
|
+
|
+
|
+ .macro backward_copy_shift push pull
|
+
|
+ subs r2, r2, #28
|
+ blo 14f
|
+
|
+ CALGN( ands ip, r1, #31 )
|
+ CALGN( rsb ip, ip, #32 )
|
+ CALGN( sbcsne r4, ip, r2 ) @ C is always set here
|
+ CALGN( subcc r2, r2, ip )
|
+ CALGN( bcc 15f )
|
+
|
+11: push {r5 - r8, r10}
|
+ cfi_adjust_cfa_offset (20)
|
+ cfi_rel_offset (r5, 0)
|
+ cfi_rel_offset (r6, 4)
|
+ cfi_rel_offset (r7, 8)
|
+ cfi_rel_offset (r8, 12)
|
+ cfi_rel_offset (r10, 16)
|
+
|
+ PLD( pld [r1, #-4] )
|
+ PLD( cmp r2, #96 )
|
+ PLD( pld [r1, #-32] )
|
+ PLD( blo 13f )
|
+ PLD( pld [r1, #-64] )
|
+ PLD( pld [r1, #-96] )
|
+
|
+12: PLD( pld [r1, #-128] )
|
+13: ldmdb r1!, {r7, r8, r10, ip}
|
+ mov lr, r3, PUSH #\push
|
+ subs r2, r2, #32
|
+ ldmdb r1!, {r3, r4, r5, r6}
|
+ orr lr, lr, ip, PULL #\pull
|
+ mov ip, ip, PUSH #\push
|
+ orr ip, ip, r10, PULL #\pull
|
+ mov r10, r10, PUSH #\push
|
+ orr r10, r10, r8, PULL #\pull
|
+ mov r8, r8, PUSH #\push
|
+ orr r8, r8, r7, PULL #\pull
|
+ mov r7, r7, PUSH #\push
|
+ orr r7, r7, r6, PULL #\pull
|
+ mov r6, r6, PUSH #\push
|
+ orr r6, r6, r5, PULL #\pull
|
+ mov r5, r5, PUSH #\push
|
+ orr r5, r5, r4, PULL #\pull
|
+ mov r4, r4, PUSH #\push
|
+ orr r4, r4, r3, PULL #\pull
|
+ stmdb r0!, {r4 - r8, r10, ip, lr}
|
+ bhs 12b
|
+
|
+ pop {r5 - r8, r10}
|
+ cfi_adjust_cfa_offset (-20)
|
+ cfi_restore (r5)
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ cfi_restore (r8)
|
+ cfi_restore (r10)
|
+
|
+14: ands ip, r2, #28
|
+ beq 16f
|
+
|
+15: mov lr, r3, PUSH #\push
|
+ ldr r3, [r1, #-4]!
|
+ subs ip, ip, #4
|
+ orr lr, lr, r3, PULL #\pull
|
+ str lr, [r0, #-4]!
|
+ bgt 15b
|
+ CALGN( cmp r2, #0 )
|
+ CALGN( bge 11b )
|
+
|
+16: add r1, r1, #(\pull / 8)
|
+ b 8b
|
+
|
+ .endm
|
+
|
+
|
+ backward_copy_shift push=8 pull=24
|
+
|
+17: backward_copy_shift push=16 pull=16
|
+
|
+18: backward_copy_shift push=24 pull=8
|
+
|
+
|
+END(memmove)
|
+libc_hidden_builtin_def (memmove)
|
diff --git a/libc/string/arm/glibc-neon/memset.S b/libc/string/arm/glibc-neon/memset.S
|
new file mode 100644
|
index 0000000..dc89ca7
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/memset.S
|
@@ -0,0 +1,68 @@
|
+/* Copyright (C) 1998-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+/* Thumb requires excessive IT insns here. */
|
+#define NO_THUMB
|
+#include <sysdep.h>
|
+
|
+ .text
|
+ .syntax unified
|
+
|
+/* void *memset (dstpp, c, len) */
|
+
|
+ENTRY(memset)
|
+ mov r3, r0
|
+ cmp r2, #8
|
+ bcc 2f @ less than 8 bytes to move
|
+
|
+1:
|
+ tst r3, #3 @ aligned yet?
|
+ strbne r1, [r3], #1
|
+ subne r2, r2, #1
|
+ bne 1b
|
+
|
+ and r1, r1, #255 @ clear any sign bits
|
+ orr r1, r1, r1, lsl $8
|
+ orr r1, r1, r1, lsl $16
|
+ mov ip, r1
|
+
|
+1:
|
+ subs r2, r2, #8
|
+ stmiacs r3!, {r1, ip} @ store up to 32 bytes per loop iteration
|
+ subscs r2, r2, #8
|
+ stmiacs r3!, {r1, ip}
|
+ subscs r2, r2, #8
|
+ stmiacs r3!, {r1, ip}
|
+ subscs r2, r2, #8
|
+ stmiacs r3!, {r1, ip}
|
+ bcs 1b
|
+
|
+ and r2, r2, #7
|
+2:
|
+ subs r2, r2, #1 @ store up to 4 bytes per loop iteration
|
+ strbcs r1, [r3], #1
|
+ subscs r2, r2, #1
|
+ strbcs r1, [r3], #1
|
+ subscs r2, r2, #1
|
+ strbcs r1, [r3], #1
|
+ subscs r2, r2, #1
|
+ strbcs r1, [r3], #1
|
+ bcs 2b
|
+
|
+ DO_RET(lr)
|
+END(memset)
|
+libc_hidden_builtin_def (memset)
|
diff --git a/libc/string/arm/glibc-neon/strcmp.S b/libc/string/arm/glibc-neon/strcmp.S
|
new file mode 100644
|
index 0000000..98a3c6c
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/strcmp.S
|
@@ -0,0 +1,504 @@
|
+/* strcmp implementation for ARMv7-A, optimized for Cortex-A15.
|
+ Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#include <arm-features.h>
|
+#include <sysdep.h>
|
+
|
+/* Implementation of strcmp for ARMv7 when DSP instructions are
|
+ available. Use ldrd to support wider loads, provided the data
|
+ is sufficiently aligned. Use saturating arithmetic to optimize
|
+ the compares. */
|
+
|
+/* Build Options:
|
+ STRCMP_PRECHECK: Run a quick pre-check of the first byte in the
|
+ string. If comparing completely random strings the pre-check will
|
+ save time, since there is a very high probability of a mismatch in
|
+ the first character: we save significant overhead if this is the
|
+ common case. However, if strings are likely to be identical (e.g.
|
+ because we're verifying a hit in a hash table), then this check
|
+ is largely redundant. */
|
+
|
+#define STRCMP_PRECHECK 1
|
+
|
+ .syntax unified
|
+
|
+#ifdef __ARM_BIG_ENDIAN
|
+# define S2LO lsl
|
+# define S2LOEQ lsleq
|
+# define S2HI lsr
|
+# define MSB 0x000000ff
|
+# define LSB 0xff000000
|
+# define BYTE0_OFFSET 24
|
+# define BYTE1_OFFSET 16
|
+# define BYTE2_OFFSET 8
|
+# define BYTE3_OFFSET 0
|
+#else /* not __ARM_BIG_ENDIAN */
|
+# define S2LO lsr
|
+# define S2LOEQ lsreq
|
+# define S2HI lsl
|
+# define BYTE0_OFFSET 0
|
+# define BYTE1_OFFSET 8
|
+# define BYTE2_OFFSET 16
|
+# define BYTE3_OFFSET 24
|
+# define MSB 0xff000000
|
+# define LSB 0x000000ff
|
+#endif /* not __ARM_BIG_ENDIAN */
|
+
|
+/* Parameters and result. */
|
+#define src1 r0
|
+#define src2 r1
|
+#define result r0 /* Overlaps src1. */
|
+
|
+/* Internal variables. */
|
+#define tmp1 r4
|
+#define tmp2 r5
|
+#define const_m1 r12
|
+
|
+/* Additional internal variables for 64-bit aligned data. */
|
+#define data1a r2
|
+#define data1b r3
|
+#define data2a r6
|
+#define data2b r7
|
+#define syndrome_a tmp1
|
+#define syndrome_b tmp2
|
+
|
+/* Additional internal variables for 32-bit aligned data. */
|
+#define data1 r2
|
+#define data2 r3
|
+#define syndrome tmp2
|
+
|
+
|
+ .thumb
|
+
|
+/* In Thumb code we can't use MVN with a register shift, but we do have ORN. */
|
+.macro prepare_mask mask_reg, nbits_reg
|
+ S2HI \mask_reg, const_m1, \nbits_reg
|
+.endm
|
+.macro apply_mask data_reg, mask_reg
|
+ orn \data_reg, \data_reg, \mask_reg
|
+.endm
|
+
|
+ /* Macro to compute and return the result value for word-aligned
|
+ cases. */
|
+ .macro strcmp_epilogue_aligned synd d1 d2 restore_r6
|
+#ifdef __ARM_BIG_ENDIAN
|
+ /* If data1 contains a zero byte, then syndrome will contain a 1 in
|
+ bit 7 of that byte. Otherwise, the highest set bit in the
|
+ syndrome will highlight the first different bit. It is therefore
|
+ sufficient to extract the eight bits starting with the syndrome
|
+ bit. */
|
+ clz tmp1, \synd
|
+ lsl r1, \d2, tmp1
|
+ .if \restore_r6
|
+ ldrd r6, r7, [sp, #8]
|
+ .endif
|
+ lsl \d1, \d1, tmp1
|
+ lsr result, \d1, #24
|
+ ldrd r4, r5, [sp], #16
|
+ cfi_remember_state
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ sub result, result, r1, lsr #24
|
+ bx lr
|
+#else
|
+ /* To use the big-endian trick we'd have to reverse all three words.
|
+ that's slower than this approach. */
|
+ rev \synd, \synd
|
+ clz tmp1, \synd
|
+ bic tmp1, tmp1, #7
|
+ lsr r1, \d2, tmp1
|
+ .if \restore_r6
|
+ ldrd r6, r7, [sp, #8]
|
+ .endif
|
+ lsr \d1, \d1, tmp1
|
+ and result, \d1, #255
|
+ and r1, r1, #255
|
+ ldrd r4, r5, [sp], #16
|
+ cfi_remember_state
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ sub result, result, r1
|
+
|
+ bx lr
|
+#endif
|
+ .endm
|
+
|
+ .text
|
+ .p2align 5
|
+.Lstrcmp_start_addr:
|
+#if STRCMP_PRECHECK == 1
|
+.Lfastpath_exit:
|
+ sub r0, r2, r3
|
+ bx lr
|
+ nop
|
+#endif
|
+ENTRY (strcmp)
|
+#if STRCMP_PRECHECK == 1
|
+ ldrb r2, [src1]
|
+ ldrb r3, [src2]
|
+ cmp r2, #1
|
+ it cs
|
+ cmpcs r2, r3
|
+ bne .Lfastpath_exit
|
+#endif
|
+ strd r4, r5, [sp, #-16]!
|
+ cfi_def_cfa_offset (16)
|
+ cfi_offset (r4, -16)
|
+ cfi_offset (r5, -12)
|
+ orr tmp1, src1, src2
|
+ strd r6, r7, [sp, #8]
|
+ cfi_offset (r6, -8)
|
+ cfi_offset (r7, -4)
|
+ mvn const_m1, #0
|
+ lsl r2, tmp1, #29
|
+ cbz r2, .Lloop_aligned8
|
+
|
+.Lnot_aligned:
|
+ eor tmp1, src1, src2
|
+ tst tmp1, #7
|
+ bne .Lmisaligned8
|
+
|
+ /* Deal with mutual misalignment by aligning downwards and then
|
+ masking off the unwanted loaded data to prevent a difference. */
|
+ and tmp1, src1, #7
|
+ bic src1, src1, #7
|
+ and tmp2, tmp1, #3
|
+ bic src2, src2, #7
|
+ lsl tmp2, tmp2, #3 /* Bytes -> bits. */
|
+ ldrd data1a, data1b, [src1], #16
|
+ tst tmp1, #4
|
+ ldrd data2a, data2b, [src2], #16
|
+ prepare_mask tmp1, tmp2
|
+ apply_mask data1a, tmp1
|
+ apply_mask data2a, tmp1
|
+ beq .Lstart_realigned8
|
+ apply_mask data1b, tmp1
|
+ mov data1a, const_m1
|
+ apply_mask data2b, tmp1
|
+ mov data2a, const_m1
|
+ b .Lstart_realigned8
|
+
|
+ /* Unwind the inner loop by a factor of 2, giving 16 bytes per
|
+ pass. */
|
+ .p2align 5,,12 /* Don't start in the tail bytes of a cache line. */
|
+ .p2align 2 /* Always word aligned. */
|
+.Lloop_aligned8:
|
+ ldrd data1a, data1b, [src1], #16
|
+ ldrd data2a, data2b, [src2], #16
|
+.Lstart_realigned8:
|
+ uadd8 syndrome_b, data1a, const_m1 /* Only want GE bits, */
|
+ eor syndrome_a, data1a, data2a
|
+ sel syndrome_a, syndrome_a, const_m1
|
+ cbnz syndrome_a, .Ldiff_in_a
|
+ uadd8 syndrome_b, data1b, const_m1 /* Only want GE bits. */
|
+ eor syndrome_b, data1b, data2b
|
+ sel syndrome_b, syndrome_b, const_m1
|
+ cbnz syndrome_b, .Ldiff_in_b
|
+
|
+ ldrd data1a, data1b, [src1, #-8]
|
+ ldrd data2a, data2b, [src2, #-8]
|
+ uadd8 syndrome_b, data1a, const_m1 /* Only want GE bits, */
|
+ eor syndrome_a, data1a, data2a
|
+ sel syndrome_a, syndrome_a, const_m1
|
+ uadd8 syndrome_b, data1b, const_m1 /* Only want GE bits. */
|
+ eor syndrome_b, data1b, data2b
|
+ sel syndrome_b, syndrome_b, const_m1
|
+ /* Can't use CBZ for backwards branch. */
|
+ orrs syndrome_b, syndrome_b, syndrome_a /* Only need if s_a == 0 */
|
+ beq .Lloop_aligned8
|
+
|
+.Ldiff_found:
|
+ cbnz syndrome_a, .Ldiff_in_a
|
+
|
+.Ldiff_in_b:
|
+ strcmp_epilogue_aligned syndrome_b, data1b, data2b 1
|
+
|
+.Ldiff_in_a:
|
+ cfi_restore_state
|
+ strcmp_epilogue_aligned syndrome_a, data1a, data2a 1
|
+
|
+ cfi_restore_state
|
+.Lmisaligned8:
|
+ tst tmp1, #3
|
+ bne .Lmisaligned4
|
+ ands tmp1, src1, #3
|
+ bne .Lmutual_align4
|
+
|
+ /* Unrolled by a factor of 2, to reduce the number of post-increment
|
+ operations. */
|
+.Lloop_aligned4:
|
+ ldr data1, [src1], #8
|
+ ldr data2, [src2], #8
|
+.Lstart_realigned4:
|
+ uadd8 syndrome, data1, const_m1 /* Only need GE bits. */
|
+ eor syndrome, data1, data2
|
+ sel syndrome, syndrome, const_m1
|
+ cbnz syndrome, .Laligned4_done
|
+ ldr data1, [src1, #-4]
|
+ ldr data2, [src2, #-4]
|
+ uadd8 syndrome, data1, const_m1
|
+ eor syndrome, data1, data2
|
+ sel syndrome, syndrome, const_m1
|
+ cmp syndrome, #0
|
+ beq .Lloop_aligned4
|
+
|
+.Laligned4_done:
|
+ strcmp_epilogue_aligned syndrome, data1, data2, 0
|
+
|
+.Lmutual_align4:
|
+ cfi_restore_state
|
+ /* Deal with mutual misalignment by aligning downwards and then
|
+ masking off the unwanted loaded data to prevent a difference. */
|
+ lsl tmp1, tmp1, #3 /* Bytes -> bits. */
|
+ bic src1, src1, #3
|
+ ldr data1, [src1], #8
|
+ bic src2, src2, #3
|
+ ldr data2, [src2], #8
|
+
|
+ prepare_mask tmp1, tmp1
|
+ apply_mask data1, tmp1
|
+ apply_mask data2, tmp1
|
+ b .Lstart_realigned4
|
+
|
+.Lmisaligned4:
|
+ ands tmp1, src1, #3
|
+ beq .Lsrc1_aligned
|
+ sub src2, src2, tmp1
|
+ bic src1, src1, #3
|
+ lsls tmp1, tmp1, #31
|
+ ldr data1, [src1], #4
|
+ beq .Laligned_m2
|
+ bcs .Laligned_m1
|
+
|
+#if STRCMP_PRECHECK == 0
|
+ ldrb data2, [src2, #1]
|
+ uxtb tmp1, data1, ror #BYTE1_OFFSET
|
+ subs tmp1, tmp1, data2
|
+ bne .Lmisaligned_exit
|
+ cbz data2, .Lmisaligned_exit
|
+
|
+.Laligned_m2:
|
+ ldrb data2, [src2, #2]
|
+ uxtb tmp1, data1, ror #BYTE2_OFFSET
|
+ subs tmp1, tmp1, data2
|
+ bne .Lmisaligned_exit
|
+ cbz data2, .Lmisaligned_exit
|
+
|
+.Laligned_m1:
|
+ ldrb data2, [src2, #3]
|
+ uxtb tmp1, data1, ror #BYTE3_OFFSET
|
+ subs tmp1, tmp1, data2
|
+ bne .Lmisaligned_exit
|
+ add src2, src2, #4
|
+ cbnz data2, .Lsrc1_aligned
|
+#else /* STRCMP_PRECHECK */
|
+ /* If we've done the pre-check, then we don't need to check the
|
+ first byte again here. */
|
+ ldrb data2, [src2, #2]
|
+ uxtb tmp1, data1, ror #BYTE2_OFFSET
|
+ subs tmp1, tmp1, data2
|
+ bne .Lmisaligned_exit
|
+ cbz data2, .Lmisaligned_exit
|
+
|
+.Laligned_m2:
|
+ ldrb data2, [src2, #3]
|
+ uxtb tmp1, data1, ror #BYTE3_OFFSET
|
+ subs tmp1, tmp1, data2
|
+ bne .Lmisaligned_exit
|
+ cbnz data2, .Laligned_m1
|
+#endif
|
+
|
+.Lmisaligned_exit:
|
+ mov result, tmp1
|
+ ldr r4, [sp], #16
|
+ cfi_remember_state
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ bx lr
|
+
|
+#if STRCMP_PRECHECK == 1
|
+.Laligned_m1:
|
+ add src2, src2, #4
|
+#endif
|
+.Lsrc1_aligned:
|
+ cfi_restore_state
|
+ /* src1 is word aligned, but src2 has no common alignment
|
+ with it. */
|
+ ldr data1, [src1], #4
|
+ lsls tmp1, src2, #31 /* C=src2[1], Z=src2[0]. */
|
+
|
+ bic src2, src2, #3
|
+ ldr data2, [src2], #4
|
+ bhi .Loverlap1 /* C=1, Z=0 => src2[1:0] = 0b11. */
|
+ bcs .Loverlap2 /* C=1, Z=1 => src2[1:0] = 0b10. */
|
+
|
+ /* (overlap3) C=0, Z=0 => src2[1:0] = 0b01. */
|
+.Loverlap3:
|
+ bic tmp1, data1, #MSB
|
+ uadd8 syndrome, data1, const_m1
|
+ eors syndrome, tmp1, data2, S2LO #8
|
+ sel syndrome, syndrome, const_m1
|
+ bne 4f
|
+ cbnz syndrome, 5f
|
+ ldr data2, [src2], #4
|
+ eor tmp1, tmp1, data1
|
+ cmp tmp1, data2, S2HI #24
|
+ bne 6f
|
+ ldr data1, [src1], #4
|
+ b .Loverlap3
|
+4:
|
+ S2LO data2, data2, #8
|
+ b .Lstrcmp_tail
|
+
|
+5:
|
+ bics syndrome, syndrome, #MSB
|
+ bne .Lstrcmp_done_equal
|
+
|
+ /* We can only get here if the MSB of data1 contains 0, so
|
+ fast-path the exit. */
|
+ ldrb result, [src2]
|
+ ldrd r4, r5, [sp], #16
|
+ cfi_remember_state
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ /* R6/7 Not used in this sequence. */
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ neg result, result
|
+ bx lr
|
+
|
+6:
|
+ cfi_restore_state
|
+ S2LO data1, data1, #24
|
+ and data2, data2, #LSB
|
+ b .Lstrcmp_tail
|
+
|
+ .p2align 5,,12 /* Ensure at least 3 instructions in cache line. */
|
+.Loverlap2:
|
+ and tmp1, data1, const_m1, S2LO #16
|
+ uadd8 syndrome, data1, const_m1
|
+ eors syndrome, tmp1, data2, S2LO #16
|
+ sel syndrome, syndrome, const_m1
|
+ bne 4f
|
+ cbnz syndrome, 5f
|
+ ldr data2, [src2], #4
|
+ eor tmp1, tmp1, data1
|
+ cmp tmp1, data2, S2HI #16
|
+ bne 6f
|
+ ldr data1, [src1], #4
|
+ b .Loverlap2
|
+4:
|
+ S2LO data2, data2, #16
|
+ b .Lstrcmp_tail
|
+5:
|
+ ands syndrome, syndrome, const_m1, S2LO #16
|
+ bne .Lstrcmp_done_equal
|
+
|
+ ldrh data2, [src2]
|
+ S2LO data1, data1, #16
|
+#ifdef __ARM_BIG_ENDIAN
|
+ lsl data2, data2, #16
|
+#endif
|
+ b .Lstrcmp_tail
|
+
|
+6:
|
+ S2LO data1, data1, #16
|
+ and data2, data2, const_m1, S2LO #16
|
+ b .Lstrcmp_tail
|
+
|
+ .p2align 5,,12 /* Ensure at least 3 instructions in cache line. */
|
+.Loverlap1:
|
+ and tmp1, data1, #LSB
|
+ uadd8 syndrome, data1, const_m1
|
+ eors syndrome, tmp1, data2, S2LO #24
|
+ sel syndrome, syndrome, const_m1
|
+ bne 4f
|
+ cbnz syndrome, 5f
|
+ ldr data2, [src2], #4
|
+ eor tmp1, tmp1, data1
|
+ cmp tmp1, data2, S2HI #8
|
+ bne 6f
|
+ ldr data1, [src1], #4
|
+ b .Loverlap1
|
+4:
|
+ S2LO data2, data2, #24
|
+ b .Lstrcmp_tail
|
+5:
|
+ tst syndrome, #LSB
|
+ bne .Lstrcmp_done_equal
|
+ ldr data2, [src2]
|
+6:
|
+ S2LO data1, data1, #8
|
+ bic data2, data2, #MSB
|
+ b .Lstrcmp_tail
|
+
|
+.Lstrcmp_done_equal:
|
+ mov result, #0
|
+ ldrd r4, r5, [sp], #16
|
+ cfi_remember_state
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ /* R6/7 not used in this sequence. */
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ bx lr
|
+
|
+.Lstrcmp_tail:
|
+ cfi_restore_state
|
+#ifndef __ARM_BIG_ENDIAN
|
+ rev data1, data1
|
+ rev data2, data2
|
+ /* Now everything looks big-endian... */
|
+#endif
|
+ uadd8 tmp1, data1, const_m1
|
+ eor tmp1, data1, data2
|
+ sel syndrome, tmp1, const_m1
|
+ clz tmp1, syndrome
|
+ lsl data1, data1, tmp1
|
+ lsl data2, data2, tmp1
|
+ lsr result, data1, #24
|
+ ldrd r4, r5, [sp], #16
|
+ cfi_def_cfa_offset (0)
|
+ cfi_restore (r4)
|
+ cfi_restore (r5)
|
+ /* R6/7 not used in this sequence. */
|
+ cfi_restore (r6)
|
+ cfi_restore (r7)
|
+ sub result, result, data2, lsr #24
|
+ bx lr
|
+END (strcmp)
|
+libc_hidden_builtin_def (strcmp)
|
+
|
+# From ../strcmp.S
|
+#include <features.h>
|
+
|
+#ifndef __UCLIBC_HAS_LOCALE__
|
+strong_alias(strcmp,strcoll)
|
+libc_hidden_def(strcoll)
|
+#endif
|
diff --git a/libc/string/arm/glibc-neon/strlen.S b/libc/string/arm/glibc-neon/strlen.S
|
new file mode 100644
|
index 0000000..dbb6344
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/strlen.S
|
@@ -0,0 +1,76 @@
|
+/* Copyright (C) 1998-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+/* Thumb requires excessive IT insns here. */
|
+#define NO_THUMB
|
+#include <sysdep.h>
|
+
|
+/* size_t strlen(const char *S)
|
+ * entry: r0 -> string
|
+ * exit: r0 = len
|
+ */
|
+
|
+ .syntax unified
|
+ .text
|
+
|
+ENTRY(strlen)
|
+ bic r1, r0, $3 @ addr of word containing first byte
|
+ ldr r2, [r1], $4 @ get the first word
|
+ ands r3, r0, $3 @ how many bytes are duff?
|
+ rsb r0, r3, $0 @ get - that number into counter.
|
+ beq Laligned @ skip into main check routine if no
|
+ @ more
|
+#ifdef __ARMEB__
|
+ orr r2, r2, $0xff000000 @ set this byte to non-zero
|
+ subs r3, r3, $1 @ any more to do?
|
+ orrgt r2, r2, $0x00ff0000 @ if so, set this byte
|
+ subs r3, r3, $1 @ more?
|
+ orrgt r2, r2, $0x0000ff00 @ then set.
|
+#else
|
+ orr r2, r2, $0x000000ff @ set this byte to non-zero
|
+ subs r3, r3, $1 @ any more to do?
|
+ orrgt r2, r2, $0x0000ff00 @ if so, set this byte
|
+ subs r3, r3, $1 @ more?
|
+ orrgt r2, r2, $0x00ff0000 @ then set.
|
+#endif
|
+Laligned: @ here, we have a word in r2. Does it
|
+ tst r2, $0x000000ff @ contain any zeroes?
|
+ tstne r2, $0x0000ff00 @
|
+ tstne r2, $0x00ff0000 @
|
+ tstne r2, $0xff000000 @
|
+ addne r0, r0, $4 @ if not, the string is 4 bytes longer
|
+ ldrne r2, [r1], $4 @ and we continue to the next word
|
+ bne Laligned @
|
+Llastword: @ drop through to here once we find a
|
+#ifdef __ARMEB__
|
+ tst r2, $0xff000000 @ word that has a zero byte in it
|
+ addne r0, r0, $1 @
|
+ tstne r2, $0x00ff0000 @ and add up to 3 bytes on to it
|
+ addne r0, r0, $1 @
|
+ tstne r2, $0x0000ff00 @ (if first three all non-zero, 4th
|
+ addne r0, r0, $1 @ must be zero)
|
+#else
|
+ tst r2, $0x000000ff @ word that has a zero byte in it
|
+ addne r0, r0, $1 @
|
+ tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it
|
+ addne r0, r0, $1 @
|
+ tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th
|
+ addne r0, r0, $1 @ must be zero)
|
+#endif
|
+ DO_RET(lr)
|
+END(strlen)
|
+libc_hidden_builtin_def (strlen)
|
diff --git a/libc/string/arm/glibc-neon/sysdep.h b/libc/string/arm/glibc-neon/sysdep.h
|
new file mode 100644
|
index 0000000..cceb4a9
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/sysdep.h
|
@@ -0,0 +1,339 @@
|
+/* Assembler macros for ARM.
|
+ Copyright (C) 1997-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library. If not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#include <sysdeps/generic/sysdep.h>
|
+#include <features.h>
|
+
|
+#ifndef __ASSEMBLER__
|
+# include <stdint.h>
|
+#else
|
+# include <arm-features.h>
|
+#endif
|
+
|
+/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
|
+#ifndef __ARM_ARCH
|
+# ifdef __ARM_ARCH_2__
|
+# define __ARM_ARCH 2
|
+# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__)
|
+# define __ARM_ARCH 3
|
+# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__)
|
+# define __ARM_ARCH 4
|
+# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \
|
+ || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
|
+ || defined(__ARM_ARCH_5TEJ__)
|
+# define __ARM_ARCH 5
|
+# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
+ || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
|
+ || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
|
+# define __ARM_ARCH 6
|
+# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|
+ || defined(__ARM_ARCH_7EM__)
|
+# define __ARM_ARCH 7
|
+# else
|
+# error unknown arm architecture
|
+# endif
|
+#endif
|
+
|
+#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
|
+# define ARCH_HAS_BX
|
+#endif
|
+#if __ARM_ARCH > 4
|
+# define ARCH_HAS_BLX
|
+#endif
|
+#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
|
+# define ARCH_HAS_HARD_TP
|
+#endif
|
+#if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__)
|
+# define ARCH_HAS_T2
|
+#endif
|
+
|
+#ifdef __ASSEMBLER__
|
+
|
+/* Syntactic details of assembler. */
|
+
|
+#define ALIGNARG(log2) log2
|
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
+
|
+#define PLTJMP(_x) _x##(PLT)
|
+
|
+#ifdef ARCH_HAS_BX
|
+# define BX(R) bx R
|
+# define BXC(C, R) bx##C R
|
+# ifdef ARCH_HAS_BLX
|
+# define BLX(R) blx R
|
+# else
|
+# define BLX(R) mov lr, pc; bx R
|
+# endif
|
+#else
|
+# define BX(R) mov pc, R
|
+# define BXC(C, R) mov##C pc, R
|
+# define BLX(R) mov lr, pc; mov pc, R
|
+#endif
|
+
|
+#define DO_RET(R) BX(R)
|
+#define RETINSTR(C, R) BXC(C, R)
|
+
|
+/* Define an entry point visible from C. */
|
+#define ENTRY(name) \
|
+ .globl C_SYMBOL_NAME(name); \
|
+ .type C_SYMBOL_NAME(name),%function; \
|
+ .align ALIGNARG(4); \
|
+ C_LABEL(name) \
|
+ CFI_SECTIONS; \
|
+ cfi_startproc; \
|
+ CALL_MCOUNT
|
+
|
+#define CFI_SECTIONS \
|
+ .cfi_sections .debug_frame
|
+
|
+#undef END
|
+#define END(name) \
|
+ cfi_endproc; \
|
+ ASM_SIZE_DIRECTIVE(name)
|
+
|
+/* If compiled for profiling, call `mcount' at the start of each function. */
|
+#ifdef PROF
|
+/* Call __gnu_mcount_nc (GCC >= 4.4). */
|
+#define CALL_MCOUNT \
|
+ push {lr}; \
|
+ cfi_adjust_cfa_offset (4); \
|
+ cfi_rel_offset (lr, 0); \
|
+ bl PLTJMP(mcount); \
|
+ cfi_adjust_cfa_offset (-4); \
|
+ cfi_restore (lr)
|
+#else
|
+#define CALL_MCOUNT /* Do nothing. */
|
+#endif
|
+
|
+/* Since C identifiers are not normally prefixed with an underscore
|
+ on this system, the asm identifier `syscall_error' intrudes on the
|
+ C name space. Make sure we use an innocuous name. */
|
+#define syscall_error __syscall_error
|
+#define mcount __gnu_mcount_nc
|
+
|
+/* Tag_ABI_align8_preserved: This code preserves 8-byte
|
+ alignment in any callee. */
|
+ .eabi_attribute 25, 1
|
+/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
|
+ the caller. */
|
+ .eabi_attribute 24, 1
|
+
|
+/* The thumb2 encoding is reasonably complete. Unless suppressed, use it. */
|
+ .syntax unified
|
+# if defined(__thumb2__) && !defined(NO_THUMB)
|
+ .thumb
|
+#else
|
+# undef __thumb__
|
+# undef __thumb2__
|
+ .arm
|
+# endif
|
+
|
+/* Load or store to/from address X + Y into/from R, (maybe) using T.
|
+ X or Y can use T freely; T can be R if OP is a load. The first
|
+ version eschews the two-register addressing mode, while the
|
+ second version uses it. */
|
+# define LDST_INDEXED_NOINDEX(OP, R, T, X, Y) \
|
+ add T, X, Y; \
|
+ OP R, [T]
|
+# define LDST_INDEXED_INDEX(OP, R, X, Y) \
|
+ OP R, [X, Y]
|
+
|
+# ifdef ARM_NO_INDEX_REGISTER
|
+/* We're never using the two-register addressing mode, so this
|
+ always uses an intermediate add. */
|
+# define LDST_INDEXED(OP, R, T, X, Y) LDST_INDEXED_NOINDEX (OP, R, T, X, Y)
|
+# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
|
+# else
|
+/* The two-register addressing mode is OK, except on Thumb with pc. */
|
+# define LDST_INDEXED(OP, R, T, X, Y) LDST_INDEXED_INDEX (OP, R, X, Y)
|
+# ifdef __thumb2__
|
+# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_NOINDEX (OP, R, T, pc, X)
|
+# else
|
+# define LDST_PC_INDEXED(OP, R, T, X) LDST_INDEXED_INDEX (OP, R, pc, X)
|
+# endif
|
+# endif
|
+
|
+/* Load or store to/from a pc-relative EXPR into/from R, using T. */
|
+# ifdef __thumb2__
|
+# define LDST_PCREL(OP, R, T, EXPR) \
|
+ ldr T, 98f; \
|
+ .subsection 2; \
|
+98: .word EXPR - 99f - PC_OFS; \
|
+ .previous; \
|
+99: add T, T, pc; \
|
+ OP R, [T]
|
+# elif defined (ARCH_HAS_T2) && ARM_PCREL_MOVW_OK
|
+# define LDST_PCREL(OP, R, T, EXPR) \
|
+ movw T, #:lower16:EXPR - 99f - PC_OFS; \
|
+ movt T, #:upper16:EXPR - 99f - PC_OFS; \
|
+99: LDST_PC_INDEXED (OP, R, T, T)
|
+# else
|
+# define LDST_PCREL(OP, R, T, EXPR) \
|
+ ldr T, 98f; \
|
+ .subsection 2; \
|
+98: .word EXPR - 99f - PC_OFS; \
|
+ .previous; \
|
+99: OP R, [pc, T]
|
+# endif
|
+
|
+/* Load from a global SYMBOL + CONSTANT into R, using T. */
|
+# if defined (ARCH_HAS_T2) && !defined (PIC)
|
+# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
+ movw T, #:lower16:SYMBOL; \
|
+ movt T, #:upper16:SYMBOL; \
|
+ ldr R, [T, $CONSTANT]
|
+# elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK
|
+# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
+ movw R, #:lower16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS; \
|
+ movw T, #:lower16:99f - 98f - PC_OFS; \
|
+ movt R, #:upper16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS; \
|
+ movt T, #:upper16:99f - 98f - PC_OFS; \
|
+ .pushsection .rodata.cst4, "aM", %progbits, 4; \
|
+ .balign 4; \
|
+99: .word SYMBOL##(GOT); \
|
+ .popsection; \
|
+97: add R, R, pc; \
|
+98: LDST_PC_INDEXED (ldr, T, T, T); \
|
+ LDST_INDEXED (ldr, R, T, R, T); \
|
+ ldr R, [R, $CONSTANT]
|
+# else
|
+# define LDR_GLOBAL(R, T, SYMBOL, CONSTANT) \
|
+ ldr T, 99f; \
|
+ ldr R, 100f; \
|
+98: add T, T, pc; \
|
+ ldr T, [T, R]; \
|
+ .subsection 2; \
|
+99: .word _GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS; \
|
+100: .word SYMBOL##(GOT); \
|
+ .previous; \
|
+ ldr R, [T, $CONSTANT]
|
+# endif
|
+
|
+/* This is the same as LDR_GLOBAL, but for a SYMBOL that is known to
|
+ be in the same linked object (as for one with hidden visibility).
|
+ We can avoid the GOT indirection in the PIC case. For the pure
|
+ static case, LDR_GLOBAL is already optimal. */
|
+# ifdef PIC
|
+# define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
|
+ LDST_PCREL (ldr, R, T, SYMBOL + CONSTANT)
|
+# else
|
+# define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \
|
+ LDR_GLOBAL (R, T, SYMBOL, CONSTANT)
|
+# endif
|
+
|
+/* Cope with negative memory offsets, which thumb can't encode.
|
+ Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
|
+ and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
|
+ or NEGOFF_OFF2 to use A-B for thumb and A for arm. */
|
+# ifdef __thumb2__
|
+# define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
|
+# define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
|
+# define NEGOFF_OFF1(R, OFF) [R]
|
+# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
|
+# else
|
+# define NEGOFF_ADJ_BASE(R, OFF)
|
+# define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
|
+# define NEGOFF_OFF1(R, OFF) [R, $OFF]
|
+# define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
|
+# endif
|
+
|
+/* Helper to get the TLS base pointer. The interface is that TMP is a
|
+ register that may be used to hold the LR, if necessary. TMP may be
|
+ LR itself to indicate that LR need not be saved. The base pointer
|
+ is returned in R0. Only R0 and TMP are modified. */
|
+
|
+# ifdef ARCH_HAS_HARD_TP
|
+/* If the cpu has cp15 available, use it. */
|
+# define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3
|
+# else
|
+/* At this generic level we have no tricks to pull. Call the ABI routine. */
|
+# define GET_TLS(TMP) \
|
+ push { r1, r2, r3, lr }; \
|
+ cfi_remember_state; \
|
+ cfi_adjust_cfa_offset (16); \
|
+ cfi_rel_offset (r1, 0); \
|
+ cfi_rel_offset (r2, 4); \
|
+ cfi_rel_offset (r3, 8); \
|
+ cfi_rel_offset (lr, 12); \
|
+ bl __aeabi_read_tp; \
|
+ pop { r1, r2, r3, lr }; \
|
+ cfi_restore_state
|
+# endif /* ARCH_HAS_HARD_TP */
|
+
|
+/* These are the directives used for EABI unwind info.
|
+ Wrap them in macros so another configuration's sysdep.h
|
+ file can define them away if it doesn't use EABI unwind info. */
|
+# define eabi_fnstart .fnstart
|
+# define eabi_fnend .fnend
|
+# define eabi_save(...) .save __VA_ARGS__
|
+# define eabi_cantunwind .cantunwind
|
+# define eabi_pad(n) .pad n
|
+
|
+#endif /* __ASSEMBLER__ */
|
+
|
+/* This number is the offset from the pc at the current location. */
|
+#ifdef __thumb__
|
+# define PC_OFS 4
|
+#else
|
+# define PC_OFS 8
|
+#endif
|
+
|
+/* Pointer mangling support. */
|
+#if (IS_IN (rtld) \
|
+ || (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
|
+# ifdef __ASSEMBLER__
|
+# define PTR_MANGLE_LOAD(guard, tmp) \
|
+ LDR_HIDDEN (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local), 0)
|
+# define PTR_MANGLE(dst, src, guard, tmp) \
|
+ PTR_MANGLE_LOAD(guard, tmp); \
|
+ PTR_MANGLE2(dst, src, guard)
|
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
|
+# define PTR_MANGLE2(dst, src, guard) \
|
+ eor dst, src, guard
|
+# define PTR_DEMANGLE(dst, src, guard, tmp) \
|
+ PTR_MANGLE (dst, src, guard, tmp)
|
+# define PTR_DEMANGLE2(dst, src, guard) \
|
+ PTR_MANGLE2 (dst, src, guard)
|
+# else
|
+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
|
+# define PTR_MANGLE(var) \
|
+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
|
+# define PTR_DEMANGLE(var) PTR_MANGLE (var)
|
+# endif
|
+#else
|
+# ifdef __ASSEMBLER__
|
+# define PTR_MANGLE_LOAD(guard, tmp) \
|
+ LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0);
|
+# define PTR_MANGLE(dst, src, guard, tmp) \
|
+ PTR_MANGLE_LOAD(guard, tmp); \
|
+ PTR_MANGLE2(dst, src, guard)
|
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
|
+# define PTR_MANGLE2(dst, src, guard) \
|
+ eor dst, src, guard
|
+# define PTR_DEMANGLE(dst, src, guard, tmp) \
|
+ PTR_MANGLE (dst, src, guard, tmp)
|
+# define PTR_DEMANGLE2(dst, src, guard) \
|
+ PTR_MANGLE2 (dst, src, guard)
|
+# else
|
+extern uintptr_t __pointer_chk_guard attribute_relro;
|
+# define PTR_MANGLE(var) \
|
+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
|
+# define PTR_DEMANGLE(var) PTR_MANGLE (var)
|
+# endif
|
+#endif
|
diff --git a/libc/string/arm/glibc-neon/sysdeps/generic/dwarf2.h b/libc/string/arm/glibc-neon/sysdeps/generic/dwarf2.h
|
new file mode 100644
|
index 0000000..0d08da0
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/sysdeps/generic/dwarf2.h
|
@@ -0,0 +1,590 @@
|
+/* Declarations and definitions of codes relating to the DWARF2 symbolic
|
+ debugging information format.
|
+ Copyright (C) 1992-2021 Free Software Foundation, Inc.
|
+ Contributed by Gary Funck (gary@intrepid.com). Derived from the
|
+ DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
|
+
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library; if not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#ifndef _DWARF2_H
|
+#define _DWARF2_H 1
|
+
|
+/* This file is derived from the DWARF specification (a public document)
|
+ Revision 2.0.0 (July 27, 1993) developed by the UNIX International
|
+ Programming Languages Special Interest Group (UI/PLSIG) and distributed
|
+ by UNIX International. Copies of this specification are available from
|
+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. */
|
+
|
+/* This file is shared between GCC and GDB, and should not contain
|
+ prototypes. */
|
+
|
+#ifndef __ASSEMBLER__
|
+/* Tag names and codes. */
|
+
|
+enum dwarf_tag
|
+ {
|
+ DW_TAG_padding = 0x00,
|
+ DW_TAG_array_type = 0x01,
|
+ DW_TAG_class_type = 0x02,
|
+ DW_TAG_entry_point = 0x03,
|
+ DW_TAG_enumeration_type = 0x04,
|
+ DW_TAG_formal_parameter = 0x05,
|
+ DW_TAG_imported_declaration = 0x08,
|
+ DW_TAG_label = 0x0a,
|
+ DW_TAG_lexical_block = 0x0b,
|
+ DW_TAG_member = 0x0d,
|
+ DW_TAG_pointer_type = 0x0f,
|
+ DW_TAG_reference_type = 0x10,
|
+ DW_TAG_compile_unit = 0x11,
|
+ DW_TAG_string_type = 0x12,
|
+ DW_TAG_structure_type = 0x13,
|
+ DW_TAG_subroutine_type = 0x15,
|
+ DW_TAG_typedef = 0x16,
|
+ DW_TAG_union_type = 0x17,
|
+ DW_TAG_unspecified_parameters = 0x18,
|
+ DW_TAG_variant = 0x19,
|
+ DW_TAG_common_block = 0x1a,
|
+ DW_TAG_common_inclusion = 0x1b,
|
+ DW_TAG_inheritance = 0x1c,
|
+ DW_TAG_inlined_subroutine = 0x1d,
|
+ DW_TAG_module = 0x1e,
|
+ DW_TAG_ptr_to_member_type = 0x1f,
|
+ DW_TAG_set_type = 0x20,
|
+ DW_TAG_subrange_type = 0x21,
|
+ DW_TAG_with_stmt = 0x22,
|
+ DW_TAG_access_declaration = 0x23,
|
+ DW_TAG_base_type = 0x24,
|
+ DW_TAG_catch_block = 0x25,
|
+ DW_TAG_const_type = 0x26,
|
+ DW_TAG_constant = 0x27,
|
+ DW_TAG_enumerator = 0x28,
|
+ DW_TAG_file_type = 0x29,
|
+ DW_TAG_friend = 0x2a,
|
+ DW_TAG_namelist = 0x2b,
|
+ DW_TAG_namelist_item = 0x2c,
|
+ DW_TAG_packed_type = 0x2d,
|
+ DW_TAG_subprogram = 0x2e,
|
+ DW_TAG_template_type_param = 0x2f,
|
+ DW_TAG_template_value_param = 0x30,
|
+ DW_TAG_thrown_type = 0x31,
|
+ DW_TAG_try_block = 0x32,
|
+ DW_TAG_variant_part = 0x33,
|
+ DW_TAG_variable = 0x34,
|
+ DW_TAG_volatile_type = 0x35,
|
+ /* SGI/MIPS Extensions */
|
+ DW_TAG_MIPS_loop = 0x4081,
|
+ /* GNU extensions */
|
+ DW_TAG_format_label = 0x4101, /* for FORTRAN 77 and Fortran 90 */
|
+ DW_TAG_function_template = 0x4102, /* for C++ */
|
+ DW_TAG_class_template = 0x4103, /* for C++ */
|
+ DW_TAG_GNU_BINCL = 0x4104,
|
+ DW_TAG_GNU_EINCL = 0x4105
|
+ };
|
+
|
+#define DW_TAG_lo_user 0x4080
|
+#define DW_TAG_hi_user 0xffff
|
+
|
+/* flag that tells whether entry has a child or not */
|
+#define DW_children_no 0
|
+#define DW_children_yes 1
|
+
|
+/* Form names and codes. */
|
+enum dwarf_form
|
+ {
|
+ DW_FORM_addr = 0x01,
|
+ DW_FORM_block2 = 0x03,
|
+ DW_FORM_block4 = 0x04,
|
+ DW_FORM_data2 = 0x05,
|
+ DW_FORM_data4 = 0x06,
|
+ DW_FORM_data8 = 0x07,
|
+ DW_FORM_string = 0x08,
|
+ DW_FORM_block = 0x09,
|
+ DW_FORM_block1 = 0x0a,
|
+ DW_FORM_data1 = 0x0b,
|
+ DW_FORM_flag = 0x0c,
|
+ DW_FORM_sdata = 0x0d,
|
+ DW_FORM_strp = 0x0e,
|
+ DW_FORM_udata = 0x0f,
|
+ DW_FORM_ref_addr = 0x10,
|
+ DW_FORM_ref1 = 0x11,
|
+ DW_FORM_ref2 = 0x12,
|
+ DW_FORM_ref4 = 0x13,
|
+ DW_FORM_ref8 = 0x14,
|
+ DW_FORM_ref_udata = 0x15,
|
+ DW_FORM_indirect = 0x16
|
+ };
|
+
|
+/* Attribute names and codes. */
|
+
|
+enum dwarf_attribute
|
+ {
|
+ DW_AT_sibling = 0x01,
|
+ DW_AT_location = 0x02,
|
+ DW_AT_name = 0x03,
|
+ DW_AT_ordering = 0x09,
|
+ DW_AT_subscr_data = 0x0a,
|
+ DW_AT_byte_size = 0x0b,
|
+ DW_AT_bit_offset = 0x0c,
|
+ DW_AT_bit_size = 0x0d,
|
+ DW_AT_element_list = 0x0f,
|
+ DW_AT_stmt_list = 0x10,
|
+ DW_AT_low_pc = 0x11,
|
+ DW_AT_high_pc = 0x12,
|
+ DW_AT_language = 0x13,
|
+ DW_AT_member = 0x14,
|
+ DW_AT_discr = 0x15,
|
+ DW_AT_discr_value = 0x16,
|
+ DW_AT_visibility = 0x17,
|
+ DW_AT_import = 0x18,
|
+ DW_AT_string_length = 0x19,
|
+ DW_AT_common_reference = 0x1a,
|
+ DW_AT_comp_dir = 0x1b,
|
+ DW_AT_const_value = 0x1c,
|
+ DW_AT_containing_type = 0x1d,
|
+ DW_AT_default_value = 0x1e,
|
+ DW_AT_inline = 0x20,
|
+ DW_AT_is_optional = 0x21,
|
+ DW_AT_lower_bound = 0x22,
|
+ DW_AT_producer = 0x25,
|
+ DW_AT_prototyped = 0x27,
|
+ DW_AT_return_addr = 0x2a,
|
+ DW_AT_start_scope = 0x2c,
|
+ DW_AT_stride_size = 0x2e,
|
+ DW_AT_upper_bound = 0x2f,
|
+ DW_AT_abstract_origin = 0x31,
|
+ DW_AT_accessibility = 0x32,
|
+ DW_AT_address_class = 0x33,
|
+ DW_AT_artificial = 0x34,
|
+ DW_AT_base_types = 0x35,
|
+ DW_AT_calling_convention = 0x36,
|
+ DW_AT_count = 0x37,
|
+ DW_AT_data_member_location = 0x38,
|
+ DW_AT_decl_column = 0x39,
|
+ DW_AT_decl_file = 0x3a,
|
+ DW_AT_decl_line = 0x3b,
|
+ DW_AT_declaration = 0x3c,
|
+ DW_AT_discr_list = 0x3d,
|
+ DW_AT_encoding = 0x3e,
|
+ DW_AT_external = 0x3f,
|
+ DW_AT_frame_base = 0x40,
|
+ DW_AT_friend = 0x41,
|
+ DW_AT_identifier_case = 0x42,
|
+ DW_AT_macro_info = 0x43,
|
+ DW_AT_namelist_items = 0x44,
|
+ DW_AT_priority = 0x45,
|
+ DW_AT_segment = 0x46,
|
+ DW_AT_specification = 0x47,
|
+ DW_AT_static_link = 0x48,
|
+ DW_AT_type = 0x49,
|
+ DW_AT_use_location = 0x4a,
|
+ DW_AT_variable_parameter = 0x4b,
|
+ DW_AT_virtuality = 0x4c,
|
+ DW_AT_vtable_elem_location = 0x4d,
|
+ /* SGI/MIPS Extensions */
|
+ DW_AT_MIPS_fde = 0x2001,
|
+ DW_AT_MIPS_loop_begin = 0x2002,
|
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
|
+ DW_AT_MIPS_epilog_begin = 0x2004,
|
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
|
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
|
+ DW_AT_MIPS_linkage_name = 0x2007,
|
+ DW_AT_MIPS_stride = 0x2008,
|
+ DW_AT_MIPS_abstract_name = 0x2009,
|
+ DW_AT_MIPS_clone_origin = 0x200a,
|
+ DW_AT_MIPS_has_inlines = 0x200b,
|
+ /* GNU extensions. */
|
+ DW_AT_sf_names = 0x2101,
|
+ DW_AT_src_info = 0x2102,
|
+ DW_AT_mac_info = 0x2103,
|
+ DW_AT_src_coords = 0x2104,
|
+ DW_AT_body_begin = 0x2105,
|
+ DW_AT_body_end = 0x2106
|
+ };
|
+
|
+#define DW_AT_lo_user 0x2000 /* implementation-defined range start */
|
+#define DW_AT_hi_user 0x3ff0 /* implementation-defined range end */
|
+
|
+/* Location atom names and codes. */
|
+
|
+enum dwarf_location_atom
|
+ {
|
+ DW_OP_addr = 0x03,
|
+ DW_OP_deref = 0x06,
|
+ DW_OP_const1u = 0x08,
|
+ DW_OP_const1s = 0x09,
|
+ DW_OP_const2u = 0x0a,
|
+ DW_OP_const2s = 0x0b,
|
+ DW_OP_const4u = 0x0c,
|
+ DW_OP_const4s = 0x0d,
|
+ DW_OP_const8u = 0x0e,
|
+ DW_OP_const8s = 0x0f,
|
+ DW_OP_constu = 0x10,
|
+ DW_OP_consts = 0x11,
|
+ DW_OP_dup = 0x12,
|
+ DW_OP_drop = 0x13,
|
+ DW_OP_over = 0x14,
|
+ DW_OP_pick = 0x15,
|
+ DW_OP_swap = 0x16,
|
+ DW_OP_rot = 0x17,
|
+ DW_OP_xderef = 0x18,
|
+ DW_OP_abs = 0x19,
|
+ DW_OP_and = 0x1a,
|
+ DW_OP_div = 0x1b,
|
+ DW_OP_minus = 0x1c,
|
+ DW_OP_mod = 0x1d,
|
+ DW_OP_mul = 0x1e,
|
+ DW_OP_neg = 0x1f,
|
+ DW_OP_not = 0x20,
|
+ DW_OP_or = 0x21,
|
+ DW_OP_plus = 0x22,
|
+ DW_OP_plus_uconst = 0x23,
|
+ DW_OP_shl = 0x24,
|
+ DW_OP_shr = 0x25,
|
+ DW_OP_shra = 0x26,
|
+ DW_OP_xor = 0x27,
|
+ DW_OP_bra = 0x28,
|
+ DW_OP_eq = 0x29,
|
+ DW_OP_ge = 0x2a,
|
+ DW_OP_gt = 0x2b,
|
+ DW_OP_le = 0x2c,
|
+ DW_OP_lt = 0x2d,
|
+ DW_OP_ne = 0x2e,
|
+ DW_OP_skip = 0x2f,
|
+ DW_OP_lit0 = 0x30,
|
+ DW_OP_lit1 = 0x31,
|
+ DW_OP_lit2 = 0x32,
|
+ DW_OP_lit3 = 0x33,
|
+ DW_OP_lit4 = 0x34,
|
+ DW_OP_lit5 = 0x35,
|
+ DW_OP_lit6 = 0x36,
|
+ DW_OP_lit7 = 0x37,
|
+ DW_OP_lit8 = 0x38,
|
+ DW_OP_lit9 = 0x39,
|
+ DW_OP_lit10 = 0x3a,
|
+ DW_OP_lit11 = 0x3b,
|
+ DW_OP_lit12 = 0x3c,
|
+ DW_OP_lit13 = 0x3d,
|
+ DW_OP_lit14 = 0x3e,
|
+ DW_OP_lit15 = 0x3f,
|
+ DW_OP_lit16 = 0x40,
|
+ DW_OP_lit17 = 0x41,
|
+ DW_OP_lit18 = 0x42,
|
+ DW_OP_lit19 = 0x43,
|
+ DW_OP_lit20 = 0x44,
|
+ DW_OP_lit21 = 0x45,
|
+ DW_OP_lit22 = 0x46,
|
+ DW_OP_lit23 = 0x47,
|
+ DW_OP_lit24 = 0x48,
|
+ DW_OP_lit25 = 0x49,
|
+ DW_OP_lit26 = 0x4a,
|
+ DW_OP_lit27 = 0x4b,
|
+ DW_OP_lit28 = 0x4c,
|
+ DW_OP_lit29 = 0x4d,
|
+ DW_OP_lit30 = 0x4e,
|
+ DW_OP_lit31 = 0x4f,
|
+ DW_OP_reg0 = 0x50,
|
+ DW_OP_reg1 = 0x51,
|
+ DW_OP_reg2 = 0x52,
|
+ DW_OP_reg3 = 0x53,
|
+ DW_OP_reg4 = 0x54,
|
+ DW_OP_reg5 = 0x55,
|
+ DW_OP_reg6 = 0x56,
|
+ DW_OP_reg7 = 0x57,
|
+ DW_OP_reg8 = 0x58,
|
+ DW_OP_reg9 = 0x59,
|
+ DW_OP_reg10 = 0x5a,
|
+ DW_OP_reg11 = 0x5b,
|
+ DW_OP_reg12 = 0x5c,
|
+ DW_OP_reg13 = 0x5d,
|
+ DW_OP_reg14 = 0x5e,
|
+ DW_OP_reg15 = 0x5f,
|
+ DW_OP_reg16 = 0x60,
|
+ DW_OP_reg17 = 0x61,
|
+ DW_OP_reg18 = 0x62,
|
+ DW_OP_reg19 = 0x63,
|
+ DW_OP_reg20 = 0x64,
|
+ DW_OP_reg21 = 0x65,
|
+ DW_OP_reg22 = 0x66,
|
+ DW_OP_reg23 = 0x67,
|
+ DW_OP_reg24 = 0x68,
|
+ DW_OP_reg25 = 0x69,
|
+ DW_OP_reg26 = 0x6a,
|
+ DW_OP_reg27 = 0x6b,
|
+ DW_OP_reg28 = 0x6c,
|
+ DW_OP_reg29 = 0x6d,
|
+ DW_OP_reg30 = 0x6e,
|
+ DW_OP_reg31 = 0x6f,
|
+ DW_OP_breg0 = 0x70,
|
+ DW_OP_breg1 = 0x71,
|
+ DW_OP_breg2 = 0x72,
|
+ DW_OP_breg3 = 0x73,
|
+ DW_OP_breg4 = 0x74,
|
+ DW_OP_breg5 = 0x75,
|
+ DW_OP_breg6 = 0x76,
|
+ DW_OP_breg7 = 0x77,
|
+ DW_OP_breg8 = 0x78,
|
+ DW_OP_breg9 = 0x79,
|
+ DW_OP_breg10 = 0x7a,
|
+ DW_OP_breg11 = 0x7b,
|
+ DW_OP_breg12 = 0x7c,
|
+ DW_OP_breg13 = 0x7d,
|
+ DW_OP_breg14 = 0x7e,
|
+ DW_OP_breg15 = 0x7f,
|
+ DW_OP_breg16 = 0x80,
|
+ DW_OP_breg17 = 0x81,
|
+ DW_OP_breg18 = 0x82,
|
+ DW_OP_breg19 = 0x83,
|
+ DW_OP_breg20 = 0x84,
|
+ DW_OP_breg21 = 0x85,
|
+ DW_OP_breg22 = 0x86,
|
+ DW_OP_breg23 = 0x87,
|
+ DW_OP_breg24 = 0x88,
|
+ DW_OP_breg25 = 0x89,
|
+ DW_OP_breg26 = 0x8a,
|
+ DW_OP_breg27 = 0x8b,
|
+ DW_OP_breg28 = 0x8c,
|
+ DW_OP_breg29 = 0x8d,
|
+ DW_OP_breg30 = 0x8e,
|
+ DW_OP_breg31 = 0x8f,
|
+ DW_OP_regx = 0x90,
|
+ DW_OP_fbreg = 0x91,
|
+ DW_OP_bregx = 0x92,
|
+ DW_OP_piece = 0x93,
|
+ DW_OP_deref_size = 0x94,
|
+ DW_OP_xderef_size = 0x95,
|
+ DW_OP_nop = 0x96
|
+ };
|
+
|
+#define DW_OP_lo_user 0x80 /* implementation-defined range start */
|
+#define DW_OP_hi_user 0xff /* implementation-defined range end */
|
+
|
+/* Type encodings. */
|
+
|
+enum dwarf_type
|
+ {
|
+ DW_ATE_void = 0x0,
|
+ DW_ATE_address = 0x1,
|
+ DW_ATE_boolean = 0x2,
|
+ DW_ATE_complex_float = 0x3,
|
+ DW_ATE_float = 0x4,
|
+ DW_ATE_signed = 0x5,
|
+ DW_ATE_signed_char = 0x6,
|
+ DW_ATE_unsigned = 0x7,
|
+ DW_ATE_unsigned_char = 0x8
|
+ };
|
+
|
+#define DW_ATE_lo_user 0x80
|
+#define DW_ATE_hi_user 0xff
|
+
|
+/* Array ordering names and codes. */
|
+enum dwarf_array_dim_ordering
|
+ {
|
+ DW_ORD_row_major = 0,
|
+ DW_ORD_col_major = 1
|
+ };
|
+
|
+/* access attribute */
|
+enum dwarf_access_attribute
|
+ {
|
+ DW_ACCESS_public = 1,
|
+ DW_ACCESS_protected = 2,
|
+ DW_ACCESS_private = 3
|
+ };
|
+
|
+/* visibility */
|
+enum dwarf_visibility_attribute
|
+ {
|
+ DW_VIS_local = 1,
|
+ DW_VIS_exported = 2,
|
+ DW_VIS_qualified = 3
|
+ };
|
+
|
+/* virtuality */
|
+enum dwarf_virtuality_attribute
|
+ {
|
+ DW_VIRTUALITY_none = 0,
|
+ DW_VIRTUALITY_virtual = 1,
|
+ DW_VIRTUALITY_pure_virtual = 2
|
+ };
|
+
|
+/* case sensitivity */
|
+enum dwarf_id_case
|
+ {
|
+ DW_ID_case_sensitive = 0,
|
+ DW_ID_up_case = 1,
|
+ DW_ID_down_case = 2,
|
+ DW_ID_case_insensitive = 3
|
+ };
|
+
|
+/* calling convention */
|
+enum dwarf_calling_convention
|
+ {
|
+ DW_CC_normal = 0x1,
|
+ DW_CC_program = 0x2,
|
+ DW_CC_nocall = 0x3
|
+ };
|
+
|
+#define DW_CC_lo_user 0x40
|
+#define DW_CC_hi_user 0xff
|
+
|
+/* inline attribute */
|
+enum dwarf_inline_attribute
|
+ {
|
+ DW_INL_not_inlined = 0,
|
+ DW_INL_inlined = 1,
|
+ DW_INL_declared_not_inlined = 2,
|
+ DW_INL_declared_inlined = 3
|
+ };
|
+
|
+/* discriminant lists */
|
+enum dwarf_discrim_list
|
+ {
|
+ DW_DSC_label = 0,
|
+ DW_DSC_range = 1
|
+ };
|
+
|
+/* line number opcodes */
|
+enum dwarf_line_number_ops
|
+ {
|
+ DW_LNS_extended_op = 0,
|
+ DW_LNS_copy = 1,
|
+ DW_LNS_advance_pc = 2,
|
+ DW_LNS_advance_line = 3,
|
+ DW_LNS_set_file = 4,
|
+ DW_LNS_set_column = 5,
|
+ DW_LNS_negate_stmt = 6,
|
+ DW_LNS_set_basic_block = 7,
|
+ DW_LNS_const_add_pc = 8,
|
+ DW_LNS_fixed_advance_pc = 9
|
+ };
|
+
|
+/* line number extended opcodes */
|
+enum dwarf_line_number_x_ops
|
+ {
|
+ DW_LNE_end_sequence = 1,
|
+ DW_LNE_set_address = 2,
|
+ DW_LNE_define_file = 3
|
+ };
|
+
|
+/* call frame information */
|
+enum dwarf_call_frame_info
|
+ {
|
+ DW_CFA_advance_loc = 0x40,
|
+ DW_CFA_offset = 0x80,
|
+ DW_CFA_restore = 0xc0,
|
+ DW_CFA_nop = 0x00,
|
+ DW_CFA_set_loc = 0x01,
|
+ DW_CFA_advance_loc1 = 0x02,
|
+ DW_CFA_advance_loc2 = 0x03,
|
+ DW_CFA_advance_loc4 = 0x04,
|
+ DW_CFA_offset_extended = 0x05,
|
+ DW_CFA_restore_extended = 0x06,
|
+ DW_CFA_undefined = 0x07,
|
+ DW_CFA_same_value = 0x08,
|
+ DW_CFA_register = 0x09,
|
+ DW_CFA_remember_state = 0x0a,
|
+ DW_CFA_restore_state = 0x0b,
|
+ DW_CFA_def_cfa = 0x0c,
|
+ DW_CFA_def_cfa_register = 0x0d,
|
+ DW_CFA_def_cfa_offset = 0x0e,
|
+ DW_CFA_def_cfa_expression = 0x0f,
|
+ DW_CFA_expression = 0x10,
|
+ /* Dwarf 2.1 */
|
+ DW_CFA_offset_extended_sf = 0x11,
|
+ DW_CFA_def_cfa_sf = 0x12,
|
+ DW_CFA_def_cfa_offset_sf = 0x13,
|
+
|
+ /* SGI/MIPS specific */
|
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
|
+
|
+ /* GNU extensions */
|
+ DW_CFA_GNU_window_save = 0x2d,
|
+ DW_CFA_GNU_args_size = 0x2e,
|
+ DW_CFA_GNU_negative_offset_extended = 0x2f
|
+ };
|
+
|
+#define DW_CIE_ID 0xffffffff
|
+#define DW_CIE_VERSION 1
|
+
|
+#define DW_CFA_extended 0
|
+#define DW_CFA_low_user 0x1c
|
+#define DW_CFA_high_user 0x3f
|
+
|
+#define DW_CHILDREN_no 0x00
|
+#define DW_CHILDREN_yes 0x01
|
+
|
+#define DW_ADDR_none 0
|
+
|
+/* Source language names and codes. */
|
+
|
+enum dwarf_source_language
|
+ {
|
+ DW_LANG_C89 = 0x0001,
|
+ DW_LANG_C = 0x0002,
|
+ DW_LANG_Ada83 = 0x0003,
|
+ DW_LANG_C_plus_plus = 0x0004,
|
+ DW_LANG_Cobol74 = 0x0005,
|
+ DW_LANG_Cobol85 = 0x0006,
|
+ DW_LANG_Fortran77 = 0x0007,
|
+ DW_LANG_Fortran90 = 0x0008,
|
+ DW_LANG_Pascal83 = 0x0009,
|
+ DW_LANG_Modula2 = 0x000a,
|
+ DW_LANG_Java = 0x000b,
|
+ DW_LANG_Mips_Assembler = 0x8001
|
+ };
|
+
|
+
|
+#define DW_LANG_lo_user 0x8000 /* implementation-defined range start */
|
+#define DW_LANG_hi_user 0xffff /* implementation-defined range start */
|
+
|
+/* Names and codes for macro information. */
|
+
|
+enum dwarf_macinfo_record_type
|
+ {
|
+ DW_MACINFO_define = 1,
|
+ DW_MACINFO_undef = 2,
|
+ DW_MACINFO_start_file = 3,
|
+ DW_MACINFO_end_file = 4,
|
+ DW_MACINFO_vendor_ext = 255
|
+ };
|
+
|
+#endif /* !ASSEMBLER */
|
+
|
+/* @@@ For use with GNU frame unwind information. */
|
+
|
+#define DW_EH_PE_absptr 0x00
|
+#define DW_EH_PE_omit 0xff
|
+
|
+#define DW_EH_PE_uleb128 0x01
|
+#define DW_EH_PE_udata2 0x02
|
+#define DW_EH_PE_udata4 0x03
|
+#define DW_EH_PE_udata8 0x04
|
+#define DW_EH_PE_sleb128 0x09
|
+#define DW_EH_PE_sdata2 0x0A
|
+#define DW_EH_PE_sdata4 0x0B
|
+#define DW_EH_PE_sdata8 0x0C
|
+#define DW_EH_PE_signed 0x08
|
+
|
+#define DW_EH_PE_pcrel 0x10
|
+#define DW_EH_PE_textrel 0x20
|
+#define DW_EH_PE_datarel 0x30
|
+#define DW_EH_PE_funcrel 0x40
|
+#define DW_EH_PE_aligned 0x50
|
+
|
+#define DW_EH_PE_indirect 0x80
|
+
|
+#endif /* dwarf2.h */
|
diff --git a/libc/string/arm/glibc-neon/sysdeps/generic/sysdep.h b/libc/string/arm/glibc-neon/sysdeps/generic/sysdep.h
|
new file mode 100644
|
index 0000000..39cac91
|
--- /dev/null
|
+++ b/libc/string/arm/glibc-neon/sysdeps/generic/sysdep.h
|
@@ -0,0 +1,97 @@
|
+/* Generic asm macros used on many machines.
|
+ Copyright (C) 1991-2021 Free Software Foundation, Inc.
|
+ This file is part of the GNU C Library.
|
+
|
+ The GNU C Library is free software; you can redistribute it and/or
|
+ modify it under the terms of the GNU Lesser General Public
|
+ License as published by the Free Software Foundation; either
|
+ version 2.1 of the License, or (at your option) any later version.
|
+
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
+ Lesser General Public License for more details.
|
+
|
+ You should have received a copy of the GNU Lesser General Public
|
+ License along with the GNU C Library; if not, see
|
+ <https://www.gnu.org/licenses/>. */
|
+
|
+#ifndef C_LABEL
|
+
|
+/* Define a macro we can use to construct the asm name for a C symbol. */
|
+# define C_LABEL(name) name##:
|
+
|
+#endif
|
+
|
+#ifdef __ASSEMBLER__
|
+/* Mark the end of function named SYM. This is used on some platforms
|
+ to generate correct debugging information. */
|
+# ifndef END
|
+# define END(sym)
|
+# endif
|
+
|
+# ifndef JUMPTARGET
|
+# define JUMPTARGET(sym) sym
|
+# endif
|
+#endif
|
+
|
+/* Makros to generate eh_frame unwind information. */
|
+#ifdef __ASSEMBLER__
|
+# define cfi_startproc .cfi_startproc
|
+# define cfi_endproc .cfi_endproc
|
+# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
|
+# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
|
+# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
|
+# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
|
+# define cfi_offset(reg, off) .cfi_offset reg, off
|
+# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
|
+# define cfi_register(r1, r2) .cfi_register r1, r2
|
+# define cfi_return_column(reg) .cfi_return_column reg
|
+# define cfi_restore(reg) .cfi_restore reg
|
+# define cfi_same_value(reg) .cfi_same_value reg
|
+# define cfi_undefined(reg) .cfi_undefined reg
|
+# define cfi_remember_state .cfi_remember_state
|
+# define cfi_restore_state .cfi_restore_state
|
+# define cfi_window_save .cfi_window_save
|
+# define cfi_personality(enc, exp) .cfi_personality enc, exp
|
+# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
|
+
|
+#else /* ! ASSEMBLER */
|
+
|
+# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name)
|
+# define CFI_STRINGIFY2(Name) #Name
|
+# define CFI_STARTPROC ".cfi_startproc"
|
+# define CFI_ENDPROC ".cfi_endproc"
|
+# define CFI_DEF_CFA(reg, off) \
|
+ ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
|
+# define CFI_DEF_CFA_REGISTER(reg) \
|
+ ".cfi_def_cfa_register " CFI_STRINGIFY(reg)
|
+# define CFI_DEF_CFA_OFFSET(off) \
|
+ ".cfi_def_cfa_offset " CFI_STRINGIFY(off)
|
+# define CFI_ADJUST_CFA_OFFSET(off) \
|
+ ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off)
|
+# define CFI_OFFSET(reg, off) \
|
+ ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
|
+# define CFI_REL_OFFSET(reg, off) \
|
+ ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
|
+# define CFI_REGISTER(r1, r2) \
|
+ ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2)
|
+# define CFI_RETURN_COLUMN(reg) \
|
+ ".cfi_return_column " CFI_STRINGIFY(reg)
|
+# define CFI_RESTORE(reg) \
|
+ ".cfi_restore " CFI_STRINGIFY(reg)
|
+# define CFI_UNDEFINED(reg) \
|
+ ".cfi_undefined " CFI_STRINGIFY(reg)
|
+# define CFI_REMEMBER_STATE \
|
+ ".cfi_remember_state"
|
+# define CFI_RESTORE_STATE \
|
+ ".cfi_restore_state"
|
+# define CFI_WINDOW_SAVE \
|
+ ".cfi_window_save"
|
+# define CFI_PERSONALITY(enc, exp) \
|
+ ".cfi_personality " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp)
|
+# define CFI_LSDA(enc, exp) \
|
+ ".cfi_lsda " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp)
|
+#endif
|
+
|
+#include "dwarf2.h"
|
--
|
2.20.1
|