Compare commits
	
		
			2 Commits
		
	
	
		
			marshmallo
			...
			jb-mr2-dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e4dda1f1e9 | ||
| 
						 | 
					5a6f55a3c4 | 
							
								
								
									
										15
									
								
								ABI-bugs.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ABI-bugs.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
KNOWN ABI BUGS
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
  time_t is 32-bit. http://b/5819737
 | 
			
		||||
 | 
			
		||||
  off_t is 32-bit. There is off64_t, but no _FILE_OFFSET_BITS support.
 | 
			
		||||
 | 
			
		||||
  sigset_t is too small on ARM and x86 (but correct on MIPS), so support
 | 
			
		||||
  for real-time signals is broken. http://b/5828899
 | 
			
		||||
 | 
			
		||||
  Too few TLS slots mean we can't allocate 128 pthread_key_t instances,
 | 
			
		||||
  which POSIX says should be the minimum.
 | 
			
		||||
 | 
			
		||||
  atexit(3) handlers registered by a shared library aren't called on
 | 
			
		||||
  dlclose(3); this only affects ARM. http://b/4998315
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
set noparent
 | 
			
		||||
filter=-build/header_guard,-runtime/int,-readability/function
 | 
			
		||||
@@ -44,10 +44,6 @@
 | 
			
		||||
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
 | 
			
		||||
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
 | 
			
		||||
 | 
			
		||||
# Switching to jemalloc requires deleting these files.
 | 
			
		||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libc_*)
 | 
			
		||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libc_*)
 | 
			
		||||
 | 
			
		||||
# ************************************************
 | 
			
		||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 | 
			
		||||
# ************************************************
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										273
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										273
									
								
								README.md
									
									
									
									
									
								
							@@ -1,273 +0,0 @@
 | 
			
		||||
Working on bionic
 | 
			
		||||
=================
 | 
			
		||||
 | 
			
		||||
What are the big pieces of bionic?
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
#### libc/ --- libc.so, libc.a
 | 
			
		||||
 | 
			
		||||
The C library. Stuff like `fopen(3)` and `kill(2)`.
 | 
			
		||||
 | 
			
		||||
#### libm/ --- libm.so, libm.a
 | 
			
		||||
 | 
			
		||||
The math library. Traditionally Unix systems kept stuff like `sin(3)` and
 | 
			
		||||
`cos(3)` in a separate library to save space in the days before shared
 | 
			
		||||
libraries.
 | 
			
		||||
 | 
			
		||||
#### libdl/ --- libdl.so
 | 
			
		||||
 | 
			
		||||
The dynamic linker interface library. This is actually just a bunch of stubs
 | 
			
		||||
that the dynamic linker replaces with pointers to its own implementation at
 | 
			
		||||
runtime. This is where stuff like `dlopen(3)` lives.
 | 
			
		||||
 | 
			
		||||
#### libstdc++/ --- libstdc++.so
 | 
			
		||||
 | 
			
		||||
The C++ ABI support functions. The C++ compiler doesn't know how to implement
 | 
			
		||||
thread-safe static initialization and the like, so it just calls functions that
 | 
			
		||||
are supplied by the system. Stuff like `__cxa_guard_acquire` and
 | 
			
		||||
`__cxa_pure_virtual` live here.
 | 
			
		||||
 | 
			
		||||
#### linker/ --- /system/bin/linker and /system/bin/linker64
 | 
			
		||||
 | 
			
		||||
The dynamic linker. When you run a dynamically-linked executable, its ELF file
 | 
			
		||||
has a `DT_INTERP` entry that says "use the following program to start me".  On
 | 
			
		||||
Android, that's either `linker` or `linker64` (depending on whether it's a
 | 
			
		||||
32-bit or 64-bit executable). It's responsible for loading the ELF executable
 | 
			
		||||
into memory and resolving references to symbols (so that when your code tries to
 | 
			
		||||
jump to `fopen(3)`, say, it lands in the right place).
 | 
			
		||||
 | 
			
		||||
#### tests/ --- unit tests
 | 
			
		||||
 | 
			
		||||
The `tests/` directory contains unit tests. Roughly arranged as one file per
 | 
			
		||||
publicly-exported header file.
 | 
			
		||||
 | 
			
		||||
#### benchmarks/ --- benchmarks
 | 
			
		||||
 | 
			
		||||
The `benchmarks/` directory contains benchmarks.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
What's in libc/?
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
libc/
 | 
			
		||||
  arch-arm/
 | 
			
		||||
  arch-arm64/
 | 
			
		||||
  arch-common/
 | 
			
		||||
  arch-mips/
 | 
			
		||||
  arch-mips64/
 | 
			
		||||
  arch-x86/
 | 
			
		||||
  arch-x86_64/
 | 
			
		||||
    # Each architecture has its own subdirectory for stuff that isn't shared
 | 
			
		||||
    # because it's architecture-specific. There will be a .mk file in here that
 | 
			
		||||
    # drags in all the architecture-specific files.
 | 
			
		||||
    bionic/
 | 
			
		||||
      # Every architecture needs a handful of machine-specific assembler files.
 | 
			
		||||
      # They live here.
 | 
			
		||||
    include/
 | 
			
		||||
      machine/
 | 
			
		||||
        # The majority of header files are actually in libc/include/, but many
 | 
			
		||||
        # of them pull in a <machine/something.h> for things like limits,
 | 
			
		||||
        # endianness, and how floating point numbers are represented. Those
 | 
			
		||||
        # headers live here.
 | 
			
		||||
    string/
 | 
			
		||||
      # Most architectures have a handful of optional assembler files
 | 
			
		||||
      # implementing optimized versions of various routines. The <string.h>
 | 
			
		||||
      # functions are particular favorites.
 | 
			
		||||
    syscalls/
 | 
			
		||||
      # The syscalls directories contain script-generated assembler files.
 | 
			
		||||
      # See 'Adding system calls' later.
 | 
			
		||||
 | 
			
		||||
  include/
 | 
			
		||||
    # The public header files on everyone's include path. These are a mixture of
 | 
			
		||||
    # files written by us and files taken from BSD.
 | 
			
		||||
 | 
			
		||||
  kernel/
 | 
			
		||||
    # The kernel uapi header files. These are scrubbed copies of the originals
 | 
			
		||||
    # in external/kernel-headers/. These files must not be edited directly. The
 | 
			
		||||
    # generate_uapi_headers.sh script should be used to go from a kernel tree to
 | 
			
		||||
    # external/kernel-headers/ --- this takes care of the architecture-specific
 | 
			
		||||
    # details. The update_all.py script should be used to regenerate bionic's
 | 
			
		||||
    # scrubbed headers from external/kernel-headers/.
 | 
			
		||||
 | 
			
		||||
  private/
 | 
			
		||||
    # These are private header files meant for use within bionic itself.
 | 
			
		||||
 | 
			
		||||
  dns/
 | 
			
		||||
    # Contains the DNS resolver (originates from NetBSD code).
 | 
			
		||||
 | 
			
		||||
  upstream-dlmalloc/
 | 
			
		||||
  upstream-freebsd/
 | 
			
		||||
  upstream-netbsd/
 | 
			
		||||
  upstream-openbsd/
 | 
			
		||||
    # These directories contain unmolested upstream source. Any time we can
 | 
			
		||||
    # just use a BSD implementation of something unmodified, we should.
 | 
			
		||||
    # The structure under these directories mimics the upstream tree,
 | 
			
		||||
    # but there's also...
 | 
			
		||||
    android/
 | 
			
		||||
      include/
 | 
			
		||||
        # This is where we keep the hacks necessary to build BSD source
 | 
			
		||||
        # in our world. The *-compat.h files are automatically included
 | 
			
		||||
        # using -include, but we also provide equivalents for missing
 | 
			
		||||
        # header/source files needed by the BSD implementation.
 | 
			
		||||
 | 
			
		||||
  bionic/
 | 
			
		||||
    # This is the biggest mess. The C++ files are files we own, typically
 | 
			
		||||
    # because the Linux kernel interface is sufficiently different that we
 | 
			
		||||
    # can't use any of the BSD implementations. The C files are usually
 | 
			
		||||
    # legacy mess that needs to be sorted out, either by replacing it with
 | 
			
		||||
    # current upstream source in one of the upstream directories or by
 | 
			
		||||
    # switching the file to C++ and cleaning it up.
 | 
			
		||||
 | 
			
		||||
  stdio/
 | 
			
		||||
    # These are legacy files of dubious provenance. We're working to clean
 | 
			
		||||
    # this mess up, and this directory should disappear.
 | 
			
		||||
 | 
			
		||||
  tools/
 | 
			
		||||
    # Various tools used to maintain bionic.
 | 
			
		||||
 | 
			
		||||
  tzcode/
 | 
			
		||||
    # A modified superset of the IANA tzcode. Most of the modifications relate
 | 
			
		||||
    # to Android's use of a single file (with corresponding index) to contain
 | 
			
		||||
    # time zone data.
 | 
			
		||||
  zoneinfo/
 | 
			
		||||
    # Android-format time zone data.
 | 
			
		||||
    # See 'Updating tzdata' later.
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Adding system calls
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
Adding a system call usually involves:
 | 
			
		||||
 | 
			
		||||
  1. Add entries to SYSCALLS.TXT.
 | 
			
		||||
     See SYSCALLS.TXT itself for documentation on the format.
 | 
			
		||||
  2. Run the gensyscalls.py script.
 | 
			
		||||
  3. Add constants (and perhaps types) to the appropriate header file.
 | 
			
		||||
     Note that you should check to see whether the constants are already in
 | 
			
		||||
     kernel uapi header files, in which case you just need to make sure that
 | 
			
		||||
     the appropriate POSIX header file in libc/include/ includes the
 | 
			
		||||
     relevant file or files.
 | 
			
		||||
  4. Add function declarations to the appropriate header file.
 | 
			
		||||
  5. Add at least basic tests. Even a test that deliberately supplies
 | 
			
		||||
     an invalid argument helps check that we're generating the right symbol
 | 
			
		||||
     and have the right declaration in the header file. (And strace(1) can
 | 
			
		||||
     confirm that the correct system call is being made.)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Updating kernel header files
 | 
			
		||||
----------------------------
 | 
			
		||||
 | 
			
		||||
As mentioned above, this is currently a two-step process:
 | 
			
		||||
 | 
			
		||||
  1. Use generate_uapi_headers.sh to go from a Linux source tree to appropriate
 | 
			
		||||
     contents for external/kernel-headers/.
 | 
			
		||||
  2. Run update_all.py to scrub those headers and import them into bionic.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Updating tzdata
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
This is fully automated:
 | 
			
		||||
 | 
			
		||||
  1. Run update-tzdata.py.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Verifying changes
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
If you make a change that is likely to have a wide effect on the tree (such as a
 | 
			
		||||
libc header change), you should run `make checkbuild`. A regular `make` will
 | 
			
		||||
_not_ build the entire tree; just the minimum number of projects that are
 | 
			
		||||
required for the device. Tests, additional developer tools, and various other
 | 
			
		||||
modules will not be built. Note that `make checkbuild` will not be complete
 | 
			
		||||
either, as `make tests` covers a few additional modules, but generally speaking
 | 
			
		||||
`make checkbuild` is enough.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Running the tests
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
The tests are all built from the tests/ directory.
 | 
			
		||||
 | 
			
		||||
### Device tests
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ adb sync
 | 
			
		||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
 | 
			
		||||
    # Only for 64-bit targets
 | 
			
		||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
			
		||||
 | 
			
		||||
### Host tests
 | 
			
		||||
 | 
			
		||||
The host tests require that you have `lunch`ed either an x86 or x86_64 target.
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ mm bionic-unit-tests-run-on-host32
 | 
			
		||||
    $ mm bionic-unit-tests-run-on-host64  # For 64-bit *targets* only.
 | 
			
		||||
 | 
			
		||||
### Against glibc
 | 
			
		||||
 | 
			
		||||
As a way to check that our tests do in fact test the correct behavior (and not
 | 
			
		||||
just the behavior we think is correct), it is possible to run the tests against
 | 
			
		||||
the host's glibc. The executables are already in your path.
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ bionic-unit-tests-glibc32
 | 
			
		||||
    $ bionic-unit-tests-glibc64
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Gathering test coverage
 | 
			
		||||
-----------------------
 | 
			
		||||
 | 
			
		||||
For either host or target coverage, you must first:
 | 
			
		||||
 | 
			
		||||
 * `$ export NATIVE_COVERAGE=true`
 | 
			
		||||
     * Note that the build system is ignorant to this flag being toggled, i.e. if
 | 
			
		||||
       you change this flag, you will have to manually rebuild bionic.
 | 
			
		||||
 * Set `bionic_coverage=true` in `libc/Android.mk` and `libm/Android.mk`.
 | 
			
		||||
 | 
			
		||||
### Coverage from device tests
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ adb sync
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        GCOV_PREFIX=/data/local/tmp/gcov \
 | 
			
		||||
        GCOV_PREFIX_STRIP=`echo $ANDROID_BUILD_TOP | grep -o / | wc -l` \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
			
		||||
    $ acov
 | 
			
		||||
 | 
			
		||||
`acov` will pull all coverage information from the device, push it to the right
 | 
			
		||||
directories, run `lcov`, and open the coverage report in your browser.
 | 
			
		||||
 | 
			
		||||
### Coverage from host tests
 | 
			
		||||
 | 
			
		||||
First, build and run the host tests as usual (see above).
 | 
			
		||||
 | 
			
		||||
    $ croot
 | 
			
		||||
    $ lcov -c -d $ANDROID_PRODUCT_OUT -o coverage.info
 | 
			
		||||
    $ genhtml -o covreport coverage.info # or lcov --list coverage.info
 | 
			
		||||
 | 
			
		||||
The coverage report is now available at `covreport/index.html`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LP32 ABI bugs
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
This probably belongs in the NDK documentation rather than here, but these
 | 
			
		||||
are the known ABI bugs in LP32:
 | 
			
		||||
 | 
			
		||||
 * `time_t` is 32-bit. <http://b/5819737>
 | 
			
		||||
 | 
			
		||||
 * `off_t` is 32-bit. There is `off64_t`, but no `_FILE_OFFSET_BITS` support.
 | 
			
		||||
   Many of the `off64_t` functions are missing in older releases, and
 | 
			
		||||
   stdio uses 32-bit offsets, so there's no way to fully implement
 | 
			
		||||
   `_FILE_OFFSET_BITS`.
 | 
			
		||||
 | 
			
		||||
 * `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
 | 
			
		||||
   for real-time signals is broken. <http://b/5828899>
 | 
			
		||||
@@ -1,131 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Benchmarks library, usable by projects outside this directory.
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
benchmark_cflags := \
 | 
			
		||||
    -O2 \
 | 
			
		||||
    -fno-builtin \
 | 
			
		||||
    -Wall \
 | 
			
		||||
    -Wextra \
 | 
			
		||||
    -Werror \
 | 
			
		||||
    -Wunused \
 | 
			
		||||
 | 
			
		||||
benchmark_cppflags := \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
benchmarklib_src_files := \
 | 
			
		||||
    Benchmark.cpp \
 | 
			
		||||
    utils.cpp \
 | 
			
		||||
    main.cpp \
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := libbenchmark
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
 | 
			
		||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbase
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
# Only supported on linux systems.
 | 
			
		||||
ifeq ($(HOST_OS),linux)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := libbenchmark
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
 | 
			
		||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbase
 | 
			
		||||
include $(BUILD_HOST_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Benchmarks.
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
benchmark_src_files := \
 | 
			
		||||
    math_benchmark.cpp \
 | 
			
		||||
    property_benchmark.cpp \
 | 
			
		||||
    pthread_benchmark.cpp \
 | 
			
		||||
    semaphore_benchmark.cpp \
 | 
			
		||||
    stdio_benchmark.cpp \
 | 
			
		||||
    string_benchmark.cpp \
 | 
			
		||||
    time_benchmark.cpp \
 | 
			
		||||
    unistd_benchmark.cpp \
 | 
			
		||||
 | 
			
		||||
# Build benchmarks for the device (with bionic's .so). Run with:
 | 
			
		||||
#   adb shell bionic-benchmarks32
 | 
			
		||||
#   adb shell bionic-benchmarks64
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := bionic-benchmarks
 | 
			
		||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks32
 | 
			
		||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks64
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmark_src_files)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
# We don't build a static benchmark executable because it's not usually
 | 
			
		||||
# useful. If you're trying to run the current benchmarks on an older
 | 
			
		||||
# release, it's (so far at least) always because you want to measure the
 | 
			
		||||
# performance of the old release's libc, and a static benchmark isn't
 | 
			
		||||
# going to let you do that.
 | 
			
		||||
 | 
			
		||||
# Only supported on linux systems.
 | 
			
		||||
ifeq ($(HOST_OS),linux)
 | 
			
		||||
 | 
			
		||||
# Build benchmarks for the host (against glibc!). Run with:
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := bionic-benchmarks-glibc
 | 
			
		||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks-glibc32
 | 
			
		||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks-glibc64
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_CFLAGS := $(benchmark_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
 | 
			
		||||
LOCAL_LDFLAGS := -lrt
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmark_src_files)
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 | 
			
		||||
include $(BUILD_HOST_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 | 
			
		||||
include $(LOCAL_PATH)/../build/run-on-host.mk
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
 | 
			
		||||
bionic-benchmarks-run-on-host32: bionic-benchmarks bionic-prepare-run-on-host
 | 
			
		||||
	ANDROID_DATA=$(TARGET_OUT_DATA) \
 | 
			
		||||
	ANDROID_ROOT=$(TARGET_OUT) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks32 $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_IS_64_BIT),true)
 | 
			
		||||
bionic-benchmarks-run-on-host64: bionic-benchmarks bionic-prepare-run-on-host
 | 
			
		||||
	ANDROID_DATA=$(TARGET_OUT_DATA) \
 | 
			
		||||
	ANDROID_ROOT=$(TARGET_OUT) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks64 $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
@@ -1,159 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <base/stringprintf.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
static uint64_t NanoTime() {
 | 
			
		||||
  struct timespec t;
 | 
			
		||||
  t.tv_sec = t.tv_nsec = 0;
 | 
			
		||||
  clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Benchmark::header_printed_;
 | 
			
		||||
 | 
			
		||||
std::vector<Benchmark*>& Benchmark::List() {
 | 
			
		||||
  static std::vector<Benchmark*> list;
 | 
			
		||||
  return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Benchmark::MaxNameColumnWidth() {
 | 
			
		||||
  size_t max = 20;
 | 
			
		||||
  for (auto& benchmark : List()) {
 | 
			
		||||
    max = std::max(max, benchmark->NameColumnWidth());
 | 
			
		||||
  }
 | 
			
		||||
  return static_cast<int>(max);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t Benchmark::RunAll(std::vector<regex_t*>& regs) {
 | 
			
		||||
  size_t benchmarks_run = 0;
 | 
			
		||||
  header_printed_ = false;
 | 
			
		||||
  for (auto& benchmark : List()) {
 | 
			
		||||
    benchmarks_run += benchmark->RunAllArgs(regs);
 | 
			
		||||
  }
 | 
			
		||||
  return benchmarks_run;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::PrintHeader() {
 | 
			
		||||
  if (!header_printed_) {
 | 
			
		||||
    printf("%-*s %10s %10s\n", MaxNameColumnWidth(), "", "iterations", "ns/op");
 | 
			
		||||
    header_printed_ = true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
bool BenchmarkT<T>::ShouldRun(std::vector<regex_t*>& regs, T arg) {
 | 
			
		||||
  if (regs.empty()) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (const auto& re : regs) {
 | 
			
		||||
    if (regexec(re, GetNameStr(arg).c_str(), 0, NULL, 0) != REG_NOMATCH) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::StopBenchmarkTiming() {
 | 
			
		||||
  if (start_time_ns_ != 0) {
 | 
			
		||||
    total_time_ns_ += NanoTime() - start_time_ns_;
 | 
			
		||||
  }
 | 
			
		||||
  start_time_ns_ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::StartBenchmarkTiming() {
 | 
			
		||||
  if (start_time_ns_ == 0) {
 | 
			
		||||
    start_time_ns_ = NanoTime();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string BenchmarkWithoutArg::GetNameStr(void*) {
 | 
			
		||||
  return Name();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
std::string BenchmarkWithArg<int>::GetNameStr(int arg) {
 | 
			
		||||
  return Name() + "/" + PrettyInt(arg, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
std::string BenchmarkWithArg<double>::GetNameStr(double arg) {
 | 
			
		||||
  return Name() + "/" + android::base::StringPrintf("%0.6f", arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
void BenchmarkT<T>::RunWithArg(T arg) {
 | 
			
		||||
  int new_iterations = 1;
 | 
			
		||||
  int iterations;
 | 
			
		||||
  while (new_iterations < 1e8) {
 | 
			
		||||
    bytes_processed_ = 0;
 | 
			
		||||
    total_time_ns_ = 0;
 | 
			
		||||
    start_time_ns_ = 0;
 | 
			
		||||
 | 
			
		||||
    iterations = new_iterations;
 | 
			
		||||
    RunIterations(iterations, arg);
 | 
			
		||||
    if (total_time_ns_ >= 1e9) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (total_time_ns_/iterations == 0) {
 | 
			
		||||
      new_iterations = 1e9;
 | 
			
		||||
    } else {
 | 
			
		||||
      new_iterations = 1e9/ (total_time_ns_/iterations);
 | 
			
		||||
    }
 | 
			
		||||
    new_iterations = std::max(iterations + 1,
 | 
			
		||||
                          std::min(new_iterations + new_iterations/2, 100*iterations));
 | 
			
		||||
 | 
			
		||||
    new_iterations = Round(new_iterations);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printf("%-*s %10s %10" PRId64, MaxNameColumnWidth(), GetNameStr(arg).c_str(),
 | 
			
		||||
         PrettyInt(iterations, 10).c_str(), total_time_ns_/iterations);
 | 
			
		||||
 | 
			
		||||
  if (total_time_ns_ > 0 && bytes_processed_ > 0) {
 | 
			
		||||
    double gib_processed = static_cast<double>(bytes_processed_)/1e9;
 | 
			
		||||
    double seconds = static_cast<double>(total_time_ns_)/1e9;
 | 
			
		||||
    printf(" %8.3f GiB/s", gib_processed/seconds);
 | 
			
		||||
  }
 | 
			
		||||
  printf("\n");
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template class BenchmarkT<int>;
 | 
			
		||||
template class BenchmarkT<double>;
 | 
			
		||||
template class BenchmarkT<void*>;
 | 
			
		||||
 | 
			
		||||
template class BenchmarkWithArg<int>;
 | 
			
		||||
template class BenchmarkWithArg<double>;
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
@@ -1,169 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
#define BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
class Benchmark {
 | 
			
		||||
public:
 | 
			
		||||
  Benchmark() {
 | 
			
		||||
    List().push_back(this);
 | 
			
		||||
  }
 | 
			
		||||
  virtual ~Benchmark() {}
 | 
			
		||||
 | 
			
		||||
  virtual std::string Name() = 0;
 | 
			
		||||
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
 | 
			
		||||
 | 
			
		||||
  void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
 | 
			
		||||
  void StopBenchmarkTiming();
 | 
			
		||||
  void StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  // Run all of the benchmarks that have registered.
 | 
			
		||||
  static size_t RunAll(std::vector<regex_t*>&);
 | 
			
		||||
 | 
			
		||||
  static std::vector<Benchmark*>& List();
 | 
			
		||||
 | 
			
		||||
  static int MaxNameColumnWidth();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t NameColumnWidth() = 0;
 | 
			
		||||
 | 
			
		||||
  uint64_t bytes_processed_;
 | 
			
		||||
  uint64_t total_time_ns_;
 | 
			
		||||
  uint64_t start_time_ns_;
 | 
			
		||||
 | 
			
		||||
  static bool header_printed_;
 | 
			
		||||
 | 
			
		||||
  static void PrintHeader();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
class BenchmarkT : public Benchmark {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkT() {}
 | 
			
		||||
  virtual ~BenchmarkT() {}
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  bool ShouldRun(std::vector<regex_t*>&, T arg);
 | 
			
		||||
  void RunWithArg(T arg);
 | 
			
		||||
  virtual void RunIterations(int, T) = 0;
 | 
			
		||||
  virtual std::string GetNameStr(T) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class BenchmarkWithoutArg : public BenchmarkT<void*> {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkWithoutArg() {}
 | 
			
		||||
  virtual ~BenchmarkWithoutArg() {}
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
 | 
			
		||||
    size_t benchmarks_run = 0;
 | 
			
		||||
    if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
 | 
			
		||||
      PrintHeader();
 | 
			
		||||
      RunWithArg(nullptr);
 | 
			
		||||
      benchmarks_run++;
 | 
			
		||||
    }
 | 
			
		||||
    return benchmarks_run;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void RunIterations(int iters, void*) override {
 | 
			
		||||
    Run(iters);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void Run(int) = 0;
 | 
			
		||||
 | 
			
		||||
  virtual size_t NameColumnWidth() override {
 | 
			
		||||
    return Name().size();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual std::string GetNameStr(void *) override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class BenchmarkWithArg : public BenchmarkT<T> {
 | 
			
		||||
public:
 | 
			
		||||
  BenchmarkWithArg() {}
 | 
			
		||||
  virtual ~BenchmarkWithArg() {}
 | 
			
		||||
 | 
			
		||||
  BenchmarkWithArg* Arg(T arg) {
 | 
			
		||||
    args_.push_back(arg);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual size_t NameColumnWidth() override {
 | 
			
		||||
    size_t max = 0;
 | 
			
		||||
    for (const auto& arg : args_) {
 | 
			
		||||
      max = std::max(max, GetNameStr(arg).size());
 | 
			
		||||
    }
 | 
			
		||||
    return max;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::string GetNameStr(T arg) override;
 | 
			
		||||
 | 
			
		||||
  virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
 | 
			
		||||
    size_t benchmarks_run = 0;
 | 
			
		||||
    for (T& arg : args_) {
 | 
			
		||||
      if (BenchmarkT<T>::ShouldRun(regs, arg)) {
 | 
			
		||||
        Benchmark::PrintHeader();
 | 
			
		||||
        BenchmarkT<T>::RunWithArg(arg);
 | 
			
		||||
        benchmarks_run++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return benchmarks_run;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void RunIterations(int iters, T arg) override {
 | 
			
		||||
    Run(iters, arg);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual void Run(int iters, T arg) = 0;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<T> args_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_START(f, super_class) \
 | 
			
		||||
  class f : public super_class { \
 | 
			
		||||
  public: \
 | 
			
		||||
    f() {} \
 | 
			
		||||
    virtual ~f() {} \
 | 
			
		||||
    virtual std::string Name() override { return #f; } \
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_NO_ARG(f) \
 | 
			
		||||
  BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
 | 
			
		||||
    virtual void Run(int) override; \
 | 
			
		||||
  }; \
 | 
			
		||||
  static ::testing::Benchmark* __benchmark_##f = new f()
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK_WITH_ARG(f, arg_type) \
 | 
			
		||||
  BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
 | 
			
		||||
    virtual void Run(int, arg_type) override; \
 | 
			
		||||
  }; \
 | 
			
		||||
  static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
 | 
			
		||||
 | 
			
		||||
#endif  // BENCHMARKS_BENCHMARK_H_
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
  if (::testing::Benchmark::List().empty()) {
 | 
			
		||||
    fprintf(stderr, "No benchmarks registered!\n");
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::vector<regex_t*> regs;
 | 
			
		||||
  for (int i = 1; i < argc; i++) {
 | 
			
		||||
    regex_t* re = new regex_t;
 | 
			
		||||
    int errcode = regcomp(re, argv[i], 0);
 | 
			
		||||
    if (errcode != 0) {
 | 
			
		||||
      size_t errbuf_size = regerror(errcode, re, NULL, 0);
 | 
			
		||||
      if (errbuf_size > 0) {
 | 
			
		||||
        char* errbuf = new char[errbuf_size];
 | 
			
		||||
        regerror(errcode, re, errbuf, errbuf_size);
 | 
			
		||||
        fprintf(stderr, "Couldn't compile \"%s\" as a regular expression: %s\n",
 | 
			
		||||
                argv[i], errbuf);
 | 
			
		||||
      } else {
 | 
			
		||||
        fprintf(stderr, "Unknown compile error for \"%s\" as a regular expression!\n", argv[i]);
 | 
			
		||||
      }
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    regs.push_back(re);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (::testing::Benchmark::RunAll(regs) == 0) {
 | 
			
		||||
    fprintf(stderr, "No matching benchmarks!\n");
 | 
			
		||||
    fprintf(stderr, "Available benchmarks:\n");
 | 
			
		||||
    for (const auto& benchmark : ::testing::Benchmark::List()) {
 | 
			
		||||
      fprintf(stderr, "  %s\n", benchmark->Name().c_str());
 | 
			
		||||
    }
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,136 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fenv.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#define AT_COMMON_VALS \
 | 
			
		||||
    Arg(1234.0)->Arg(nan(""))->Arg(HUGE_VAL)->Arg(0.0)
 | 
			
		||||
 | 
			
		||||
// Avoid optimization.
 | 
			
		||||
volatile double d;
 | 
			
		||||
volatile double v;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sqrt);
 | 
			
		||||
void BM_math_sqrt::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 2.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += sqrt(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_log10);
 | 
			
		||||
void BM_math_log10::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += log10(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_logb);
 | 
			
		||||
void BM_math_logb::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += logb(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
 | 
			
		||||
void BM_math_isinf::Run(int iters, double value) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = value;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_fast);
 | 
			
		||||
void BM_math_sin_fast::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += sin(d);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_feupdateenv);
 | 
			
		||||
void BM_math_sin_feupdateenv::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    fenv_t __libc_save_rm;
 | 
			
		||||
    feholdexcept(&__libc_save_rm);
 | 
			
		||||
    fesetround(FE_TONEAREST);
 | 
			
		||||
    d += sin(d);
 | 
			
		||||
    feupdateenv(&__libc_save_rm);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_math_sin_fesetenv);
 | 
			
		||||
void BM_math_sin_fesetenv::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    fenv_t __libc_save_rm;
 | 
			
		||||
    feholdexcept(&__libc_save_rm);
 | 
			
		||||
    fesetround(FE_TONEAREST);
 | 
			
		||||
    d += sin(d);
 | 
			
		||||
    fesetenv(&__libc_save_rm);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_math_fpclassify, double)->AT_COMMON_VALS;
 | 
			
		||||
void BM_math_fpclassify::Run(int iters, double value) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = value;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,233 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 | 
			
		||||
#include <sys/_system_properties.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
extern void* __system_property_area__;
 | 
			
		||||
 | 
			
		||||
// Do not exceed 512, that is about the largest number of properties
 | 
			
		||||
// that can be created with the current property area size.
 | 
			
		||||
#define TEST_NUM_PROPS \
 | 
			
		||||
    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
 | 
			
		||||
 | 
			
		||||
struct LocalPropertyTestState {
 | 
			
		||||
  LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
 | 
			
		||||
    static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
 | 
			
		||||
 | 
			
		||||
    const char* android_data = getenv("ANDROID_DATA");
 | 
			
		||||
    if (android_data == NULL) {
 | 
			
		||||
      printf("ANDROID_DATA environment variable not set\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    char dir_template[PATH_MAX];
 | 
			
		||||
    snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
 | 
			
		||||
    char* dirname = mkdtemp(dir_template);
 | 
			
		||||
    if (!dirname) {
 | 
			
		||||
      printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
 | 
			
		||||
             android_data, strerror(errno));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    old_pa = __system_property_area__;
 | 
			
		||||
    __system_property_area__ = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_dirname = dirname;
 | 
			
		||||
    pa_filename = pa_dirname + "/__properties__";
 | 
			
		||||
 | 
			
		||||
    __system_property_set_filename(pa_filename.c_str());
 | 
			
		||||
    __system_property_area_init();
 | 
			
		||||
 | 
			
		||||
    names = new char* [nprops];
 | 
			
		||||
    name_lens = new int[nprops];
 | 
			
		||||
    values = new char* [nprops];
 | 
			
		||||
    value_lens = new int[nprops];
 | 
			
		||||
 | 
			
		||||
    srandom(nprops);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < nprops; i++) {
 | 
			
		||||
      // Make sure the name has at least 10 characters to make
 | 
			
		||||
      // it very unlikely to generate the same random name.
 | 
			
		||||
      name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
 | 
			
		||||
      names[i] = new char[PROP_NAME_MAX + 1];
 | 
			
		||||
      size_t prop_name_len = sizeof(prop_name_chars) - 1;
 | 
			
		||||
      for (int j = 0; j < name_lens[i]; j++) {
 | 
			
		||||
        if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
 | 
			
		||||
          // Certain values are not allowed:
 | 
			
		||||
          // - Don't start name with '.'
 | 
			
		||||
          // - Don't allow '.' to appear twice in a row
 | 
			
		||||
          // - Don't allow the name to end with '.'
 | 
			
		||||
          // This assumes that '.' is the last character in the
 | 
			
		||||
          // array so that decrementing the length by one removes
 | 
			
		||||
          // the value from the possible values.
 | 
			
		||||
          prop_name_len--;
 | 
			
		||||
        }
 | 
			
		||||
        names[i][j] = prop_name_chars[random() % prop_name_len];
 | 
			
		||||
      }
 | 
			
		||||
      names[i][name_lens[i]] = 0;
 | 
			
		||||
 | 
			
		||||
      // Make sure the value contains at least 1 character.
 | 
			
		||||
      value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
 | 
			
		||||
      values[i] = new char[PROP_VALUE_MAX];
 | 
			
		||||
      for (int j = 0; j < value_lens[i]; j++) {
 | 
			
		||||
        values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
 | 
			
		||||
        printf("Failed to add a property, terminating...\n");
 | 
			
		||||
        printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
 | 
			
		||||
        exit(1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    valid = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ~LocalPropertyTestState() {
 | 
			
		||||
    if (!valid)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    __system_property_area__ = old_pa;
 | 
			
		||||
 | 
			
		||||
    __system_property_set_filename(PROP_FILENAME);
 | 
			
		||||
    unlink(pa_filename.c_str());
 | 
			
		||||
    rmdir(pa_dirname.c_str());
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < nprops; i++) {
 | 
			
		||||
      delete names[i];
 | 
			
		||||
      delete values[i];
 | 
			
		||||
    }
 | 
			
		||||
    delete[] names;
 | 
			
		||||
    delete[] name_lens;
 | 
			
		||||
    delete[] values;
 | 
			
		||||
    delete[] value_lens;
 | 
			
		||||
  }
 | 
			
		||||
public:
 | 
			
		||||
  const int nprops;
 | 
			
		||||
  char** names;
 | 
			
		||||
  int* name_lens;
 | 
			
		||||
  char** values;
 | 
			
		||||
  int* value_lens;
 | 
			
		||||
  bool valid;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::string pa_dirname;
 | 
			
		||||
  std::string pa_filename;
 | 
			
		||||
  void* old_pa;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_get::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
  char value[PROP_VALUE_MAX];
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_get(pa.names[random() % nprops], value);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_find::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_read::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
  const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
  char propvalue[PROP_VALUE_MAX];
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_read(pinfo[i], 0, propvalue);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  delete[] pinfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
 | 
			
		||||
void BM_property_serial::Run(int iters, int nprops) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  LocalPropertyTestState pa(nprops);
 | 
			
		||||
 | 
			
		||||
  if (!pa.valid)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  srandom(iters * nprops);
 | 
			
		||||
  const prop_info** pinfo = new const prop_info*[iters];
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    pinfo[i] = __system_property_find(pa.names[random() % nprops]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  for (int i = 0; i < iters; i++) {
 | 
			
		||||
    __system_property_serial(pinfo[i]);
 | 
			
		||||
  }
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  delete[] pinfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // __BIONIC__
 | 
			
		||||
@@ -1,233 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_self);
 | 
			
		||||
void BM_pthread_self::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_self_fp();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_getspecific);
 | 
			
		||||
void BM_pthread_getspecific::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
  pthread_key_create(&key, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_getspecific(key);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_delete(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_setspecific);
 | 
			
		||||
void BM_pthread_setspecific::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
  pthread_key_create(&key, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_setspecific(key, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_delete(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void DummyPthreadOnceInitFunction() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_once);
 | 
			
		||||
void BM_pthread_once::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_once_t once = PTHREAD_ONCE_INIT;
 | 
			
		||||
  pthread_once(&once, DummyPthreadOnceInitFunction);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_once(&once, DummyPthreadOnceInitFunction);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock);
 | 
			
		||||
void BM_pthread_mutex_lock::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_mutex_lock(&mutex);
 | 
			
		||||
    pthread_mutex_unlock(&mutex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_ERRORCHECK);
 | 
			
		||||
void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_mutex_lock(&mutex);
 | 
			
		||||
    pthread_mutex_unlock(&mutex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_RECURSIVE);
 | 
			
		||||
void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_mutex_lock(&mutex);
 | 
			
		||||
    pthread_mutex_unlock(&mutex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_read);
 | 
			
		||||
void BM_pthread_rwlock_read::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_t lock;
 | 
			
		||||
  pthread_rwlock_init(&lock, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_rwlock_rdlock(&lock);
 | 
			
		||||
    pthread_rwlock_unlock(&lock);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_destroy(&lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_write);
 | 
			
		||||
void BM_pthread_rwlock_write::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_t lock;
 | 
			
		||||
  pthread_rwlock_init(&lock, NULL);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_rwlock_wrlock(&lock);
 | 
			
		||||
    pthread_rwlock_unlock(&lock);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_rwlock_destroy(&lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* IdleThread(void*) {
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_create);
 | 
			
		||||
void BM_pthread_create::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_create(&thread, NULL, IdleThread, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* RunThread(void* arg) {
 | 
			
		||||
  ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_create_and_run);
 | 
			
		||||
void BM_pthread_create_and_run::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_create(&thread, NULL, RunThread, this);
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* ExitThread(void* arg) {
 | 
			
		||||
  ::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
 | 
			
		||||
  benchmark->StartBenchmarkTiming();
 | 
			
		||||
  pthread_exit(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_exit_and_join);
 | 
			
		||||
void BM_pthread_exit_and_join::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_t thread;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_create(&thread, NULL, ExitThread, this);
 | 
			
		||||
    pthread_join(thread, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_key_create);
 | 
			
		||||
void BM_pthread_key_create::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_key_create(&key, NULL);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
    pthread_key_delete(key);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_pthread_key_delete);
 | 
			
		||||
void BM_pthread_key_delete::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_key_t key;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_key_create(&key, NULL);
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    pthread_key_delete(key);
 | 
			
		||||
    StopBenchmarkTiming();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,143 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
#include <stdatomic.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_getvalue);
 | 
			
		||||
void BM_semaphore_sem_getvalue::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 1, 1);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    int dummy;
 | 
			
		||||
    sem_getvalue(&semaphore, &dummy);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_wait_sem_post);
 | 
			
		||||
void BM_semaphore_sem_wait_sem_post::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 1, 1);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    sem_wait(&semaphore);
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *    This test reports the overhead of the underlying futex wake syscall on
 | 
			
		||||
 * the producer. It does not report the overhead from issuing the wake to the
 | 
			
		||||
 * point where the posted consumer thread wakes up. It suffers from
 | 
			
		||||
 * clock_gettime syscall overhead. Lock the CPU speed for consistent results
 | 
			
		||||
 * as we may not reach >50% cpu utilization.
 | 
			
		||||
 *
 | 
			
		||||
 *    We will run a background thread that catches the sem_post wakeup and
 | 
			
		||||
 * loops immediately returning back to sleep in sem_wait for the next one. This
 | 
			
		||||
 * thread is run with policy SCHED_OTHER (normal policy), a middle policy.
 | 
			
		||||
 *
 | 
			
		||||
 *    The primary thread will run at SCHED_IDLE (lowest priority policy) when
 | 
			
		||||
 * monitoring the background thread to detect when it hits sem_wait sleep. It
 | 
			
		||||
 * will do so with no clock running. Once we are ready, we will switch to
 | 
			
		||||
 * SCHED_FIFO (highest priority policy) to time the act of running sem_post
 | 
			
		||||
 * with the benchmark clock running. This ensures nothing else in the system
 | 
			
		||||
 * can preempt our timed activity, including the background thread. We are
 | 
			
		||||
 * also protected with the scheduling policy of letting a process hit a
 | 
			
		||||
 * resource limit rather than get hit with a context switch.
 | 
			
		||||
 *
 | 
			
		||||
 *    The background thread will start executing either on another CPU, or
 | 
			
		||||
 * after we back down from SCHED_FIFO, but certainly not in the context of
 | 
			
		||||
 * the timing of the sem_post.
 | 
			
		||||
 */
 | 
			
		||||
static atomic_int BM_semaphore_sem_post_running;
 | 
			
		||||
 | 
			
		||||
static void *BM_semaphore_sem_post_start_thread(void *obj) {
 | 
			
		||||
    sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
 | 
			
		||||
 | 
			
		||||
    while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
    BM_semaphore_sem_post_running = -1;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_semaphore_sem_post);
 | 
			
		||||
void BM_semaphore_sem_post::Run(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 0, 0);
 | 
			
		||||
 | 
			
		||||
  pthread_attr_t attr;
 | 
			
		||||
  pthread_attr_init(&attr);
 | 
			
		||||
  BM_semaphore_sem_post_running = 1;
 | 
			
		||||
  struct sched_param param = { 0, };
 | 
			
		||||
  pthread_attr_setschedparam(&attr, ¶m);
 | 
			
		||||
  pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
 | 
			
		||||
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 | 
			
		||||
  pthread_t pthread;
 | 
			
		||||
  pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
 | 
			
		||||
  pthread_attr_destroy(&attr);
 | 
			
		||||
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    int trys = 3, dummy = 0;
 | 
			
		||||
    do {
 | 
			
		||||
      if (BM_semaphore_sem_post_running < 0) {
 | 
			
		||||
        sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
        fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      sched_yield();
 | 
			
		||||
      sem_getvalue(&semaphore, &dummy);
 | 
			
		||||
      if (dummy < 0) {  // POSIX.1-2001 possibility 1
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (dummy == 0) { // POSIX.1-2001 possibility 2
 | 
			
		||||
        --trys;
 | 
			
		||||
      }
 | 
			
		||||
    } while (trys);
 | 
			
		||||
    param.sched_priority = 1;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_FIFO, ¶m);
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
 | 
			
		||||
    param.sched_priority = 0;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  }
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
 | 
			
		||||
  if (BM_semaphore_sem_post_running > 0) {
 | 
			
		||||
    BM_semaphore_sem_post_running = 0;
 | 
			
		||||
  }
 | 
			
		||||
  do {
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    sched_yield();
 | 
			
		||||
  } while (!BM_semaphore_sem_post_running);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,93 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdio_ext.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#define KB 1024
 | 
			
		||||
#define MB 1024*KB
 | 
			
		||||
 | 
			
		||||
#define AT_COMMON_SIZES \
 | 
			
		||||
    Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
 | 
			
		||||
    Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
 | 
			
		||||
 | 
			
		||||
template <typename Fn>
 | 
			
		||||
void ReadWriteTest(::testing::Benchmark* benchmark, int iters, int chunk_size, Fn f, bool buffered) {
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
  FILE* fp = fopen("/dev/zero", "rw");
 | 
			
		||||
  __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
  char* buf = new char[chunk_size];
 | 
			
		||||
  benchmark->StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  if (!buffered) {
 | 
			
		||||
    setvbuf(fp, 0, _IONBF, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    f(buf, chunk_size, 1, fp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  benchmark->StopBenchmarkTiming();
 | 
			
		||||
  benchmark->SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fread, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fread::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fread, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fwrite::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fwrite, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fread_unbuffered::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fread, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_stdio_fwrite_unbuffered::Run(int iters, int chunk_size) {
 | 
			
		||||
  ReadWriteTest(this, iters, chunk_size, fwrite, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void FopenFgetsFclose(int iters, bool no_locking) {
 | 
			
		||||
  char buf[1024];
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    FILE* fp = fopen("/proc/version", "re");
 | 
			
		||||
    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
    fgets(buf, sizeof(buf), fp);
 | 
			
		||||
    fclose(fp);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_locking);
 | 
			
		||||
void BM_stdio_fopen_fgets_fclose_locking::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  FopenFgetsFclose(iters, false);
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_no_locking);
 | 
			
		||||
void BM_stdio_fopen_fgets_fclose_no_locking::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
  FopenFgetsFclose(iters, true);
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,113 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
#define KB 1024
 | 
			
		||||
#define MB 1024*KB
 | 
			
		||||
 | 
			
		||||
#define AT_COMMON_SIZES \
 | 
			
		||||
    Arg(8)->Arg(64)->Arg(512)->Arg(1*KB)->Arg(8*KB)->Arg(16*KB)->Arg(32*KB)->Arg(64*KB)
 | 
			
		||||
 | 
			
		||||
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memcmp, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memcmp::Run(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* src = new char[nbytes]; char* dst = new char[nbytes];
 | 
			
		||||
  memset(src, 'x', nbytes);
 | 
			
		||||
  memset(dst, 'x', nbytes);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  volatile int c __attribute__((unused)) = 0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    c += memcmp(dst, src, nbytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memcpy, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memcpy::Run(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* src = new char[nbytes]; char* dst = new char[nbytes];
 | 
			
		||||
  memset(src, 'x', nbytes);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    memcpy(dst, src, nbytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memmove, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memmove::Run(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* buf = new char[nbytes + 64];
 | 
			
		||||
  memset(buf, 'x', nbytes + 64);
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    memmove(buf, buf + 1, nbytes); // Worst-case overlap.
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_memset, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_memset::Run(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* dst = new char[nbytes];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    memset(dst, 0, nbytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_WITH_ARG(BM_string_strlen, int)->AT_COMMON_SIZES;
 | 
			
		||||
void BM_string_strlen::Run(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* s = new char[nbytes];
 | 
			
		||||
  memset(s, 'x', nbytes);
 | 
			
		||||
  s[nbytes - 1] = 0;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  volatile int c __attribute__((unused)) = 0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    c += strlen(s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
 | 
			
		||||
  delete[] s;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,80 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_clock_gettime);
 | 
			
		||||
void BM_time_clock_gettime::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_clock_gettime_syscall);
 | 
			
		||||
void BM_time_clock_gettime_syscall::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_gettimeofday);
 | 
			
		||||
void BM_time_gettimeofday::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    gettimeofday(&tv, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_gettimeofday_syscall);
 | 
			
		||||
void BM_time_gettimeofday_syscall::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_gettimeofday, &tv, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_time_time);
 | 
			
		||||
void BM_time_time::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    time(NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,71 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_getpid);
 | 
			
		||||
void BM_unistd_getpid::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    getpid();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_getpid_syscall);
 | 
			
		||||
void BM_unistd_getpid_syscall::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_getpid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_gettid);
 | 
			
		||||
void BM_unistd_gettid::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    gettid_fp();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
BENCHMARK_NO_ARG(BM_unistd_gettid_syscall);
 | 
			
		||||
void BM_unistd_gettid_syscall::Run(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_gettid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,81 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
int Round(int n) {
 | 
			
		||||
  int base = 1;
 | 
			
		||||
  while (base*10 < n) {
 | 
			
		||||
    base *= 10;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 2*base) {
 | 
			
		||||
    return 2*base;
 | 
			
		||||
  }
 | 
			
		||||
  if (n < 5*base) {
 | 
			
		||||
    return 5*base;
 | 
			
		||||
  }
 | 
			
		||||
  return 10*base;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Similar to the code in art, but supporting both binary and decimal prefixes.
 | 
			
		||||
std::string PrettyInt(long value, size_t base) {
 | 
			
		||||
  if (base != 2 && base != 10) abort();
 | 
			
		||||
 | 
			
		||||
  uint64_t count = static_cast<uint64_t>(value);
 | 
			
		||||
  bool negative_number = false;
 | 
			
		||||
  if (value < 0) {
 | 
			
		||||
    negative_number = true;
 | 
			
		||||
    count = static_cast<uint64_t>(-value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // The byte thresholds at which we display amounts. A count is displayed
 | 
			
		||||
  // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
 | 
			
		||||
  static const uint64_t kUnitThresholds2[] = {
 | 
			
		||||
    1024*1024*1024 /* Gi */, 2*1024*1024 /* Mi */, 3*1024 /* Ki */, 0,
 | 
			
		||||
  };
 | 
			
		||||
  static const uint64_t kUnitThresholds10[] = {
 | 
			
		||||
    1000*1000*1000 /* G */, 2*1000*1000 /* M */, 3*1000 /* k */, 0,
 | 
			
		||||
  };
 | 
			
		||||
  static const uint64_t kAmountPerUnit2[] = { 1024*1024*1024, 1024*1024, 1024, 1 };
 | 
			
		||||
  static const uint64_t kAmountPerUnit10[] = { 1000*1000*1000, 1000*1000, 1000, 1 };
 | 
			
		||||
  static const char* const kUnitStrings2[] = { "Gi", "Mi", "Ki", "" };
 | 
			
		||||
  static const char* const kUnitStrings10[] = { "G", "M", "k", "" };
 | 
			
		||||
 | 
			
		||||
  // Which set are we using?
 | 
			
		||||
  const uint64_t* kUnitThresholds = ((base == 2) ? kUnitThresholds2 : kUnitThresholds10);
 | 
			
		||||
  const uint64_t* kAmountPerUnit = ((base == 2) ? kAmountPerUnit2 : kAmountPerUnit10);
 | 
			
		||||
  const char* const* kUnitStrings = ((base == 2) ? kUnitStrings2 : kUnitStrings10);
 | 
			
		||||
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  for (; kUnitThresholds[i] != 0; ++i) {
 | 
			
		||||
    if (count >= kUnitThresholds[i]) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  char* s = NULL;
 | 
			
		||||
  asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
 | 
			
		||||
           count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
  std::string result(s);
 | 
			
		||||
  free(s);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef BENCHMARKS_UTILS_H
 | 
			
		||||
#define BENCHMARKS_UTILS_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
int Round(int n);
 | 
			
		||||
std::string PrettyInt(long value, size_t base);
 | 
			
		||||
 | 
			
		||||
#endif  // BENCHMARKS_UTILS_H
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Include once
 | 
			
		||||
ifneq ($(bionic_run_on_host_mk_included),true)
 | 
			
		||||
bionic_run_on_host_mk_included:=true
 | 
			
		||||
 | 
			
		||||
ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
 | 
			
		||||
LINKER = linker64
 | 
			
		||||
else
 | 
			
		||||
LINKER = linker
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
 | 
			
		||||
# gtest needs ANDROID_DATA/local/tmp for death test output.
 | 
			
		||||
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
 | 
			
		||||
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
 | 
			
		||||
bionic-prepare-run-on-host: $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT)/etc/hosts $(TARGET_OUT_EXECUTABLES)/sh
 | 
			
		||||
	if [ ! -d /system ]; then \
 | 
			
		||||
	  echo "Attempting to create /system"; \
 | 
			
		||||
	  sudo mkdir -p -m 0777 /system; \
 | 
			
		||||
	fi
 | 
			
		||||
	mkdir -p $(TARGET_OUT_DATA)/local/tmp
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/bin` /system/
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/etc` /system/
 | 
			
		||||
	ln -fs `realpath $(TARGET_OUT)/lib` /system/
 | 
			
		||||
	if [ -d "$(TARGET_OUT)/lib64" ]; then \
 | 
			
		||||
	  ln -fs `realpath $(TARGET_OUT)/lib64` /system/; \
 | 
			
		||||
	fi
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										1959
									
								
								libc/Android.mk
									
									
									
									
									
								
							
							
						
						
									
										1959
									
								
								libc/Android.mk
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										26
									
								
								libc/CAVEATS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libc/CAVEATS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
Bionic is a very small C library because we have decided to *not* implement various features
 | 
			
		||||
of the POSIX standard. we only add functions on a as-needed basis, and there are a few things
 | 
			
		||||
we wish we'll never put in there.
 | 
			
		||||
 | 
			
		||||
this file is here to document explicitely what we don't want to support in Bionic:
 | 
			
		||||
 | 
			
		||||
- C++ exceptions are not supported. on embedded systems, they lead to extremely larger and
 | 
			
		||||
  slower code for no good reason (even when so-called zero-cost exception schemes are
 | 
			
		||||
  implemented, they enforce very large numbers of registers spills to the stack, even
 | 
			
		||||
  in functions that do not throw an exception themselves).
 | 
			
		||||
 | 
			
		||||
- pthread cancellation is *not* supported. this seemingly simple "feature" is the source
 | 
			
		||||
  of much bloat and complexity in a C library. Besides, you'd better write correct
 | 
			
		||||
  multi-threaded code instead of relying on this stuff.
 | 
			
		||||
 | 
			
		||||
- pthread_once() doesn't support C++ exceptions thrown from the init function, or the init
 | 
			
		||||
  function doing a fork().
 | 
			
		||||
 | 
			
		||||
- locales and wide characters are not supported. we use ICU for all this i18n stuff, which
 | 
			
		||||
  is much better than the ill-designed related C libraries functions.
 | 
			
		||||
 | 
			
		||||
- at the moment, several user-account-related functions like getpwd are stubbed and return
 | 
			
		||||
  the values corresponding to root. this will be fixed when we'll be able to have distinct
 | 
			
		||||
  users on the Android filesystem. :-(
 | 
			
		||||
 | 
			
		||||
  see bionic/stubs.c for the details
 | 
			
		||||
							
								
								
									
										2087
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										2087
									
								
								libc/NOTICE
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,339 +1,321 @@
 | 
			
		||||
# This file is used to automatically generate bionic's system call stubs.
 | 
			
		||||
# This file is used to automatically generate bionic's the system calls stubs.
 | 
			
		||||
#
 | 
			
		||||
# Each non-blank, non-comment line has the following format:
 | 
			
		||||
# Each non comment line has the following format:
 | 
			
		||||
#
 | 
			
		||||
# return_type func_name[|alias_list][:syscall_name[:socketcall_id]]([parameter_list]) arch_list
 | 
			
		||||
# return_type    func_name[:syscall_name[:call_id]]([parameter_list])  (1|-1|"stub")
 | 
			
		||||
#
 | 
			
		||||
# where:
 | 
			
		||||
#       arch_list ::= "all" | arch+
 | 
			
		||||
#       arch      ::= "arm" | "arm64" | "mips" | "mips64" | "x86" | "x86_64"
 | 
			
		||||
#
 | 
			
		||||
# Note:
 | 
			
		||||
# Note that:
 | 
			
		||||
#      - syscall_name corresponds to the name of the syscall, which may differ from
 | 
			
		||||
#        the exported function name (example: the exit syscall is implemented by the _exit()
 | 
			
		||||
#        function, which is not the same as the standard C exit() function which calls it)
 | 
			
		||||
#
 | 
			
		||||
#      - alias_list is optional comma separated list of function aliases.
 | 
			
		||||
#
 | 
			
		||||
#      - The call_id parameter, given that func_name and syscall_name have
 | 
			
		||||
#        The call_id parameter, given that func_name and syscall_name have
 | 
			
		||||
#        been provided, allows the user to specify dispatch style syscalls.
 | 
			
		||||
#        For example, socket() syscall on i386 actually becomes:
 | 
			
		||||
#          socketcall(__NR_socket, 1, *(rest of args on stack)).
 | 
			
		||||
#
 | 
			
		||||
#      - Each parameter type is assumed to be stored in 32 bits.
 | 
			
		||||
#      - each parameter type is assumed to be stored on 32 bits, there is no plan to support
 | 
			
		||||
#        64-bit architectures at the moment
 | 
			
		||||
#
 | 
			
		||||
#      - the final field can be "1", meaning: generate a stub for each architecture,
 | 
			
		||||
#        taking the constants from the kernel header files.
 | 
			
		||||
#
 | 
			
		||||
#      - the final field can be "stub" meaning: do not generate any stubs ---
 | 
			
		||||
#        in this case, a hand-written custom stub must be provided.
 | 
			
		||||
#        TODO: replace this with something like "custom" or "none", or remove
 | 
			
		||||
#        it entirely.
 | 
			
		||||
#
 | 
			
		||||
#      - the final field can be a three-element list of 1s and -1 meaning:
 | 
			
		||||
#        this system call is only available on some of the architectures (1),
 | 
			
		||||
#        and no stub should be generated for those architectures marked with -1.
 | 
			
		||||
#        the order is arm,x86,mips.
 | 
			
		||||
#        TODO: replace this with something more readable like "-arm,-mips" (meaning x86 only).
 | 
			
		||||
#
 | 
			
		||||
# This file is processed by a python script named gensyscalls.py.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
int     execve(const char*, char* const*, char* const*)  all
 | 
			
		||||
# process management
 | 
			
		||||
void    _exit:exit_group (int)      1
 | 
			
		||||
void    _exit_thread:exit (int)     1
 | 
			
		||||
pid_t   __fork:fork (void)           1
 | 
			
		||||
pid_t   _waitpid:waitpid (pid_t, int*, int, struct rusage*)   -1,1,1
 | 
			
		||||
int     __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*)          1
 | 
			
		||||
pid_t   wait4(pid_t pid, int *status, int options, struct rusage *rusage)   1
 | 
			
		||||
 | 
			
		||||
uid_t   getuid:getuid32()         arm,x86
 | 
			
		||||
uid_t   getuid:getuid()           arm64,mips,mips64,x86_64
 | 
			
		||||
gid_t   getgid:getgid32()         arm,x86
 | 
			
		||||
gid_t   getgid:getgid()           arm64,mips,mips64,x86_64
 | 
			
		||||
uid_t   geteuid:geteuid32()       arm,x86
 | 
			
		||||
uid_t   geteuid:geteuid()         arm64,mips,mips64,x86_64
 | 
			
		||||
gid_t   getegid:getegid32()       arm,x86
 | 
			
		||||
gid_t   getegid:getegid()         arm64,mips,mips64,x86_64
 | 
			
		||||
uid_t   getresuid:getresuid32(uid_t* ruid, uid_t* euid, uid_t* suid)   arm,x86
 | 
			
		||||
uid_t   getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid)     arm64,mips,mips64,x86_64
 | 
			
		||||
gid_t   getresgid:getresgid32(gid_t* rgid, gid_t* egid, gid_t* sgid)   arm,x86
 | 
			
		||||
gid_t   getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid)     arm64,mips,mips64,x86_64
 | 
			
		||||
ssize_t readahead(int, off64_t, size_t)     all
 | 
			
		||||
int     getgroups:getgroups32(int, gid_t*)    arm,x86
 | 
			
		||||
int     getgroups:getgroups(int, gid_t*)      arm64,mips,mips64,x86_64
 | 
			
		||||
pid_t   getpgid(pid_t)             all
 | 
			
		||||
pid_t   getppid()                  all
 | 
			
		||||
pid_t   getsid(pid_t)              all
 | 
			
		||||
pid_t   setsid()                   all
 | 
			
		||||
int     setgid:setgid32(gid_t)     arm,x86
 | 
			
		||||
int     setgid:setgid(gid_t)       arm64,mips,mips64,x86_64
 | 
			
		||||
int     setuid:setuid32(uid_t)    arm,x86
 | 
			
		||||
int     setuid:setuid(uid_t)      arm64,mips,mips64,x86_64
 | 
			
		||||
int     setreuid:setreuid32(uid_t, uid_t)   arm,x86
 | 
			
		||||
int     setreuid:setreuid(uid_t, uid_t)     arm64,mips,mips64,x86_64
 | 
			
		||||
int     setresuid:setresuid32(uid_t, uid_t, uid_t)   arm,x86
 | 
			
		||||
int     setresuid:setresuid(uid_t, uid_t, uid_t)     arm64,mips,mips64,x86_64
 | 
			
		||||
int     setresgid:setresgid32(gid_t, gid_t, gid_t)   arm,x86
 | 
			
		||||
int     setresgid:setresgid(gid_t, gid_t, gid_t)     arm64,mips,mips64,x86_64
 | 
			
		||||
void*   __brk:brk(void*)           all
 | 
			
		||||
int     kill(pid_t, int)           all
 | 
			
		||||
int     tgkill(pid_t tgid, pid_t tid, int sig)  all
 | 
			
		||||
int     __ptrace:ptrace(int request, int pid, void* addr, void* data)  all
 | 
			
		||||
# NOTE: this system call is never called directly, but we list it there
 | 
			
		||||
#       to have __NR_clone properly defined.
 | 
			
		||||
#
 | 
			
		||||
pid_t   __sys_clone:clone (int, void*, int*, void*, int*) 1
 | 
			
		||||
 | 
			
		||||
# <sys/resource.h>
 | 
			
		||||
int getrusage(int, struct rusage*)  all
 | 
			
		||||
int __getpriority:getpriority(int, int)  all
 | 
			
		||||
int setpriority(int, int, int)   all
 | 
			
		||||
# On LP64, rlimit and rlimit64 are the same.
 | 
			
		||||
# On 32-bit systems we use prlimit64 to implement the rlimit64 functions.
 | 
			
		||||
int getrlimit:ugetrlimit(int, struct rlimit*)  arm,x86
 | 
			
		||||
int getrlimit(int, struct rlimit*)  mips
 | 
			
		||||
int getrlimit|getrlimit64(int, struct rlimit*)  arm64,mips64,x86_64
 | 
			
		||||
int setrlimit(int, const struct rlimit*)  arm,mips,x86
 | 
			
		||||
int setrlimit|setrlimit64(int, const struct rlimit*)  arm64,mips64,x86_64
 | 
			
		||||
int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*)  arm64,mips64,x86_64
 | 
			
		||||
int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*)  arm,mips,x86
 | 
			
		||||
int     execve (const char*, char* const*, char* const*)  1
 | 
			
		||||
 | 
			
		||||
int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 | 
			
		||||
int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 | 
			
		||||
int     setpgid(pid_t, pid_t)  all
 | 
			
		||||
pid_t   vfork(void)  arm
 | 
			
		||||
int     setregid:setregid32(gid_t, gid_t)  arm,x86
 | 
			
		||||
int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
			
		||||
int     chroot(const char*)  all
 | 
			
		||||
int     prctl(int, unsigned long, unsigned long, unsigned long, unsigned long) all
 | 
			
		||||
long    __arch_prctl:arch_prctl(int, unsigned long) x86_64
 | 
			
		||||
int     capget(cap_user_header_t header, cap_user_data_t data) all
 | 
			
		||||
int     capset(cap_user_header_t header, const cap_user_data_t data) all
 | 
			
		||||
int     sigaltstack(const stack_t*, stack_t*) all
 | 
			
		||||
int     acct(const char*  filepath)  all
 | 
			
		||||
int     __setuid:setuid32 (uid_t)    1,1,-1
 | 
			
		||||
int     __setuid:setuid (uid_t)   -1,-1,1
 | 
			
		||||
uid_t   getuid:getuid32 ()         1,1,-1
 | 
			
		||||
uid_t   getuid:getuid ()           -1,-1,1
 | 
			
		||||
gid_t   getgid:getgid32 ()         1,1,-1
 | 
			
		||||
gid_t   getgid:getgid ()           -1,-1,1
 | 
			
		||||
uid_t   geteuid:geteuid32 ()       1,1,-1
 | 
			
		||||
uid_t   geteuid:geteuid ()         -1,-1,1
 | 
			
		||||
gid_t   getegid:getegid32 ()       1,1,-1
 | 
			
		||||
gid_t   getegid:getegid ()         -1,-1,1
 | 
			
		||||
uid_t   getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid)   1,1,-1
 | 
			
		||||
uid_t   getresuid:getresuid (uid_t *ruid, uid_t *euid, uid_t *suid)     -1,-1,1
 | 
			
		||||
gid_t   getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid)   1,1,-1
 | 
			
		||||
gid_t   getresgid:getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid)     -1,-1,1
 | 
			
		||||
pid_t   gettid()                   1
 | 
			
		||||
ssize_t readahead(int, off64_t, size_t)     1
 | 
			
		||||
int     getgroups:getgroups32(int, gid_t *)    1,1,-1
 | 
			
		||||
int     getgroups:getgroups(int, gid_t *)      -1,-1,1
 | 
			
		||||
pid_t   getpgid(pid_t)             1
 | 
			
		||||
pid_t   getppid()                  1
 | 
			
		||||
pid_t   getsid(pid_t)              1
 | 
			
		||||
pid_t   setsid()                   1
 | 
			
		||||
int     setgid:setgid32(gid_t)     1,1,-1
 | 
			
		||||
int     setgid:setgid(gid_t)       -1,-1,1
 | 
			
		||||
int     seteuid:seteuid32(uid_t)   stub
 | 
			
		||||
int     __setreuid:setreuid32(uid_t, uid_t)   1,1,-1
 | 
			
		||||
int     __setreuid:setreuid(uid_t, uid_t)     -1,-1,1
 | 
			
		||||
int     __setresuid:setresuid32(uid_t, uid_t, uid_t)   1,1,-1
 | 
			
		||||
int     __setresuid:setresuid(uid_t, uid_t, uid_t)     -1,-1,1
 | 
			
		||||
int     setresgid:setresgid32(gid_t, gid_t, gid_t)   1,1,-1
 | 
			
		||||
int     setresgid:setresgid(gid_t, gid_t, gid_t)     -1,-1,1
 | 
			
		||||
void*   __brk:brk(void*)           1
 | 
			
		||||
# see comments in arch-arm/bionic/kill.S to understand why we don't generate an ARM stub for kill/tkill
 | 
			
		||||
int     kill(pid_t, int)           -1,1,1
 | 
			
		||||
int     tkill(pid_t tid, int sig)  -1,1,1
 | 
			
		||||
int     tgkill(pid_t tgid, pid_t tid, int sig)  -1,1,1
 | 
			
		||||
int     __ptrace:ptrace(int request, int pid, void* addr, void* data)  1
 | 
			
		||||
int     __set_thread_area:set_thread_area(void*  user_desc)  -1,1,1
 | 
			
		||||
int     __getpriority:getpriority(int, int)  1
 | 
			
		||||
int     setpriority(int, int, int)   1
 | 
			
		||||
int     setrlimit(int resource, const struct rlimit *rlp)  1
 | 
			
		||||
int     getrlimit:ugetrlimit(int resource, struct rlimit *rlp)  1,1,-1
 | 
			
		||||
int     getrlimit:getrlimit(int resource, struct rlimit *rlp)  -1,-1,1
 | 
			
		||||
int     getrusage(int who, struct rusage*  r_usage)  1
 | 
			
		||||
int     setgroups:setgroups32(int, const gid_t *)   1,1,-1
 | 
			
		||||
int     setgroups:setgroups(int, const gid_t *)     -1,-1,1
 | 
			
		||||
pid_t   getpgrp(void)  stub
 | 
			
		||||
int     setpgid(pid_t, pid_t)  1
 | 
			
		||||
pid_t   vfork(void)  1,-1,-1
 | 
			
		||||
int     setregid:setregid32(gid_t, gid_t)  1,1,-1
 | 
			
		||||
int     setregid:setregid(gid_t, gid_t)    -1,-1,1
 | 
			
		||||
int     chroot(const char *)  1
 | 
			
		||||
# IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
 | 
			
		||||
#            to match the kernel implementation.
 | 
			
		||||
int     prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5) 1
 | 
			
		||||
int     capget(cap_user_header_t header, cap_user_data_t data) 1
 | 
			
		||||
int     capset(cap_user_header_t header, const cap_user_data_t data) 1
 | 
			
		||||
int     sigaltstack(const stack_t*, stack_t*) 1
 | 
			
		||||
int     acct(const char*  filepath)  1
 | 
			
		||||
 | 
			
		||||
# file descriptors
 | 
			
		||||
ssize_t     read(int, void*, size_t)        all
 | 
			
		||||
ssize_t     write(int, const void*, size_t)       all
 | 
			
		||||
ssize_t     pread64(int, void*, size_t, off64_t) arm,mips,x86
 | 
			
		||||
ssize_t     pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
 | 
			
		||||
ssize_t     pwrite64(int, void*, size_t, off64_t) arm,mips,x86
 | 
			
		||||
ssize_t     pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
 | 
			
		||||
int         ___close:close(int)  all
 | 
			
		||||
pid_t       __getpid:getpid()  all
 | 
			
		||||
int         munmap(void*, size_t)  all
 | 
			
		||||
void*       mremap(void*, size_t, size_t, unsigned long)  all
 | 
			
		||||
int         msync(const void*, size_t, int)    all
 | 
			
		||||
int         mprotect(const void*, size_t, int)  all
 | 
			
		||||
int         madvise(void*, size_t, int)  all
 | 
			
		||||
int         mlock(const void* addr, size_t len)    all
 | 
			
		||||
int         munlock(const void* addr, size_t len)   all
 | 
			
		||||
int         mlockall(int flags)   all
 | 
			
		||||
int         munlockall()   all
 | 
			
		||||
int         mincore(void*  start, size_t  length, unsigned char*  vec)   all
 | 
			
		||||
int         __ioctl:ioctl(int, int, void*)  all
 | 
			
		||||
int         readv(int, const struct iovec*, int)   all
 | 
			
		||||
int         writev(int, const struct iovec*, int)  all
 | 
			
		||||
int         __fcntl64:fcntl64(int, int, void*)  arm,mips,x86
 | 
			
		||||
int         fcntl(int, int, void*)  arm64,mips64,x86_64
 | 
			
		||||
int         flock(int, int)   all
 | 
			
		||||
int         ___fchmod:fchmod(int, mode_t)  all
 | 
			
		||||
int         dup(int)  all
 | 
			
		||||
int         pipe2(int*, int) all
 | 
			
		||||
int         dup3(int, int, int)   all
 | 
			
		||||
int         fsync(int)  all
 | 
			
		||||
int         fdatasync(int) all
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  arm,x86
 | 
			
		||||
int         fchown:fchown(int, uid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
			
		||||
void        sync(void)  all
 | 
			
		||||
int         ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
 | 
			
		||||
ssize_t     flistxattr(int, char*, size_t) all
 | 
			
		||||
int         fremovexattr(int, const char*) all
 | 
			
		||||
 | 
			
		||||
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int)   arm,arm64,mips,mips64,x86,x86_64
 | 
			
		||||
 | 
			
		||||
int __openat:openat(int, const char*, int, mode_t) all
 | 
			
		||||
int ___faccessat:faccessat(int, const char*, int)  all
 | 
			
		||||
int ___fchmodat:fchmodat(int, const char*, mode_t)  all
 | 
			
		||||
int fchownat(int, const char*, uid_t, gid_t, int)  all
 | 
			
		||||
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   arm,mips,x86
 | 
			
		||||
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,x86_64
 | 
			
		||||
int linkat(int, const char*, int, const char*, int)  all
 | 
			
		||||
int mkdirat(int, const char*, mode_t)  all
 | 
			
		||||
int mknodat(int, const char*, mode_t, dev_t)  all
 | 
			
		||||
int readlinkat(int, const char*, char*, size_t)  all
 | 
			
		||||
int renameat(int, const char*, int, const char*)  all
 | 
			
		||||
int symlinkat(const char*, int, const char*)  all
 | 
			
		||||
int unlinkat(int, const char*, int)   all
 | 
			
		||||
int utimensat(int, const char*, const struct timespec times[2], int)  all
 | 
			
		||||
 | 
			
		||||
# Paired off_t/off64_t system calls. On 64-bit systems,
 | 
			
		||||
# sizeof(off_t) == sizeof(off64_t), so there we emit two symbols that are
 | 
			
		||||
# aliases. On 32-bit systems, we have two different system calls.
 | 
			
		||||
# That means that every system call in this section should take three lines.
 | 
			
		||||
off_t lseek(int, off_t, int) arm,mips,x86
 | 
			
		||||
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
 | 
			
		||||
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
 | 
			
		||||
int ftruncate64(int, off64_t) arm,mips,x86
 | 
			
		||||
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
 | 
			
		||||
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
 | 
			
		||||
ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) arm,mips,x86
 | 
			
		||||
ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) arm64,mips64,x86_64
 | 
			
		||||
int truncate(const char*, off_t) arm,mips,x86
 | 
			
		||||
int truncate64(const char*, off64_t) arm,mips,x86
 | 
			
		||||
int truncate|truncate64(const char*, off_t) arm64,mips64,x86_64
 | 
			
		||||
# (mmap only gets two lines because we only used the 64-bit variant on 32-bit systems.)
 | 
			
		||||
void* __mmap2:mmap2(void*, size_t, int, int, int, long)   arm,mips,x86
 | 
			
		||||
void* mmap|mmap64(void*, size_t, int, int, int, off_t)  arm64,mips64,x86_64
 | 
			
		||||
# (fallocate only gets two lines because there is no 32-bit variant.)
 | 
			
		||||
int fallocate64:fallocate(int, int, off64_t, off64_t) arm,mips,x86
 | 
			
		||||
int fallocate|fallocate64(int, int, off_t, off_t) arm64,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
# posix_fadvise64 is awkward: arm has shuffled arguments,
 | 
			
		||||
# the POSIX functions don't set errno, and no architecture has posix_fadvise.
 | 
			
		||||
int __arm_fadvise64_64:arm_fadvise64_64(int, int, off64_t, off64_t) arm
 | 
			
		||||
int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
 | 
			
		||||
int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
int __fstatfs64:fstatfs64(int, size_t, struct statfs*)  arm,mips,x86
 | 
			
		||||
int __fstatfs:fstatfs(int, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
int __statfs64:statfs64(const char*, size_t, struct statfs*)  arm,mips,x86
 | 
			
		||||
int __statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
 | 
			
		||||
int     fstat64|fstat:fstat64(int, struct stat*)    arm,mips,x86
 | 
			
		||||
int     fstat64|fstat:fstat(int, struct stat*)    arm64,x86_64
 | 
			
		||||
ssize_t     read (int, void*, size_t)        1
 | 
			
		||||
ssize_t     write (int, const void*, size_t)       1
 | 
			
		||||
ssize_t     pread64 (int, void *, size_t, off64_t) 1
 | 
			
		||||
ssize_t     pwrite64 (int, void *, size_t, off64_t) 1
 | 
			
		||||
int         __open:open (const char*, int, mode_t)  1
 | 
			
		||||
int         __openat:openat (int, const char*, int, mode_t) 1
 | 
			
		||||
int         close (int)                      1
 | 
			
		||||
int         creat(const char*, mode_t)       stub
 | 
			
		||||
off_t       lseek(int, off_t, int)           1
 | 
			
		||||
int         __llseek:_llseek (int, unsigned long, unsigned long, loff_t*, int)  1
 | 
			
		||||
pid_t       getpid ()    1
 | 
			
		||||
void *      mmap(void *, size_t, int, int, int, long)  stub
 | 
			
		||||
void *      __mmap2:mmap2(void*, size_t, int, int, int, long)   1
 | 
			
		||||
int         munmap(void *, size_t)  1
 | 
			
		||||
void *      mremap(void *, size_t, size_t, unsigned long)  1
 | 
			
		||||
int         msync(const void *, size_t, int)    1
 | 
			
		||||
int         mprotect(const void *, size_t, int)  1
 | 
			
		||||
int         madvise(const void *, size_t, int)  1
 | 
			
		||||
int         mlock(const void *addr, size_t len)    1
 | 
			
		||||
int         munlock(const void *addr, size_t len)   1
 | 
			
		||||
int         mlockall(int flags)   1
 | 
			
		||||
int         munlockall()   1
 | 
			
		||||
int         mincore(void*  start, size_t  length, unsigned char*  vec)   1
 | 
			
		||||
int         __ioctl:ioctl(int, int, void *)  1
 | 
			
		||||
int         readv(int, const struct iovec *, int)   1
 | 
			
		||||
int         writev(int, const struct iovec *, int)  1
 | 
			
		||||
int         __fcntl:fcntl(int, int, void*)  1
 | 
			
		||||
int         flock(int, int)   1
 | 
			
		||||
int         fchmod(int, mode_t)  1
 | 
			
		||||
int         dup(int)  1
 | 
			
		||||
int         pipe(int *)  1,1,-1
 | 
			
		||||
int         pipe2(int *, int) 1
 | 
			
		||||
int         dup2(int, int)   1
 | 
			
		||||
int         select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *)  1
 | 
			
		||||
int         ftruncate(int, off_t)  1
 | 
			
		||||
int         ftruncate64(int, off64_t) 1
 | 
			
		||||
int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   1
 | 
			
		||||
int         fsync(int)  1
 | 
			
		||||
int         fdatasync(int) 1
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  1,1,-1
 | 
			
		||||
int         fchown:fchown(int, uid_t, gid_t)    -1,-1,1
 | 
			
		||||
void        sync(void)  1
 | 
			
		||||
int         __fcntl64:fcntl64(int, int, void *)  1
 | 
			
		||||
int         __fstatfs64:fstatfs64(int, size_t, struct statfs *)  1
 | 
			
		||||
ssize_t     sendfile(int out_fd, int in_fd, off_t *offset, size_t count)  1
 | 
			
		||||
int         fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags)   1
 | 
			
		||||
int         mkdirat(int dirfd, const char *pathname, mode_t mode)  1
 | 
			
		||||
int         fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags)  1
 | 
			
		||||
int         fchmodat(int dirfd, const char *path, mode_t mode, int flags)  1
 | 
			
		||||
int         renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)  1
 | 
			
		||||
int         fsetxattr(int, const char *, const void *, size_t, int) 1
 | 
			
		||||
ssize_t     fgetxattr(int, const char *, void *, size_t) 1
 | 
			
		||||
ssize_t     flistxattr(int, char *, size_t) 1
 | 
			
		||||
int         fremovexattr(int, const char *) 1
 | 
			
		||||
 | 
			
		||||
# file system
 | 
			
		||||
int     chdir(const char*)              all
 | 
			
		||||
int     mount(const char*, const char*, const char*, unsigned long, const void*)  all
 | 
			
		||||
int     umount2(const char*, int)  all
 | 
			
		||||
int     __getcwd:getcwd(char* buf, size_t size)  all
 | 
			
		||||
int     fchdir(int)    all
 | 
			
		||||
int     setxattr(const char*, const char*, const void*, size_t, int) all
 | 
			
		||||
int     lsetxattr(const char*, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t getxattr(const char*, const char*, void*, size_t) all
 | 
			
		||||
ssize_t lgetxattr(const char*, const char*, void*, size_t) all
 | 
			
		||||
ssize_t listxattr(const char*, char*, size_t) all
 | 
			
		||||
ssize_t llistxattr(const char*, char*, size_t) all
 | 
			
		||||
int     removexattr(const char*, const char*) all
 | 
			
		||||
int     lremovexattr(const char*, const char*) all
 | 
			
		||||
int     swapon(const char*, int) all
 | 
			
		||||
int     swapoff(const char*) all
 | 
			
		||||
int     link (const char*, const char*)  1
 | 
			
		||||
int     unlink (const char*)             1
 | 
			
		||||
int     unlinkat (int, const char *, int)   1
 | 
			
		||||
int     chdir (const char*)              1
 | 
			
		||||
int     mknod (const char*, mode_t, dev_t)  1
 | 
			
		||||
int     chmod (const char*,mode_t)          1
 | 
			
		||||
int     chown:chown32(const char *, uid_t, gid_t)  1,1,-1
 | 
			
		||||
int     chown:chown(const char *, uid_t, gid_t)    -1,-1,1
 | 
			
		||||
int     lchown:lchown32 (const char*, uid_t, gid_t)  1,1,-1
 | 
			
		||||
int     lchown:lchown (const char*, uid_t, gid_t)  -1,-1,1
 | 
			
		||||
int     mount (const char*, const char*, const char*, unsigned long, const void*)  1
 | 
			
		||||
int     umount(const char*)  stub
 | 
			
		||||
int     umount2 (const char*, int)  1
 | 
			
		||||
int     fstat:fstat64(int, struct stat*)    1
 | 
			
		||||
int     stat:stat64(const char *, struct stat *)  1
 | 
			
		||||
int     lstat:lstat64(const char *, struct stat *)  1
 | 
			
		||||
int     mkdir(const char *, mode_t) 1
 | 
			
		||||
int     readlink(const char *, char *, size_t)  1
 | 
			
		||||
int     rmdir(const char *)  1
 | 
			
		||||
int     rename(const char *, const char *)  1
 | 
			
		||||
int     __getcwd:getcwd(char * buf, size_t size)  1
 | 
			
		||||
int     access(const char *, int)  1
 | 
			
		||||
int     faccessat(int, const char *, int, int)  1
 | 
			
		||||
int     symlink(const char *, const char *)  1
 | 
			
		||||
int     fchdir(int)    1
 | 
			
		||||
int     truncate(const char*, off_t)    1
 | 
			
		||||
int     setxattr(const char *, const char *, const void *, size_t, int) 1
 | 
			
		||||
int     lsetxattr(const char *, const char *, const void *, size_t, int) 1
 | 
			
		||||
ssize_t getxattr(const char *, const char *, void *, size_t) 1
 | 
			
		||||
ssize_t lgetxattr(const char *, const char *, void *, size_t) 1
 | 
			
		||||
ssize_t listxattr(const char *, char *, size_t) 1
 | 
			
		||||
ssize_t llistxattr(const char *, char *, size_t) 1
 | 
			
		||||
int     removexattr(const char *, const char *) 1
 | 
			
		||||
int     lremovexattr(const char *, const char *) 1
 | 
			
		||||
int     __statfs64:statfs64(const char *, size_t, struct statfs *)  1
 | 
			
		||||
long    unshare(unsigned long)  1
 | 
			
		||||
 | 
			
		||||
# time
 | 
			
		||||
int           settimeofday(const struct timeval*, const struct timezone*)   all
 | 
			
		||||
clock_t       times(struct tms*)       all
 | 
			
		||||
int           nanosleep(const struct timespec*, struct timespec*)   all
 | 
			
		||||
int           clock_settime(clockid_t, const struct timespec*)  all
 | 
			
		||||
int           clock_getres(clockid_t, struct timespec*)   all
 | 
			
		||||
int           ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
 | 
			
		||||
int           getitimer(int, const struct itimerval*)   all
 | 
			
		||||
int           setitimer(int, const struct itimerval*, struct itimerval*)  all
 | 
			
		||||
int           __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid)    all
 | 
			
		||||
int           __timer_settime:timer_settime(__kernel_timer_t, int, const struct itimerspec*, struct itimerspec*) all
 | 
			
		||||
int           __timer_gettime:timer_gettime(__kernel_timer_t, struct itimerspec*)                                all
 | 
			
		||||
int           __timer_getoverrun:timer_getoverrun(__kernel_timer_t)                                              all
 | 
			
		||||
int           __timer_delete:timer_delete(__kernel_timer_t)                                                      all
 | 
			
		||||
int           timerfd_create(clockid_t, int)   all
 | 
			
		||||
int           timerfd_settime(int, int, const struct itimerspec*, struct itimerspec*)   all
 | 
			
		||||
int           timerfd_gettime(int, struct itimerspec*)   all
 | 
			
		||||
int           pause ()                       1
 | 
			
		||||
int           gettimeofday(struct timeval*, struct timezone*)       1
 | 
			
		||||
int           settimeofday(const struct timeval*, const struct timezone*)   1
 | 
			
		||||
clock_t       times(struct tms *)       1
 | 
			
		||||
int           nanosleep(const struct timespec *, struct timespec *)   1
 | 
			
		||||
int           clock_gettime(clockid_t clk_id, struct timespec *tp)    1
 | 
			
		||||
int           clock_settime(clockid_t clk_id, const struct timespec *tp)  1
 | 
			
		||||
int           clock_getres(clockid_t clk_id, struct timespec *res)   1
 | 
			
		||||
int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem)  1
 | 
			
		||||
int           getitimer(int, const struct itimerval *)   1
 | 
			
		||||
int           setitimer(int, const struct itimerval *, struct itimerval *)  1
 | 
			
		||||
int           __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)    1
 | 
			
		||||
int           __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 1
 | 
			
		||||
int           __timer_gettime:timer_gettime(timer_t, struct itimerspec*)                                1
 | 
			
		||||
int           __timer_getoverrun:timer_getoverrun(timer_t)                                              1
 | 
			
		||||
int           __timer_delete:timer_delete(timer_t)                                                      1
 | 
			
		||||
int           utimes(const char*, const struct timeval tvp[2])                          1
 | 
			
		||||
int           utimensat(int, const char *, const struct timespec times[2], int)         1
 | 
			
		||||
 | 
			
		||||
# signals
 | 
			
		||||
int     __sigaction:sigaction(int, const struct sigaction*, struct sigaction*)  arm,mips,x86
 | 
			
		||||
int     __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t)  all
 | 
			
		||||
int     __rt_sigpending:rt_sigpending(sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t)  all
 | 
			
		||||
int     ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
 | 
			
		||||
int     __signalfd4:signalfd4(int, const sigset_t*, size_t, int)  all
 | 
			
		||||
int     sigaction(int, const struct sigaction *, struct sigaction *)  1
 | 
			
		||||
int     sigprocmask(int, const sigset_t *, sigset_t *)  1
 | 
			
		||||
int     __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask)  1,1,-1
 | 
			
		||||
int     __sigsuspend:sigsuspend(const sigset_t *mask)  -1,-1,1
 | 
			
		||||
int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  1
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  1
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  1
 | 
			
		||||
int     sigpending(sigset_t *)  1
 | 
			
		||||
int     signalfd4(int fd, const sigset_t *mask, size_t sizemask, int flags)  1
 | 
			
		||||
 | 
			
		||||
# sockets
 | 
			
		||||
int           __socket:socket(int, int, int)              arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           socketpair(int, int, int, int*)    arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           bind(int, struct sockaddr*, int)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           __connect:connect(int, struct sockaddr*, socklen_t)   arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           listen(int, int)                   arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           __accept4:accept4(int, struct sockaddr*, socklen_t*, int)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           getsockname(int, struct sockaddr*, socklen_t*)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           getpeername(int, struct sockaddr*, socklen_t*)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           shutdown(int, int)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           setsockopt(int, int, int, const void*, socklen_t)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           getsockopt(int, int, int, void*, socklen_t*)    arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           sendmsg(int, const struct msghdr*, unsigned int)  arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           sendmmsg(int, struct mmsghdr*, unsigned int, int)   arm,arm64,mips,mips64,x86_64
 | 
			
		||||
int           socket(int, int, int)              1,-1,1
 | 
			
		||||
int           socketpair(int, int, int, int*)    1,-1,1
 | 
			
		||||
int           bind(int, struct sockaddr *, int)  1,-1,1
 | 
			
		||||
int           connect(int, struct sockaddr *, socklen_t)   1,-1,1
 | 
			
		||||
int           listen(int, int)                   1,-1,1
 | 
			
		||||
int           accept(int, struct sockaddr *, socklen_t *)  1,-1,1
 | 
			
		||||
int           getsockname(int, struct sockaddr *, socklen_t *)  1,-1,1
 | 
			
		||||
int           getpeername(int, struct sockaddr *, socklen_t *)  1,-1,1
 | 
			
		||||
int           sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  1,-1,1
 | 
			
		||||
int           recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  1,-1,1
 | 
			
		||||
int           shutdown(int, int)  1,-1,1
 | 
			
		||||
int           setsockopt(int, int, int, const void *, socklen_t)  1,-1,1
 | 
			
		||||
int           getsockopt(int, int, int, void *, socklen_t *)    1,-1,1
 | 
			
		||||
int           sendmsg(int, const struct msghdr *, unsigned int)  1,-1,1
 | 
			
		||||
int           recvmsg(int, struct msghdr *, unsigned int)   1,-1,1
 | 
			
		||||
 | 
			
		||||
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
 | 
			
		||||
int           __socket:socketcall:1(int, int, int) x86
 | 
			
		||||
int           bind:socketcall:2(int, struct sockaddr*, int)  x86
 | 
			
		||||
int           __connect:socketcall:3(int, struct sockaddr*, socklen_t)   x86
 | 
			
		||||
int           listen:socketcall:4(int, int)                   x86
 | 
			
		||||
int           getsockname:socketcall:6(int, struct sockaddr*, socklen_t*)  x86
 | 
			
		||||
int           getpeername:socketcall:7(int, struct sockaddr*, socklen_t*)  x86
 | 
			
		||||
int           socketpair:socketcall:8(int, int, int, int*)    x86
 | 
			
		||||
int           sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t)  x86
 | 
			
		||||
int           recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*)  x86
 | 
			
		||||
int           shutdown:socketcall:13(int, int)  x86
 | 
			
		||||
int           setsockopt:socketcall:14(int, int, int, const void*, socklen_t)  x86
 | 
			
		||||
int           getsockopt:socketcall:15(int, int, int, void*, socklen_t*)    x86
 | 
			
		||||
int           sendmsg:socketcall:16(int, const struct msghdr*, unsigned int)  x86
 | 
			
		||||
int           recvmsg:socketcall:17(int, struct msghdr*, unsigned int)   x86
 | 
			
		||||
int           __accept4:socketcall:18(int, struct sockaddr*, socklen_t*, int)  x86
 | 
			
		||||
int           recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   x86
 | 
			
		||||
int           sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int)   x86
 | 
			
		||||
int           socket:socketcall:1 (int, int, int) -1,1,-1
 | 
			
		||||
int           bind:socketcall:2 (int, struct sockaddr *, int)  -1,1,-1
 | 
			
		||||
int           connect:socketcall:3(int, struct sockaddr *, socklen_t)   -1,1,-1
 | 
			
		||||
int           listen:socketcall:4(int, int)                   -1,1,-1
 | 
			
		||||
int           accept:socketcall:5(int, struct sockaddr *, socklen_t *)  -1,1,-1
 | 
			
		||||
int           getsockname:socketcall:6(int, struct sockaddr *, socklen_t *)  -1,1,-1
 | 
			
		||||
int           getpeername:socketcall:7(int, struct sockaddr *, socklen_t *)  -1,1,-1
 | 
			
		||||
int           socketpair:socketcall:8(int, int, int, int*)    -1,1,-1
 | 
			
		||||
int           sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  -1,1,-1
 | 
			
		||||
int           recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  -1,1,-1
 | 
			
		||||
int           shutdown:socketcall:13(int, int)  -1,1,-1
 | 
			
		||||
int           setsockopt:socketcall:14(int, int, int, const void *, socklen_t)  -1,1,-1
 | 
			
		||||
int           getsockopt:socketcall:15(int, int, int, void *, socklen_t *)    -1,1,-1
 | 
			
		||||
int           sendmsg:socketcall:16(int, const struct msghdr *, unsigned int)  -1,1,-1
 | 
			
		||||
int           recvmsg:socketcall:17(int, struct msghdr *, unsigned int)   -1,1,-1
 | 
			
		||||
 | 
			
		||||
# scheduler & real-time
 | 
			
		||||
int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param)  all
 | 
			
		||||
int sched_getscheduler(pid_t pid)  all
 | 
			
		||||
int sched_yield(void)  all
 | 
			
		||||
int sched_setparam(pid_t pid, const struct sched_param* param)  all
 | 
			
		||||
int sched_getparam(pid_t pid, struct sched_param* param)  all
 | 
			
		||||
int sched_get_priority_max(int policy)  all
 | 
			
		||||
int sched_get_priority_min(int policy)  all
 | 
			
		||||
int sched_rr_get_interval(pid_t pid, struct timespec* interval)  all
 | 
			
		||||
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) all
 | 
			
		||||
int setns(int, int) all
 | 
			
		||||
int unshare(int) all
 | 
			
		||||
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  all
 | 
			
		||||
int __getcpu:getcpu(unsigned*, unsigned*, void*) all
 | 
			
		||||
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)  1
 | 
			
		||||
int sched_getscheduler(pid_t pid)  1
 | 
			
		||||
int sched_yield(void)  1
 | 
			
		||||
int sched_setparam(pid_t pid, const struct sched_param *param)  1
 | 
			
		||||
int sched_getparam(pid_t pid, struct sched_param *param)  1
 | 
			
		||||
int sched_get_priority_max(int policy)  1
 | 
			
		||||
int sched_get_priority_min(int policy)  1
 | 
			
		||||
int sched_rr_get_interval(pid_t pid, struct timespec *interval)  1
 | 
			
		||||
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 1
 | 
			
		||||
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  1
 | 
			
		||||
int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 1
 | 
			
		||||
 | 
			
		||||
# io priorities
 | 
			
		||||
int ioprio_set(int which, int who, int ioprio) 1
 | 
			
		||||
int ioprio_get(int which, int who) 1
 | 
			
		||||
 | 
			
		||||
# other
 | 
			
		||||
int     uname(struct utsname*)  all
 | 
			
		||||
mode_t  umask(mode_t)  all
 | 
			
		||||
int     __reboot:reboot(int, int, int, void*)  all
 | 
			
		||||
int     init_module(void*, unsigned long, const char*)  all
 | 
			
		||||
int     delete_module(const char*, unsigned int)   all
 | 
			
		||||
int     klogctl:syslog(int, char*, int)   all
 | 
			
		||||
int     sysinfo(struct sysinfo*)  all
 | 
			
		||||
int     personality(unsigned long)  all
 | 
			
		||||
int     uname(struct utsname *)  1
 | 
			
		||||
mode_t  umask(mode_t)  1
 | 
			
		||||
int      __reboot:reboot(int, int, int, void *)  1
 | 
			
		||||
int     __syslog:syslog(int, char *, int)  1
 | 
			
		||||
int     init_module(void *, unsigned long, const char *)  1
 | 
			
		||||
int     delete_module(const char*, unsigned int)   1
 | 
			
		||||
int     klogctl:syslog(int, char *, int)   1
 | 
			
		||||
int     sysinfo(struct sysinfo *)  1
 | 
			
		||||
int     personality(unsigned long)  1
 | 
			
		||||
long    perf_event_open(struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) 1
 | 
			
		||||
 | 
			
		||||
ssize_t tee(int, int, size_t, unsigned int)  all
 | 
			
		||||
ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int)  all
 | 
			
		||||
ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int)  all
 | 
			
		||||
# futex
 | 
			
		||||
int	futex(void *, int, int, void *, void *, int) 1
 | 
			
		||||
 | 
			
		||||
int epoll_create1(int)  all
 | 
			
		||||
int epoll_ctl(int, int op, int, struct epoll_event*)  all
 | 
			
		||||
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t)  all
 | 
			
		||||
# epoll
 | 
			
		||||
int     epoll_create(int size)     1
 | 
			
		||||
int     epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)    1
 | 
			
		||||
int     epoll_wait(int epfd, struct epoll_event *events, int max, int timeout)   1
 | 
			
		||||
 | 
			
		||||
int eventfd:eventfd2(unsigned int, int)  all
 | 
			
		||||
int     inotify_init(void)      1
 | 
			
		||||
int     inotify_add_watch(int, const char *, unsigned int)  1
 | 
			
		||||
int     inotify_rm_watch(int, unsigned int)  1
 | 
			
		||||
 | 
			
		||||
void _exit|_Exit:exit_group(int)  all
 | 
			
		||||
void __exit:exit(int)  all
 | 
			
		||||
int     poll(struct pollfd *, unsigned int, long)  1
 | 
			
		||||
 | 
			
		||||
int inotify_init1(int)  all
 | 
			
		||||
int inotify_add_watch(int, const char*, unsigned int)  all
 | 
			
		||||
int inotify_rm_watch(int, unsigned int)  all
 | 
			
		||||
int     eventfd:eventfd2(unsigned int, int)  1
 | 
			
		||||
 | 
			
		||||
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*)  all
 | 
			
		||||
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t)  all
 | 
			
		||||
 | 
			
		||||
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
 | 
			
		||||
int __set_tid_address:set_tid_address(int*)  all
 | 
			
		||||
 | 
			
		||||
int setfsgid(gid_t)  all
 | 
			
		||||
int setfsuid(uid_t)  all
 | 
			
		||||
 | 
			
		||||
int sethostname(const char*, size_t)  all
 | 
			
		||||
 | 
			
		||||
pid_t wait4(pid_t, int*, int, struct rusage*)  all
 | 
			
		||||
int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*)  all
 | 
			
		||||
 | 
			
		||||
# ARM-specific
 | 
			
		||||
int     __set_tls:__ARM_NR_set_tls(void*)                                 arm
 | 
			
		||||
int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  arm
 | 
			
		||||
# ARM-specific ARM_NR_BASE == 0x0f0000 == 983040
 | 
			
		||||
int     __set_tls:__ARM_NR_set_tls(void*)                                 1,-1,-1
 | 
			
		||||
int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  1,-1,-1
 | 
			
		||||
 | 
			
		||||
# MIPS-specific
 | 
			
		||||
int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
 | 
			
		||||
int     __set_tls:set_thread_area(void*) mips,mips64
 | 
			
		||||
 | 
			
		||||
# x86-specific
 | 
			
		||||
int     __set_thread_area:set_thread_area(void*) x86
 | 
			
		||||
 | 
			
		||||
# vdso stuff.
 | 
			
		||||
int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
 | 
			
		||||
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
 | 
			
		||||
int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
 | 
			
		||||
int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
 | 
			
		||||
int     _flush_cache:cacheflush(char *addr, const int nbytes, const int op) -1,-1,1
 | 
			
		||||
int     syscall(int number,...) -1,-1,1
 | 
			
		||||
 
 | 
			
		||||
@@ -1,73 +1,35 @@
 | 
			
		||||
# 32-bit arm.
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default implementations of functions that are commonly optimized.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    bionic/strchr.cpp \
 | 
			
		||||
    bionic/strnlen.c \
 | 
			
		||||
    bionic/strrchr.cpp \
 | 
			
		||||
 | 
			
		||||
libc_freebsd_src_files_arm += \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcscat.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcschr.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcscmp.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcscpy.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcslen.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcsrchr.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wmemcmp.c \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wmemmove.c \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memchr.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memrchr.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpncpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strncat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strncmp.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strncpy.c \
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Inherently architecture-specific code.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
_LIBC_ARCH_COMMON_SRC_FILES := \
 | 
			
		||||
    arch-arm/bionic/abort_arm.S \
 | 
			
		||||
    arch-arm/bionic/atomics_arm.c \
 | 
			
		||||
    arch-arm/bionic/__bionic_clone.S \
 | 
			
		||||
    arch-arm/bionic/clone.S \
 | 
			
		||||
    arch-arm/bionic/eabi.c \
 | 
			
		||||
    arch-arm/bionic/_exit_with_stack_teardown.S \
 | 
			
		||||
    arch-arm/bionic/ffs.S \
 | 
			
		||||
    arch-arm/bionic/futex_arm.S \
 | 
			
		||||
    arch-arm/bionic/__get_sp.S \
 | 
			
		||||
    arch-arm/bionic/kill.S \
 | 
			
		||||
    arch-arm/bionic/libgcc_compat.c \
 | 
			
		||||
    arch-arm/bionic/__restore.S \
 | 
			
		||||
    arch-arm/bionic/memcmp16.S \
 | 
			
		||||
    arch-arm/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/bionic/_setjmp.S \
 | 
			
		||||
    arch-arm/bionic/setjmp.S \
 | 
			
		||||
    arch-arm/bionic/sigsetjmp.S \
 | 
			
		||||
    arch-arm/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/bionic/strlen.c.arm \
 | 
			
		||||
    arch-arm/bionic/syscall.S \
 | 
			
		||||
    arch-arm/bionic/tgkill.S \
 | 
			
		||||
    arch-arm/bionic/tkill.S \
 | 
			
		||||
 | 
			
		||||
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 | 
			
		||||
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
 | 
			
		||||
# These are used by the static and dynamic versions of the libc
 | 
			
		||||
# respectively.
 | 
			
		||||
_LIBC_ARCH_STATIC_SRC_FILES := \
 | 
			
		||||
    arch-arm/bionic/exidx_static.c
 | 
			
		||||
 | 
			
		||||
## CPU variant specific source files
 | 
			
		||||
ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
 | 
			
		||||
  $(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
 | 
			
		||||
_LIBC_ARCH_DYNAMIC_SRC_FILES := \
 | 
			
		||||
    arch-arm/bionic/exidx_dynamic.c
 | 
			
		||||
 | 
			
		||||
ifeq ($(strip $(wildcard bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk)),)
 | 
			
		||||
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 | 
			
		||||
endif
 | 
			
		||||
cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
 | 
			
		||||
ifeq ($(wildcard $(cpu_variant_mk)),)
 | 
			
		||||
$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 | 
			
		||||
endif
 | 
			
		||||
include $(cpu_variant_mk)
 | 
			
		||||
libc_common_additional_dependencies += $(cpu_variant_mk)
 | 
			
		||||
 | 
			
		||||
cpu_variant_mk :=
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
libc_crt_target_cflags_arm := \
 | 
			
		||||
    -I$(LOCAL_PATH)/arch-arm/include \
 | 
			
		||||
    -mthumb-interwork
 | 
			
		||||
 | 
			
		||||
libc_crt_target_so_cflags_arm :=
 | 
			
		||||
 | 
			
		||||
libc_crt_target_crtbegin_file_arm := \
 | 
			
		||||
    $(LOCAL_PATH)/arch-common/bionic/crtbegin.c
 | 
			
		||||
 | 
			
		||||
libc_crt_target_crtbegin_so_file_arm := \
 | 
			
		||||
    $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c
 | 
			
		||||
include bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
 | 
			
		||||
 
 | 
			
		||||
@@ -1,113 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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(__clang__)
 | 
			
		||||
// clang interprets -fno-builtin more loosely than you might expect,
 | 
			
		||||
// and thinks it's okay to still substitute builtins as long as they're
 | 
			
		||||
// named __aeabi_* rather than __builtin_*, which causes infinite
 | 
			
		||||
// recursion if we have the fortified memcpy visible in this file.
 | 
			
		||||
#undef _FORTIFY_SOURCE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
extern int __cxa_atexit(void (*)(void*), void*, void*);
 | 
			
		||||
 | 
			
		||||
// All of these are weak symbols to avoid multiple definition errors when
 | 
			
		||||
// linking with libstdc++-v3 or compiler-rt.
 | 
			
		||||
 | 
			
		||||
/* The "C++ ABI for ARM" document states that static C++ constructors,
 | 
			
		||||
 * which are called from the .init_array, should manually call
 | 
			
		||||
 * __aeabi_atexit() to register static destructors explicitly.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that 'dso_handle' is the address of a magic linker-generate
 | 
			
		||||
 * variable from the shared object that contains the constructor/destructor
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int __attribute__((weak))
 | 
			
		||||
__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
 | 
			
		||||
    return __cxa_atexit(destructor, object, dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak))
 | 
			
		||||
__aeabi_memcpy8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memcpy4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memcpy(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * __aeabi_memset has the order of its second and third arguments reversed.
 | 
			
		||||
 *  This allows __aeabi_memclr to tail-call __aeabi_memset
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset8(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset4(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memset(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr8(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset8(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr4(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset4(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __attribute__((weak)) __aeabi_memclr(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,70 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
 | 
			
		||||
ENTRY(__bionic_clone)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    # save registers to parent stack
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
 | 
			
		||||
    # load extra parameters
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
 | 
			
		||||
    # Push 'fn' and 'arg' onto the child stack.
 | 
			
		||||
    stmdb   r1!, {r5, r6}
 | 
			
		||||
 | 
			
		||||
    # Make the system call.
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
 | 
			
		||||
    # Are we the child?
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    beq     1f
 | 
			
		||||
 | 
			
		||||
    # In the parent, reload saved registers then either return or set errno.
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
 | 
			
		||||
1:  # The child.
 | 
			
		||||
    # Setting lr to 0 will make the unwinder stop at __start_thread
 | 
			
		||||
    mov    lr, #0
 | 
			
		||||
    # Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
 | 
			
		||||
    pop    {r0, r1}
 | 
			
		||||
    b      __start_thread
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
.hidden __bionic_clone
 | 
			
		||||
							
								
								
									
										34
									
								
								libc/arch-arm/bionic/__get_sp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								libc/arch-arm/bionic/__get_sp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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>
 | 
			
		||||
 | 
			
		||||
ENTRY(__get_sp)
 | 
			
		||||
  mov r0, sp
 | 
			
		||||
  bx lr
 | 
			
		||||
END(__get_sp)
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
// gdb is smart enough to unwind through signal frames with just the regular
 | 
			
		||||
// CFI information but libgcc and libunwind both need extra help. We do this
 | 
			
		||||
// by using .fnstart/.fnend and inserting a nop before both __restore and
 | 
			
		||||
// __restore_rt (but covered by the .fnstart/.fnend) so that although they're
 | 
			
		||||
// not inside the functions from objdump's point of view, an unwinder that
 | 
			
		||||
// blindly looks at the previous instruction (but is then smart enough to check
 | 
			
		||||
// the DWARF information to find out where it landed) gets the right answer.
 | 
			
		||||
 | 
			
		||||
// We need to place .fnstart ourselves (but we may as well keep the free .fnend).
 | 
			
		||||
#undef __bionic_asm_custom_entry
 | 
			
		||||
#define __bionic_asm_custom_entry(f)
 | 
			
		||||
 | 
			
		||||
  .fnstart
 | 
			
		||||
  .save {r0-r15}
 | 
			
		||||
  .pad #32
 | 
			
		||||
  nop
 | 
			
		||||
ENTRY_PRIVATE(__restore)
 | 
			
		||||
  // This function must have exactly this instruction sequence.
 | 
			
		||||
  mov r7, #__NR_sigreturn
 | 
			
		||||
  swi #0
 | 
			
		||||
END(__restore)
 | 
			
		||||
 | 
			
		||||
  .fnstart
 | 
			
		||||
  .save {r0-r15}
 | 
			
		||||
  .pad #160
 | 
			
		||||
  nop
 | 
			
		||||
ENTRY_PRIVATE(__restore_rt)
 | 
			
		||||
  // This function must have exactly this instruction sequence.
 | 
			
		||||
  mov r7, #__NR_rt_sigreturn
 | 
			
		||||
  swi #0
 | 
			
		||||
END(__restore_rt)
 | 
			
		||||
@@ -26,16 +26,19 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
 | 
			
		||||
// void _exit_with_stack_teardown(void* stackBase, size_t stackSize)
 | 
			
		||||
ENTRY_PRIVATE(_exit_with_stack_teardown)
 | 
			
		||||
  ldr r7, =__NR_munmap
 | 
			
		||||
  swi #0
 | 
			
		||||
  // If munmap failed, we ignore the failure and exit anyway.
 | 
			
		||||
// void _exit_with_stack_teardown(void* stackBase, int stackSize, int retCode)
 | 
			
		||||
ENTRY(_exit_with_stack_teardown)
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
    ldr     r7, =__NR_munmap
 | 
			
		||||
    swi     #0              // the stack is destroyed by this call
 | 
			
		||||
    mov     r0, lr
 | 
			
		||||
    ldr     r7, =__NR_exit
 | 
			
		||||
    swi     #0
 | 
			
		||||
 | 
			
		||||
  mov r0, #0
 | 
			
		||||
  ldr r7, =__NR_exit
 | 
			
		||||
  swi #0
 | 
			
		||||
  // The exit syscall does not return.
 | 
			
		||||
    // exit() should never return, cause a crash if it does
 | 
			
		||||
    mov     r0, #0
 | 
			
		||||
    ldr     r0, [r0]
 | 
			
		||||
END(_exit_with_stack_teardown)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								libc/arch-arm/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								libc/arch-arm/bionic/_setjmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
/*	$OpenBSD: _setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
 * Copyright (c) 2010 Android Open Source Project.
 | 
			
		||||
 * 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>
 | 
			
		||||
#include <machine/cpu-features.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 are scratch registers in functions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
	ldr	r1, .L_setjmp_magic
 | 
			
		||||
	str	r1, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
	/* Store core registers */
 | 
			
		||||
	add     r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	stmia   r1, {r4-r14}
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Store floating-point registers */
 | 
			
		||||
	add     r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vstmia  r1, {d8-d15}
 | 
			
		||||
	/* Store floating-point state */
 | 
			
		||||
	fmrx    r1, fpscr
 | 
			
		||||
	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#endif  /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
        mov	r0, #0x00000000
 | 
			
		||||
        bx      lr
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
	.word	_JB_MAGIC__SETJMP
 | 
			
		||||
 | 
			
		||||
ENTRY(_longjmp)
 | 
			
		||||
	ldr	r2, .L_setjmp_magic
 | 
			
		||||
	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	bne	botch
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Restore floating-point registers */
 | 
			
		||||
	add     r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vldmia  r2, {d8-d15}
 | 
			
		||||
	/* Restore floating-point state */
 | 
			
		||||
	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
	fmxr    fpscr, r2
 | 
			
		||||
#endif /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
	/* Restore core registers */
 | 
			
		||||
	add     r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	ldmia   r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
	/* Validate sp and r14 */
 | 
			
		||||
	teq	sp, #0
 | 
			
		||||
	teqne	r14, #0
 | 
			
		||||
	beq	botch
 | 
			
		||||
 | 
			
		||||
	/* Set return value */
 | 
			
		||||
	mov	r0, r1
 | 
			
		||||
	teq	r0, #0x00000000
 | 
			
		||||
	moveq	r0, #0x00000001
 | 
			
		||||
	bx      lr
 | 
			
		||||
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(abort), PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(_longjmp)
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Coding the abort function in assembly so that registers are guaranteed to
 | 
			
		||||
@@ -36,9 +36,7 @@
 | 
			
		||||
 * sequence when the crash happens.
 | 
			
		||||
 */
 | 
			
		||||
ENTRY(abort)
 | 
			
		||||
    .save   {r3, r14}
 | 
			
		||||
    stmfd   sp!, {r3, r14}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r3, 0
 | 
			
		||||
    .cfi_rel_offset r14, 4
 | 
			
		||||
    bl      __libc_android_abort
 | 
			
		||||
    blx     PIC_SYM(_C_LABEL(__libc_android_abort), PLT)
 | 
			
		||||
END(abort)
 | 
			
		||||
 
 | 
			
		||||
@@ -26,20 +26,10 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
extern void* __dso_handle;
 | 
			
		||||
 | 
			
		||||
extern int __cxa_atexit(void (*)(void*), void*, void*);
 | 
			
		||||
extern void *__dso_handle;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((visibility ("hidden")))
 | 
			
		||||
void __atexit_handler_wrapper(void* func) {
 | 
			
		||||
  if (func != NULL) {
 | 
			
		||||
    (*(void (*)(void))func)();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((visibility ("hidden")))
 | 
			
		||||
int atexit(void (*func)(void)) {
 | 
			
		||||
  return (__cxa_atexit(&__atexit_handler_wrapper, func, &__dso_handle));
 | 
			
		||||
int atexit(void (*func)(void))
 | 
			
		||||
{
 | 
			
		||||
  return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2012 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -27,10 +27,9 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <private/libc_logging.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This source file should only be included by libc.so, its purpose is
 | 
			
		||||
 * to support legacy ARM binaries by exporting a publicly visible
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008-2010 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <linux/err.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
 | 
			
		||||
// int  __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
 | 
			
		||||
ENTRY(__pthread_clone)
 | 
			
		||||
    # Copy the args onto the new stack.
 | 
			
		||||
    stmdb   r1!, {r0, r3}
 | 
			
		||||
 | 
			
		||||
    # The sys_clone system call only takes two arguments: 'flags' and 'child_stack'.
 | 
			
		||||
    # 'child_stack' is already in r1, but we need to move 'flags' into position.
 | 
			
		||||
    mov     r0, r2
 | 
			
		||||
    stmfd   sp!, {r4, r7}
 | 
			
		||||
 | 
			
		||||
    # System call.
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    beq     1f
 | 
			
		||||
 | 
			
		||||
    # In parent, reload saved registers then either return or set errno.
 | 
			
		||||
    ldmfd   sp!, {r4, r7}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
 | 
			
		||||
1:  # The child.
 | 
			
		||||
    # pick the function arg and call address off the stack and jump
 | 
			
		||||
    # to the C __thread_entry function which does some setup and then
 | 
			
		||||
    # calls the thread's start function
 | 
			
		||||
    pop     {r0, r1}
 | 
			
		||||
    # __thread_entry needs the TLS pointer
 | 
			
		||||
    mov     r2, sp
 | 
			
		||||
    b       __thread_entry
 | 
			
		||||
END(__pthread_clone)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # This function is defined as:
 | 
			
		||||
    #
 | 
			
		||||
    #   pid_t  __bionic_clone( int  flags, void *child_stack,
 | 
			
		||||
    #                          pid_t *pid, void *tls, pid_t *ctid,
 | 
			
		||||
    #                          int  (*fn)(void *), void* arg );
 | 
			
		||||
    #
 | 
			
		||||
    # NOTE: This is not the same signature as the glibc
 | 
			
		||||
    #       __clone function. Placing 'fn' and 'arg'
 | 
			
		||||
    #       at the end of the parameter list makes the
 | 
			
		||||
    #       implementation much simpler.
 | 
			
		||||
    #
 | 
			
		||||
 | 
			
		||||
ENTRY(__bionic_clone)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    .save   {r4, r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
    # save registers to parent stack
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
    # load extra parameters
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
 | 
			
		||||
    # store 'fn' and 'arg' to the child stack
 | 
			
		||||
    str     r5, [r1, #-4]
 | 
			
		||||
    str     r6, [r1, #-8]
 | 
			
		||||
 | 
			
		||||
    # System call
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    beq     1f
 | 
			
		||||
 | 
			
		||||
    # In the parent, reload saved registers then either return or set errno.
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
 | 
			
		||||
1:  # The child.
 | 
			
		||||
    ldr    r0, [sp, #-4]
 | 
			
		||||
    ldr    r1, [sp, #-8]
 | 
			
		||||
    b      __bionic_clone_entry
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
							
								
								
									
										53
									
								
								libc/arch-arm/bionic/crtbegin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								libc/arch-arm/bionic/crtbegin.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 "../../bionic/libc_init_common.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".preinit_array")))
 | 
			
		||||
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".init_array")))
 | 
			
		||||
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".fini_array")))
 | 
			
		||||
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__LIBC_HIDDEN__ void _start() {
 | 
			
		||||
  structors_array_t array;
 | 
			
		||||
  array.preinit_array = &__PREINIT_ARRAY__;
 | 
			
		||||
  array.init_array = &__INIT_ARRAY__;
 | 
			
		||||
  array.fini_array = &__FINI_ARRAY__;
 | 
			
		||||
 | 
			
		||||
  void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*));
 | 
			
		||||
  __libc_init(raw_args, NULL, &main, &array);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "__dso_handle.h"
 | 
			
		||||
#include "atexit.h"
 | 
			
		||||
							
								
								
									
										58
									
								
								libc/arch-arm/bionic/crtbegin_so.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libc/arch-arm/bionic/crtbegin_so.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern void __cxa_finalize(void *);
 | 
			
		||||
extern void *__dso_handle;
 | 
			
		||||
 | 
			
		||||
__attribute__((visibility("hidden"),destructor))
 | 
			
		||||
void __on_dlclose() {
 | 
			
		||||
  __cxa_finalize(&__dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* CRT_LEGACY_WORKAROUND should only be defined when building
 | 
			
		||||
 * this file as part of the platform's C library.
 | 
			
		||||
 *
 | 
			
		||||
 * The C library already defines a function named 'atexit()'
 | 
			
		||||
 * for backwards compatibility with older NDK-generated binaries.
 | 
			
		||||
 *
 | 
			
		||||
 * For newer ones, 'atexit' is actually embedded in the C
 | 
			
		||||
 * runtime objects that are linked into the final ELF
 | 
			
		||||
 * binary (shared library or executable), and will call
 | 
			
		||||
 * __cxa_atexit() in order to un-register any atexit()
 | 
			
		||||
 * handler when a library is unloaded.
 | 
			
		||||
 *
 | 
			
		||||
 * This function must be global *and* hidden. Only the
 | 
			
		||||
 * code inside the same ELF binary should be able to access it.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef CRT_LEGACY_WORKAROUND
 | 
			
		||||
#include "__dso_handle.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "__dso_handle_so.h"
 | 
			
		||||
#include "atexit.h"
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										40
									
								
								libc/arch-arm/bionic/crtend.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libc/arch-arm/bionic/crtend.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
	
 | 
			
		||||
	.section .preinit_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) && defined(__ELF__)
 | 
			
		||||
	.section .note.GNU-stack,"",%progbits
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										31
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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(__linux__) && defined(__ELF__)
 | 
			
		||||
	.section .note.GNU-stack,"",%progbits
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										103
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
extern int  __cxa_atexit(void (*)(void*), void*, void* );
 | 
			
		||||
 | 
			
		||||
/* The "C++ ABI for ARM" document states that static C++ constructors,
 | 
			
		||||
 * which are called from the .init_array, should manually call
 | 
			
		||||
 * __aeabi_atexit() to register static destructors explicitely.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that 'dso_handle' is the address of a magic linker-generate
 | 
			
		||||
 * variable from the shared object that contains the constructor/destructor
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Make this a weak symbol to avoid a multiple definition error when linking
 | 
			
		||||
 * with libstdc++-v3.  */
 | 
			
		||||
int __attribute__((weak))
 | 
			
		||||
__aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle)
 | 
			
		||||
{
 | 
			
		||||
    return __cxa_atexit(destructor, object, dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * __aeabi_memset has the order of its second and third arguments reversed. 
 | 
			
		||||
 *  This allows __aeabi_memclr to tail-call __aeabi_memset
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
void __aeabi_memset8(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memset4(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memset(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr8(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset8(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr4(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset4(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								libc/arch-arm/bionic/ffs.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								libc/arch-arm/bionic/ffs.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
/*	$NetBSD: ffs.S,v 1.5 2003/04/05 23:08:52 bjh21 Exp $	*/
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2001 Christopher Gilbert
 | 
			
		||||
 * 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 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>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(ffs)
 | 
			
		||||
	/* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */
 | 
			
		||||
 	rsb     r1, r0, #0
 | 
			
		||||
 	ands    r0, r0, r1
 | 
			
		||||
	clzne	r0, r0
 | 
			
		||||
	rsbne	r0, r0, #32
 | 
			
		||||
	bx		lr
 | 
			
		||||
END(ffs)
 | 
			
		||||
							
								
								
									
										73
									
								
								libc/arch-arm/bionic/futex_arm.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								libc/arch-arm/bionic/futex_arm.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <asm/unistd.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#define FUTEX_WAIT 0
 | 
			
		||||
#define FUTEX_WAKE 1
 | 
			
		||||
 | 
			
		||||
// __futex_syscall3(*ftx, op, val)
 | 
			
		||||
ENTRY(__futex_syscall3)
 | 
			
		||||
    stmdb   sp!, {r4, r7}
 | 
			
		||||
    .save   {r4, r7}
 | 
			
		||||
    ldr     r7, =__NR_futex
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmia   sp!, {r4, r7}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_syscall3)
 | 
			
		||||
 | 
			
		||||
// __futex_syscall4(*ftx, op, val, *timespec)
 | 
			
		||||
ENTRY(__futex_syscall4)
 | 
			
		||||
    b __futex_syscall3
 | 
			
		||||
END(__futex_syscall4)
 | 
			
		||||
 | 
			
		||||
// __futex_wait(*ftx, val, *timespec)
 | 
			
		||||
ENTRY(__futex_wait)
 | 
			
		||||
    stmdb   sp!, {r4, r7}
 | 
			
		||||
    .save   {r4, r7}
 | 
			
		||||
    mov     r3, r2
 | 
			
		||||
    mov     r2, r1
 | 
			
		||||
    mov     r1, #FUTEX_WAIT
 | 
			
		||||
    ldr     r7, =__NR_futex
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmia   sp!, {r4, r7}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_wait)
 | 
			
		||||
 | 
			
		||||
// __futex_wake(*ftx, counter)
 | 
			
		||||
ENTRY(__futex_wake)
 | 
			
		||||
    .save   {r4, r7}
 | 
			
		||||
    stmdb   sp!, {r4, r7}
 | 
			
		||||
    mov     r2, r1
 | 
			
		||||
    mov     r1, #FUTEX_WAKE
 | 
			
		||||
    ldr     r7, =__NR_futex
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmia   sp!, {r4, r7}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_wake)
 | 
			
		||||
							
								
								
									
										50
									
								
								libc/arch-arm/bionic/kill.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libc/arch-arm/bionic/kill.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <linux/err.h>
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/* unlike our auto-generated syscall stubs, this code saves lr
 | 
			
		||||
   on the stack, as well as a few other registers. this makes
 | 
			
		||||
   our stack unwinder happy, when we generate debug stack
 | 
			
		||||
   traces after the C library or other parts of the system
 | 
			
		||||
   abort due to a fatal runtime error (e.g. detection
 | 
			
		||||
   of a corrupted malloc heap).
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
ENTRY(kill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_kill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
END(kill)
 | 
			
		||||
@@ -1,159 +1,161 @@
 | 
			
		||||
/* Generated by genlibgcc_compat.py */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern char __adddf3;
 | 
			
		||||
extern char __addsf3;
 | 
			
		||||
extern char __aeabi_cdcmpeq;
 | 
			
		||||
extern char __aeabi_cdcmple;
 | 
			
		||||
extern char __aeabi_cdrcmple;
 | 
			
		||||
extern char __aeabi_d2f;
 | 
			
		||||
extern char __aeabi_d2iz;
 | 
			
		||||
extern char __aeabi_dadd;
 | 
			
		||||
extern char __aeabi_dcmpeq;
 | 
			
		||||
extern char __aeabi_dcmpge;
 | 
			
		||||
extern char __aeabi_dcmpgt;
 | 
			
		||||
extern char __aeabi_dcmple;
 | 
			
		||||
extern char __aeabi_dcmplt;
 | 
			
		||||
extern char __aeabi_dcmpun;
 | 
			
		||||
extern char __aeabi_ddiv;
 | 
			
		||||
extern char __aeabi_dmul;
 | 
			
		||||
extern char __aeabi_drsub;
 | 
			
		||||
extern char __aeabi_dsub;
 | 
			
		||||
extern char __aeabi_f2d;
 | 
			
		||||
extern char __aeabi_f2iz;
 | 
			
		||||
extern char __aeabi_f2uiz;
 | 
			
		||||
extern char __aeabi_fadd;
 | 
			
		||||
extern char __aeabi_fcmpun;
 | 
			
		||||
extern char __aeabi_fdiv;
 | 
			
		||||
extern char __aeabi_fmul;
 | 
			
		||||
extern char __aeabi_frsub;
 | 
			
		||||
extern char __aeabi_fsub;
 | 
			
		||||
extern char __aeabi_i2d;
 | 
			
		||||
extern char __aeabi_i2f;
 | 
			
		||||
extern char __aeabi_idiv;
 | 
			
		||||
extern char __aeabi_idivmod;
 | 
			
		||||
extern char __aeabi_l2d;
 | 
			
		||||
extern char __aeabi_l2f;
 | 
			
		||||
extern char __aeabi_lasr;
 | 
			
		||||
extern char __aeabi_ldivmod;
 | 
			
		||||
extern char __aeabi_llsl;
 | 
			
		||||
extern char __aeabi_llsr;
 | 
			
		||||
extern char __aeabi_lmul;
 | 
			
		||||
extern char __aeabi_ui2d;
 | 
			
		||||
extern char __aeabi_ui2f;
 | 
			
		||||
extern char __aeabi_uidiv;
 | 
			
		||||
extern char __aeabi_uidivmod;
 | 
			
		||||
extern char __aeabi_ul2d;
 | 
			
		||||
extern char __aeabi_ul2f;
 | 
			
		||||
extern char __aeabi_uldivmod;
 | 
			
		||||
extern char __aeabi_unwind_cpp_pr0;
 | 
			
		||||
extern char __aeabi_unwind_cpp_pr1;
 | 
			
		||||
extern char __cmpdf2;
 | 
			
		||||
extern char __divdf3;
 | 
			
		||||
extern char __divsf3;
 | 
			
		||||
extern char __eqdf2;
 | 
			
		||||
extern char __extendsfdf2;
 | 
			
		||||
extern char __fixdfsi;
 | 
			
		||||
extern char __fixsfsi;
 | 
			
		||||
extern char __floatdidf;
 | 
			
		||||
extern char __floatdisf;
 | 
			
		||||
extern char __floatsidf;
 | 
			
		||||
extern char __floatsisf;
 | 
			
		||||
extern char __floatundidf;
 | 
			
		||||
extern char __floatundisf;
 | 
			
		||||
extern char __floatunsidf;
 | 
			
		||||
extern char __floatunsisf;
 | 
			
		||||
extern char __gedf2;
 | 
			
		||||
extern char __gtdf2;
 | 
			
		||||
extern char __ledf2;
 | 
			
		||||
extern char __ltdf2;
 | 
			
		||||
extern char __muldf3;
 | 
			
		||||
extern char __muldi3;
 | 
			
		||||
extern char __mulsf3;
 | 
			
		||||
extern char __nedf2;
 | 
			
		||||
extern char __popcount_tab;
 | 
			
		||||
extern char __popcountsi2;
 | 
			
		||||
extern char __subdf3;
 | 
			
		||||
extern char __subsf3;
 | 
			
		||||
extern char __truncdfsf2;
 | 
			
		||||
extern char __unorddf2;
 | 
			
		||||
extern char __unordsf2;
 | 
			
		||||
/* This file contains dummy references to libgcc.a functions to force the
 | 
			
		||||
 * dynamic linker to copy their definition into the final libc.so binary.
 | 
			
		||||
 *
 | 
			
		||||
 * They are required to ensure backwards binary compatibility with
 | 
			
		||||
 * Android 1.5, 1.6 and even 3.0  system images. Some applications built
 | 
			
		||||
 * using the NDK require them to be here.
 | 
			
		||||
 *
 | 
			
		||||
 * Now, for a more elaborate description of the issue:
 | 
			
		||||
 *
 | 
			
		||||
 * libgcc.a is a compiler-specific library containing various helper
 | 
			
		||||
 * functions used to implement certain operations that are not necessarily
 | 
			
		||||
 * supported by the target CPU. For example, integer division doesn't have a
 | 
			
		||||
 * corresponding CPU instruction on ARMv5, and is instead implemented in the
 | 
			
		||||
 * compiler-generated machine code as a call to an __idiv helper function.
 | 
			
		||||
 *
 | 
			
		||||
 * Normally, one has to place libgcc.a in the link command used to generate
 | 
			
		||||
 * target binaries (shared libraries and executables) after all objects and
 | 
			
		||||
 * static libraries, but before dependent shared libraries, i.e. something
 | 
			
		||||
 * like:
 | 
			
		||||
 *         gcc <options> -o libfoo.so  foo.a libgcc.a -lc -lm
 | 
			
		||||
 *
 | 
			
		||||
 * This ensures that any helper function needed by the code in foo.a is copied
 | 
			
		||||
 * into the final libfoo.so. Unfortunately, the Android build system has been
 | 
			
		||||
 * using this instead:
 | 
			
		||||
 *
 | 
			
		||||
 *         gcc <options> -o libfoo.so foo.a -lc -lm libgcc.a
 | 
			
		||||
 *
 | 
			
		||||
 * The problem with this is that if one helper function needed by foo.a has
 | 
			
		||||
 * already been copied into libc.so or libm.so, then nothing will be copied
 | 
			
		||||
 * into libfoo.so. Instead, a symbol import definition will be added to it
 | 
			
		||||
 * so libfoo.so can directly call the one in libc.so at runtime.
 | 
			
		||||
 *
 | 
			
		||||
 * When changing toolchains for 2.0, the set of helper functions copied to
 | 
			
		||||
 * libc.so changed, which resulted in some native shared libraries generated
 | 
			
		||||
 * with the NDK to fail to load properly.
 | 
			
		||||
 *
 | 
			
		||||
 * The NDK has been fixed after 1.6_r1 to use the correct link command, so
 | 
			
		||||
 * any native shared library generated with it should now be safe from that
 | 
			
		||||
 * problem. On the other hand, existing shared libraries distributed with
 | 
			
		||||
 * applications that were generated with a previous version of the NDK
 | 
			
		||||
 * still need all 1.5/1.6 helper functions in libc.so and libm.so
 | 
			
		||||
 *
 | 
			
		||||
 * After 3.2, the toolchain was updated again, adding __aeabi_f2uiz to the
 | 
			
		||||
 * list of requirements. Technically, this is due to mis-linked NDK libraries
 | 
			
		||||
 * but it is easier to add a single function here than asking several app
 | 
			
		||||
 * developers to fix their build.
 | 
			
		||||
 *
 | 
			
		||||
 * Final note: some of the functions below should really be in libm.so to
 | 
			
		||||
 *             completely reflect the state of 1.5/1.6 system images. However,
 | 
			
		||||
 *             since libm.so depends on libc.so, it's easier to put all of
 | 
			
		||||
 *             these in libc.so instead, since the dynamic linker will always
 | 
			
		||||
 *             search in libc.so before libm.so for dependencies.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void* __bionic_libgcc_compat_symbols[] = {
 | 
			
		||||
    &__adddf3,
 | 
			
		||||
    &__addsf3,
 | 
			
		||||
    &__aeabi_cdcmpeq,
 | 
			
		||||
    &__aeabi_cdcmple,
 | 
			
		||||
    &__aeabi_cdrcmple,
 | 
			
		||||
    &__aeabi_d2f,
 | 
			
		||||
    &__aeabi_d2iz,
 | 
			
		||||
    &__aeabi_dadd,
 | 
			
		||||
    &__aeabi_dcmpeq,
 | 
			
		||||
    &__aeabi_dcmpge,
 | 
			
		||||
    &__aeabi_dcmpgt,
 | 
			
		||||
    &__aeabi_dcmple,
 | 
			
		||||
    &__aeabi_dcmplt,
 | 
			
		||||
    &__aeabi_dcmpun,
 | 
			
		||||
    &__aeabi_ddiv,
 | 
			
		||||
    &__aeabi_dmul,
 | 
			
		||||
    &__aeabi_drsub,
 | 
			
		||||
    &__aeabi_dsub,
 | 
			
		||||
    &__aeabi_f2d,
 | 
			
		||||
    &__aeabi_f2iz,
 | 
			
		||||
    &__aeabi_f2uiz,
 | 
			
		||||
    &__aeabi_fadd,
 | 
			
		||||
    &__aeabi_fcmpun,
 | 
			
		||||
    &__aeabi_fdiv,
 | 
			
		||||
    &__aeabi_fmul,
 | 
			
		||||
    &__aeabi_frsub,
 | 
			
		||||
    &__aeabi_fsub,
 | 
			
		||||
    &__aeabi_i2d,
 | 
			
		||||
    &__aeabi_i2f,
 | 
			
		||||
    &__aeabi_idiv,
 | 
			
		||||
    &__aeabi_idivmod,
 | 
			
		||||
    &__aeabi_l2d,
 | 
			
		||||
    &__aeabi_l2f,
 | 
			
		||||
    &__aeabi_lasr,
 | 
			
		||||
    &__aeabi_ldivmod,
 | 
			
		||||
    &__aeabi_llsl,
 | 
			
		||||
    &__aeabi_llsr,
 | 
			
		||||
    &__aeabi_lmul,
 | 
			
		||||
    &__aeabi_ui2d,
 | 
			
		||||
    &__aeabi_ui2f,
 | 
			
		||||
    &__aeabi_uidiv,
 | 
			
		||||
    &__aeabi_uidivmod,
 | 
			
		||||
    &__aeabi_ul2d,
 | 
			
		||||
    &__aeabi_ul2f,
 | 
			
		||||
    &__aeabi_uldivmod,
 | 
			
		||||
    &__aeabi_unwind_cpp_pr0,
 | 
			
		||||
    &__aeabi_unwind_cpp_pr1,
 | 
			
		||||
    &__cmpdf2,
 | 
			
		||||
    &__divdf3,
 | 
			
		||||
    &__divsf3,
 | 
			
		||||
    &__eqdf2,
 | 
			
		||||
    &__extendsfdf2,
 | 
			
		||||
    &__fixdfsi,
 | 
			
		||||
    &__fixsfsi,
 | 
			
		||||
    &__floatdidf,
 | 
			
		||||
    &__floatdisf,
 | 
			
		||||
    &__floatsidf,
 | 
			
		||||
    &__floatsisf,
 | 
			
		||||
    &__floatundidf,
 | 
			
		||||
    &__floatundisf,
 | 
			
		||||
    &__floatunsidf,
 | 
			
		||||
    &__floatunsisf,
 | 
			
		||||
    &__gedf2,
 | 
			
		||||
    &__gtdf2,
 | 
			
		||||
    &__ledf2,
 | 
			
		||||
    &__ltdf2,
 | 
			
		||||
    &__muldf3,
 | 
			
		||||
    &__muldi3,
 | 
			
		||||
    &__mulsf3,
 | 
			
		||||
    &__nedf2,
 | 
			
		||||
    &__popcount_tab,
 | 
			
		||||
    &__popcountsi2,
 | 
			
		||||
    &__subdf3,
 | 
			
		||||
    &__subsf3,
 | 
			
		||||
    &__truncdfsf2,
 | 
			
		||||
    &__unorddf2,
 | 
			
		||||
    &__unordsf2,
 | 
			
		||||
};
 | 
			
		||||
#define   COMPAT_FUNCTIONS_LIST \
 | 
			
		||||
    XX(__adddf3)             \
 | 
			
		||||
    XX(__addsf3)             \
 | 
			
		||||
    XX(__aeabi_cdcmpeq)      \
 | 
			
		||||
    XX(__aeabi_cdcmple)      \
 | 
			
		||||
    XX(__aeabi_cdrcmple)     \
 | 
			
		||||
    XX(__aeabi_d2f)          \
 | 
			
		||||
    XX(__aeabi_d2iz)         \
 | 
			
		||||
    XX(__aeabi_dadd)         \
 | 
			
		||||
    XX(__aeabi_dcmpeq)       \
 | 
			
		||||
    XX(__aeabi_dcmpge)       \
 | 
			
		||||
    XX(__aeabi_dcmpgt)       \
 | 
			
		||||
    XX(__aeabi_dcmple)       \
 | 
			
		||||
    XX(__aeabi_dcmplt)       \
 | 
			
		||||
    XX(__aeabi_dcmpun)       \
 | 
			
		||||
    XX(__aeabi_ddiv)         \
 | 
			
		||||
    XX(__aeabi_dmul)         \
 | 
			
		||||
    XX(__aeabi_drsub)        \
 | 
			
		||||
    XX(__aeabi_dsub)         \
 | 
			
		||||
    XX(__aeabi_f2d)          \
 | 
			
		||||
    XX(__aeabi_f2iz)         \
 | 
			
		||||
    XX(__aeabi_f2uiz)        \
 | 
			
		||||
    XX(__aeabi_fadd)         \
 | 
			
		||||
    XX(__aeabi_fcmpun)       \
 | 
			
		||||
    XX(__aeabi_fdiv)         \
 | 
			
		||||
    XX(__aeabi_fmul)         \
 | 
			
		||||
    XX(__aeabi_frsub)        \
 | 
			
		||||
    XX(__aeabi_fsub)         \
 | 
			
		||||
    XX(__aeabi_i2d)          \
 | 
			
		||||
    XX(__aeabi_i2f)          \
 | 
			
		||||
    XX(__aeabi_idiv)         \
 | 
			
		||||
    XX(__aeabi_l2d)          \
 | 
			
		||||
    XX(__aeabi_l2f)          \
 | 
			
		||||
    XX(__aeabi_lmul)         \
 | 
			
		||||
    XX(__aeabi_llsl)         \
 | 
			
		||||
    XX(__aeabi_llsr)         \
 | 
			
		||||
    XX(__aeabi_ui2d)         \
 | 
			
		||||
    XX(__aeabi_ui2f)         \
 | 
			
		||||
    XX(__aeabi_ul2d)         \
 | 
			
		||||
    XX(__aeabi_ul2f)         \
 | 
			
		||||
    XX(__cmpdf2)             \
 | 
			
		||||
    XX(__divdf3)             \
 | 
			
		||||
    XX(__divsf3)             \
 | 
			
		||||
    XX(__eqdf2)             \
 | 
			
		||||
    XX(__extendsfdf2)        \
 | 
			
		||||
    XX(__fixdfsi)            \
 | 
			
		||||
    XX(__fixsfsi)            \
 | 
			
		||||
    XX(__floatdidf)          \
 | 
			
		||||
    XX(__floatdisf)          \
 | 
			
		||||
    XX(__floatsidf)          \
 | 
			
		||||
    XX(__floatsisf)          \
 | 
			
		||||
    XX(__floatundidf)        \
 | 
			
		||||
    XX(__floatundisf)        \
 | 
			
		||||
    XX(__floatunsidf)        \
 | 
			
		||||
    XX(__floatunsisf)        \
 | 
			
		||||
    XX(__gedf2)              \
 | 
			
		||||
    XX(__gtdf2)              \
 | 
			
		||||
    XX(__ledf2)              \
 | 
			
		||||
    XX(__ltdf2)              \
 | 
			
		||||
    XX(__muldf3)             \
 | 
			
		||||
    XX(__muldi3)             \
 | 
			
		||||
    XX(__mulsf3)             \
 | 
			
		||||
    XX(__nedf2)              \
 | 
			
		||||
    XX(__subdf3)             \
 | 
			
		||||
    XX(__subsf3)             \
 | 
			
		||||
    XX(__truncdfsf2)         \
 | 
			
		||||
    XX(__unorddf2)           \
 | 
			
		||||
    XX(__unordsf2)           \
 | 
			
		||||
 | 
			
		||||
#define  XX(f)    extern void f(void);
 | 
			
		||||
COMPAT_FUNCTIONS_LIST
 | 
			
		||||
#undef XX
 | 
			
		||||
 | 
			
		||||
void  __bionic_libgcc_compat_hooks(void)
 | 
			
		||||
{
 | 
			
		||||
#define XX(f)    f();
 | 
			
		||||
COMPAT_FUNCTIONS_LIST
 | 
			
		||||
#undef XX
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										341
									
								
								libc/arch-arm/bionic/memcmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								libc/arch-arm/bionic/memcmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,341 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
#else
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(memcmp)
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
        /* take of the case where length is 0 or the buffers are the same */
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 8+4 bytes, this simplify things below
 | 
			
		||||
         * and avoid some overhead for small blocks
 | 
			
		||||
         */
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
/*
 | 
			
		||||
 * Neon optimization
 | 
			
		||||
 * Comparing 32 bytes at a time
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__ARM_NEON__) && defined(NEON_UNALIGNED_ACCESS)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop compares 32 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Start subtracting the values and merge results */
 | 
			
		||||
        vsub.i8     q0, q2
 | 
			
		||||
        vsub.i8     q1, q3
 | 
			
		||||
        vorr        q2, q0, q1
 | 
			
		||||
        vorr        d4, d5
 | 
			
		||||
        vmov        r3, ip, d4
 | 
			
		||||
        /* Check if there are any differences among the 32 bytes */
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        b           3f
 | 
			
		||||
2:
 | 
			
		||||
        /* Check if the difference was in the first or last 16 bytes */
 | 
			
		||||
        sub         r0, #32
 | 
			
		||||
        vorr        d0, d1
 | 
			
		||||
        sub         r1, #32
 | 
			
		||||
        vmov        r3, ip, d0
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        /* if the first 16 bytes are equal, we only have to rewind 16 bytes */
 | 
			
		||||
        ittt        eq
 | 
			
		||||
        subeq       r2, #16
 | 
			
		||||
        addeq       r0, #16
 | 
			
		||||
        addeq       r1, #16
 | 
			
		||||
 | 
			
		||||
3:      /* fix-up the remaining count */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        .save {r4, lr}
 | 
			
		||||
        /* save registers */
 | 
			
		||||
        stmfd       sp!, {r4, lr}
 | 
			
		||||
 | 
			
		||||
        /* since r0 hold the result, move the first source
 | 
			
		||||
         * pointer somewhere else
 | 
			
		||||
         */
 | 
			
		||||
         mov        r4, r0
 | 
			
		||||
 | 
			
		||||
        /* align first pointer to word boundary
 | 
			
		||||
         * offset = -src & 3
 | 
			
		||||
         */
 | 
			
		||||
        rsb         r3, r4, #0
 | 
			
		||||
        ands        r3, r3, #3
 | 
			
		||||
        beq         0f
 | 
			
		||||
 | 
			
		||||
        /* align first pointer  */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
1:      ldrb        r0, [r4], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r3, r3, #1
 | 
			
		||||
        bne         1b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
0:      /* here the first pointer is aligned, and we have at least 4 bytes
 | 
			
		||||
         * to process.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* see if the pointers are congruent */
 | 
			
		||||
        eor         r0, r4, r1
 | 
			
		||||
        ands        r0, r0, #3
 | 
			
		||||
        bne         5f
 | 
			
		||||
 | 
			
		||||
        /* congruent case, 32 bytes per iteration
 | 
			
		||||
         * We need to make sure there are at least 32+4 bytes left
 | 
			
		||||
         * because we effectively read ahead one word, and we could
 | 
			
		||||
         * read past the buffer (and segfault) if we're not careful.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        ldr         ip, [r1]
 | 
			
		||||
        subs        r2, r2, #(32 + 4)
 | 
			
		||||
        bmi         1f
 | 
			
		||||
 | 
			
		||||
0:      pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        ldr         lr, [r1, #4]!
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         0b
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 4 bytes left? */
 | 
			
		||||
1:      adds        r2, r2, #(32 - 4 + 4)
 | 
			
		||||
        bmi         4f
 | 
			
		||||
 | 
			
		||||
        /* finish off 4 bytes at a time */
 | 
			
		||||
3:      ldr         r0, [r4], #4
 | 
			
		||||
        ldr         ip, [r1], #4
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #4
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
4:      adds        r2, r2, #4
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9f
 | 
			
		||||
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8f
 | 
			
		||||
 | 
			
		||||
2:      /* the last 4 bytes are different, restart them */
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
 | 
			
		||||
        /* process the last few bytes */
 | 
			
		||||
8:      ldrb        r0, [r4], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        // stall
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         8b
 | 
			
		||||
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
10:     /* process less than 12 bytes */
 | 
			
		||||
        cmp         r2, #0
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
11:
 | 
			
		||||
        ldrb        r0, [r3], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        subs        r0, ip
 | 
			
		||||
        bxne        lr
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         11b
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
5:      /*************** non-congruent case ***************/
 | 
			
		||||
        and         r0, r1, #3
 | 
			
		||||
        cmp         r0, #2
 | 
			
		||||
        bne         4f
 | 
			
		||||
 | 
			
		||||
        /* here, offset is 2 (16-bits aligned, special cased) */
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 16 bytes to process */
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        addmi       r2, r2, #16
 | 
			
		||||
        bmi         8b
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
 | 
			
		||||
6:      pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        mov         ip, lr, lsr #16
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        orr         ip, ip, lr, lsl #16
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         6b
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #16
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #(4+2)
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
4:      /*************** offset is 1 or 3 (less optimized) ***************/
 | 
			
		||||
 | 
			
		||||
		stmfd		sp!, {r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
        // r5 = rhs
 | 
			
		||||
        // r6 = lhs
 | 
			
		||||
        // r7 = scratch
 | 
			
		||||
 | 
			
		||||
        mov         r5, r0, lsl #3		/* r5 = right shift */
 | 
			
		||||
        rsb         r6, r5, #32         /* r6 = left shift */
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         r7, [r1], #4
 | 
			
		||||
        sub         r2, r2, #8
 | 
			
		||||
 | 
			
		||||
6:      mov         ip, r7, lsr r5
 | 
			
		||||
        ldr         r7, [r1], #4
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        orr         ip, ip, r7, lsl r6
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, r7, lsr r5
 | 
			
		||||
        ldreq       r7, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, r7, lsl r6
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
 | 
			
		||||
        sub         r1, r1, r6, lsr #3
 | 
			
		||||
		ldmfd       sp!, {r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #8
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        sub         r1, r1, r6, lsr #3
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
		ldmfd		sp!, {r5, r6, r7}
 | 
			
		||||
        b           8b
 | 
			
		||||
END(memcmp)
 | 
			
		||||
							
								
								
									
										232
									
								
								libc/arch-arm/bionic/memcmp16.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								libc/arch-arm/bionic/memcmp16.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,232 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optimized memcmp16() for ARM9.
 | 
			
		||||
 * This would not be optimal on XScale or ARM11, where more prefetching
 | 
			
		||||
 * and use of PLD will be needed.
 | 
			
		||||
 * The 2 major optimzations here are
 | 
			
		||||
 * (1) The main loop compares 16 bytes at a time
 | 
			
		||||
 * (2) The loads are scheduled in a way they won't stall
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcmp16)
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
 | 
			
		||||
        /* take of the case where length is nul or the buffers are the same */
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        cmpne       r2, #0
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
 | 
			
		||||
        /* since r0 hold the result, move the first source
 | 
			
		||||
         * pointer somewhere else
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
 | 
			
		||||
         /* make sure we have at least 12 words, this simplify things below
 | 
			
		||||
          * and avoid some overhead for small blocks
 | 
			
		||||
          */
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #12
 | 
			
		||||
        bpl         0f
 | 
			
		||||
 | 
			
		||||
        /* small blocks (less then 12 words) */
 | 
			
		||||
        PLD         (r0, #32)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
1:      ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bxne        lr        
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         1b
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        .save {r4, lr}
 | 
			
		||||
        /* save registers */
 | 
			
		||||
0:      stmfd       sp!, {r4, lr}
 | 
			
		||||
        
 | 
			
		||||
        /* align first pointer to word boundary */
 | 
			
		||||
        tst         r3, #2
 | 
			
		||||
        beq         0f
 | 
			
		||||
        
 | 
			
		||||
        ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        sub         r2, r2, #1
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        ldmnefd     sp!, {r4, lr}
 | 
			
		||||
        bxne        lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
0:      /* here the first pointer is aligned, and we have at least 3 words
 | 
			
		||||
         * to process.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* see if the pointers are congruent */
 | 
			
		||||
        eor         r0, r3, r1
 | 
			
		||||
        ands        r0, r0, #2
 | 
			
		||||
        bne         5f
 | 
			
		||||
 | 
			
		||||
        /* congruent case, 16 half-words per iteration
 | 
			
		||||
         * We need to make sure there are at least 16+2 words left
 | 
			
		||||
         * because we effectively read ahead one long word, and we could
 | 
			
		||||
         * read past the buffer (and segfault) if we're not careful.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        ldr         ip, [r1]
 | 
			
		||||
        subs        r2, r2, #(16 + 2)
 | 
			
		||||
        bmi         1f
 | 
			
		||||
        
 | 
			
		||||
0:
 | 
			
		||||
        PLD         (r3, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        ldr         r0, [r3], #4
 | 
			
		||||
        ldr         lr, [r1, #4]!
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f        
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         0b
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 2 words left? */
 | 
			
		||||
1:      adds        r2, r2, #(16 - 2 + 2)
 | 
			
		||||
        bmi         4f
 | 
			
		||||
        
 | 
			
		||||
        /* finish off 2 words at a time */
 | 
			
		||||
3:      ldr         r0, [r3], #4
 | 
			
		||||
        ldr         ip, [r1], #4
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #2
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
4:      adds        r2, r2, #2
 | 
			
		||||
        bne         8f
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        mov         r0, #0
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
2:      /* the last 2 words are different, restart them */
 | 
			
		||||
        ldrh        r0, [r3, #-4]
 | 
			
		||||
        ldrh        ip, [r1, #-4]
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        ldreqh      r0, [r3, #-2]
 | 
			
		||||
        ldreqh      ip, [r1, #-2]
 | 
			
		||||
        subeqs      r0, r0, ip
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
        /* process the last few words */
 | 
			
		||||
8:      ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         8b
 | 
			
		||||
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
5:      /*************** non-congruent case ***************/
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        sub         r2, r2, #8
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
        PLD         (r3, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        mov         ip, lr, lsr #16
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        ldr         r0, [r3], #4
 | 
			
		||||
        orr         ip, ip, lr, lsl #16
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #8
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        b           2b
 | 
			
		||||
END(__memcmp16)
 | 
			
		||||
							
								
								
									
										686
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										686
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,686 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_NEON__) && !defined(ARCH_ARM_USE_NON_NEON_MEMCPY)
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
/* a prefetch distance of 2 cache-lines */
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
#else
 | 
			
		||||
/* a prefetch distance of 4 cache-lines works best experimentally */
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
/* If Neon supports unaligned access then remove the align code,
 | 
			
		||||
 * unless a size limit has been specified.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        /* do we have at least 16-bytes to copy (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to cache-line for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        /* make sure we have at least 32 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need.
 | 
			
		||||
         * NOTE: the number of pld below depends on PREFETCH_DISTANCE,
 | 
			
		||||
         * ideally would would increase the distance in the main loop to
 | 
			
		||||
         * avoid the goofy code below. In practice this doesn't seem to make
 | 
			
		||||
         * a big difference.
 | 
			
		||||
         */
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 32 bytes at a time */
 | 
			
		||||
        vld1.8      {d0  - d3},   [r1]!
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0  - d3},   [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
#else
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
#endif
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
#else   /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
 | 
			
		||||
        // Check so divider is at least 16 bytes, needed for alignment code.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
#ifdef NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
#if NEON_MEMCPY_ALIGNMENT_DIVIDER >= 16
 | 
			
		||||
        cmp         r2, #NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        blo         3f
 | 
			
		||||
#endif
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
3:
 | 
			
		||||
#endif
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
#endif  /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
11:
 | 
			
		||||
        /* Simple arm-only copy loop to handle aligned copy operations */
 | 
			
		||||
        stmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Check alignment */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, #3
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
         * stall 2 cycles.
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r5, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r5, [r0], #1
 | 
			
		||||
2:
 | 
			
		||||
        subs        r2, #32
 | 
			
		||||
        blt         5f
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
3:      /* Main copy loop, copying 32 bytes at a time */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 4)]
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        bge         3b
 | 
			
		||||
5:      /* Handle any remaining bytes */
 | 
			
		||||
        adds        r2, #32
 | 
			
		||||
        beq         6f
 | 
			
		||||
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r3, r4, r5, r6}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r7, r8}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r3, r4, r5, r6}
 | 
			
		||||
        stmmiia     r0!, {r7, r8}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
6:
 | 
			
		||||
        ldmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else   /* __ARM_ARCH__ < 7 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Optimized memcpy() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
		 * note that memcpy() always returns the destination pointer,
 | 
			
		||||
		 * so we have to preserve R0.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
		/* The stack must always be 64-bits aligned to be compliant with the
 | 
			
		||||
		 * ARM ABI. Since we have to save R0, we might as well save R4
 | 
			
		||||
		 * which we can use for better pipelining of the reads below
 | 
			
		||||
		 */
 | 
			
		||||
        .save       {r0, r4, lr}
 | 
			
		||||
        stmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        /* Making room for r5-r11 which will be spilled later */
 | 
			
		||||
        .pad        #28
 | 
			
		||||
        sub         sp, sp, #28
 | 
			
		||||
 | 
			
		||||
        // preload the destination because we'll align it to a cache line
 | 
			
		||||
        // with small writes. Also start the source "pump".
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
		/* it simplifies things to take care of len<4 early */
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
		/* compute the offset to align the source
 | 
			
		||||
		 * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
		 */
 | 
			
		||||
		rsb			r3, r1, #0
 | 
			
		||||
		ands		r3, r3, #3
 | 
			
		||||
		beq			src_aligned
 | 
			
		||||
 | 
			
		||||
		/* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
		 * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
		 * stall 2 cycles.
 | 
			
		||||
		 */
 | 
			
		||||
		movs		r12, r3, lsl #31
 | 
			
		||||
		sub			r2, r2, r3		/* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
		ldrmib		r3, [r1], #1
 | 
			
		||||
		ldrcsb		r4, [r1], #1
 | 
			
		||||
		ldrcsb		r12,[r1], #1
 | 
			
		||||
        strmib		r3, [r0], #1
 | 
			
		||||
		strcsb		r4, [r0], #1
 | 
			
		||||
		strcsb		r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
src_aligned:
 | 
			
		||||
 | 
			
		||||
		/* see if src and dst are aligned together (congruent) */
 | 
			
		||||
		eor			r12, r0, r1
 | 
			
		||||
		tst			r12, #3
 | 
			
		||||
		bne			non_congruent
 | 
			
		||||
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
         */
 | 
			
		||||
        stmea		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
		/* align the destination to a cache-line */
 | 
			
		||||
		rsb         r3, r0, #0
 | 
			
		||||
		ands		r3, r3, #0x1C
 | 
			
		||||
		beq         congruent_aligned32
 | 
			
		||||
		cmp         r3, r2
 | 
			
		||||
		andhi		r3, r2, #0x1C
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly copies 0 to 7 words (length in r3) */
 | 
			
		||||
		movs		r12, r3, lsl #28
 | 
			
		||||
		ldmcsia		r1!, {r4, r5, r6, r7}	/* 16 bytes */
 | 
			
		||||
		ldmmiia		r1!, {r8, r9}			/*  8 bytes */
 | 
			
		||||
		stmcsia		r0!, {r4, r5, r6, r7}
 | 
			
		||||
		stmmiia		r0!, {r8, r9}
 | 
			
		||||
		tst         r3, #0x4
 | 
			
		||||
		ldrne		r10,[r1], #4			/*  4 bytes */
 | 
			
		||||
		strne		r10,[r0], #4
 | 
			
		||||
		sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
congruent_aligned32:
 | 
			
		||||
		/*
 | 
			
		||||
		 * here source is aligned to 32 bytes.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
cached_aligned32:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         less_than_32_left
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * We preload a cache-line up to 64 bytes ahead. On the 926, this will
 | 
			
		||||
         * stall only until the requested world is fetched, but the linefill
 | 
			
		||||
         * continues in the the background.
 | 
			
		||||
         * While the linefill is going, we write our previous cache-line
 | 
			
		||||
         * into the write-buffer (which should have some free space).
 | 
			
		||||
         * When the linefill is done, the writebuffer will
 | 
			
		||||
         * start dumping its content into memory
 | 
			
		||||
         *
 | 
			
		||||
         * While all this is going, we then load a full cache line into
 | 
			
		||||
         * 8 registers, this cache line should be in the cache by now
 | 
			
		||||
         * (or partly in the cache).
 | 
			
		||||
         *
 | 
			
		||||
         * This code should work well regardless of the source/dest alignment.
 | 
			
		||||
         *
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        // Align the preload register to a cache-line because the cpu does
 | 
			
		||||
        // "critical word first" (the first word requested is loaded first).
 | 
			
		||||
        bic         r12, r1, #0x1F
 | 
			
		||||
        add         r12, r12, #64
 | 
			
		||||
 | 
			
		||||
1:      ldmia       r1!, { r4-r11 }
 | 
			
		||||
        PLD         (r12, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
 | 
			
		||||
        // for ARM9 preload will not be safely guarded by the preceding subs.
 | 
			
		||||
        // When it is safely guarded the only possibility to have SIGSEGV here
 | 
			
		||||
        // is because the caller overstates the length.
 | 
			
		||||
        ldrhi       r3, [r12], #32      /* cheap ARM9 preload */
 | 
			
		||||
        stmia       r0!, { r4-r11 }
 | 
			
		||||
		bhs         1b
 | 
			
		||||
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
less_than_32_left:
 | 
			
		||||
		/*
 | 
			
		||||
		 * less than 32 bytes left at this point (length in r2)
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		/* skip all this if there is nothing to do, which should
 | 
			
		||||
		 * be a common case (if not executed the code below takes
 | 
			
		||||
		 * about 16 cycles)
 | 
			
		||||
		 */
 | 
			
		||||
		tst			r2, #0x1F
 | 
			
		||||
		beq			1f
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
		movs		r12, r2, lsl #28
 | 
			
		||||
		ldmcsia		r1!, {r4, r5, r6, r7}	/* 16 bytes */
 | 
			
		||||
		ldmmiia		r1!, {r8, r9}			/*  8 bytes */
 | 
			
		||||
		stmcsia		r0!, {r4, r5, r6, r7}
 | 
			
		||||
		stmmiia		r0!, {r8, r9}
 | 
			
		||||
		movs		r12, r2, lsl #30
 | 
			
		||||
		ldrcs		r3, [r1], #4			/*  4 bytes */
 | 
			
		||||
		ldrmih		r4, [r1], #2			/*  2 bytes */
 | 
			
		||||
		strcs		r3, [r0], #4
 | 
			
		||||
		strmih		r4, [r0], #2
 | 
			
		||||
		tst         r2, #0x1
 | 
			
		||||
		ldrneb		r3, [r1]				/*  last byte  */
 | 
			
		||||
		strneb		r3, [r0]
 | 
			
		||||
 | 
			
		||||
		/* we're done! restore everything and return */
 | 
			
		||||
1:		ldmfd		sp!, {r5-r11}
 | 
			
		||||
		ldmfd		sp!, {r0, r4, lr}
 | 
			
		||||
		bx			lr
 | 
			
		||||
 | 
			
		||||
		/********************************************************************/
 | 
			
		||||
 | 
			
		||||
non_congruent:
 | 
			
		||||
		/*
 | 
			
		||||
		 * here source is aligned to 4 bytes
 | 
			
		||||
		 * but destination is not.
 | 
			
		||||
		 *
 | 
			
		||||
		 * in the code below r2 is the number of bytes read
 | 
			
		||||
		 * (the number of bytes written is always smaller, because we have
 | 
			
		||||
		 * partial words in the shift queue)
 | 
			
		||||
		 */
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
         */
 | 
			
		||||
        stmea		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
		/* compute shifts needed to align src to dest */
 | 
			
		||||
		rsb			r5, r0, #0
 | 
			
		||||
		and			r5, r5, #3			/* r5 = # bytes in partial words */
 | 
			
		||||
		mov			r12, r5, lsl #3		/* r12 = right */
 | 
			
		||||
		rsb			lr, r12, #32		/* lr = left  */
 | 
			
		||||
 | 
			
		||||
		/* read the first word */
 | 
			
		||||
		ldr			r3, [r1], #4
 | 
			
		||||
		sub			r2, r2, #4
 | 
			
		||||
 | 
			
		||||
		/* write a partial word (0 to 3 bytes), such that destination
 | 
			
		||||
		 * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
		 */
 | 
			
		||||
		movs		r5, r5, lsl #31
 | 
			
		||||
		strmib		r3, [r0], #1
 | 
			
		||||
		movmi		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
		/* Align destination to 32 bytes (cache line boundary) */
 | 
			
		||||
1:		tst			r0, #0x1c
 | 
			
		||||
		beq			2f
 | 
			
		||||
		ldr			r5, [r1], #4
 | 
			
		||||
		sub         r2, r2, #4
 | 
			
		||||
		orr			r4, r3, r5,		lsl lr
 | 
			
		||||
		mov			r3, r5,			lsr r12
 | 
			
		||||
		str			r4, [r0], #4
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
		/* copy 32 bytes at a time */
 | 
			
		||||
2:		subs		r2, r2, #32
 | 
			
		||||
		blo			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
		/* Use immediate mode for the shifts, because there is an extra cycle
 | 
			
		||||
		 * for register shifts, which could account for up to 50% of
 | 
			
		||||
		 * performance hit.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
        cmp			r12, #24
 | 
			
		||||
		beq			loop24
 | 
			
		||||
		cmp			r12, #8
 | 
			
		||||
		beq			loop8
 | 
			
		||||
 | 
			
		||||
loop16:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		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, r6,		lsl #16
 | 
			
		||||
		mov			r6, r6,			lsr #16
 | 
			
		||||
		orr			r6, r6, r7,		lsl #16
 | 
			
		||||
		mov			r7, r7,			lsr #16
 | 
			
		||||
		orr			r7, r7, r8,		lsl #16
 | 
			
		||||
		mov			r8, r8,			lsr #16
 | 
			
		||||
		orr			r8, r8, r9,		lsl #16
 | 
			
		||||
		mov			r9, r9,			lsr #16
 | 
			
		||||
		orr			r9, r9, r10,	lsl #16
 | 
			
		||||
		mov			r10, r10,		lsr #16
 | 
			
		||||
		orr			r10, r10, r11,	lsl #16
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #16
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		b			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
loop8:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		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, r6,		lsl #24
 | 
			
		||||
		mov			r6, r6,			lsr #8
 | 
			
		||||
		orr			r6, r6, r7,		lsl #24
 | 
			
		||||
		mov			r7, r7,			lsr #8
 | 
			
		||||
		orr			r7, r7, r8,		lsl #24
 | 
			
		||||
		mov			r8, r8,			lsr #8
 | 
			
		||||
		orr			r8, r8, r9,		lsl #24
 | 
			
		||||
		mov			r9, r9,			lsr #8
 | 
			
		||||
		orr			r9, r9, r10,	lsl #24
 | 
			
		||||
		mov			r10, r10,		lsr #8
 | 
			
		||||
		orr			r10, r10, r11,	lsl #24
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #8
 | 
			
		||||
		bhs			1b
 | 
			
		||||
		b			less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
loop24:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		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, r6,		lsl #8
 | 
			
		||||
		mov			r6, r6,			lsr #24
 | 
			
		||||
		orr			r6, r6, r7,		lsl #8
 | 
			
		||||
		mov			r7, r7,			lsr #24
 | 
			
		||||
		orr			r7, r7, r8,		lsl #8
 | 
			
		||||
		mov			r8, r8,			lsr #24
 | 
			
		||||
		orr			r8, r8, r9,		lsl #8
 | 
			
		||||
		mov			r9, r9,			lsr #24
 | 
			
		||||
		orr			r9, r9, r10,	lsl #8
 | 
			
		||||
		mov			r10, r10,		lsr #24
 | 
			
		||||
		orr			r10, r10, r11,	lsl #8
 | 
			
		||||
		stmia		r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
		mov			r3, r11,		lsr #24
 | 
			
		||||
		bhs			1b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
less_than_thirtytwo:
 | 
			
		||||
		/* copy the last 0 to 31 bytes of the source */
 | 
			
		||||
		rsb			r12, lr, #32		/* we corrupted r12, recompute it  */
 | 
			
		||||
		add			r2, r2, #32
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
		blo			partial_word_tail
 | 
			
		||||
 | 
			
		||||
1:		ldr			r5, [r1], #4
 | 
			
		||||
		sub         r2, r2, #4
 | 
			
		||||
		orr			r4, r3, r5,		lsl lr
 | 
			
		||||
		mov			r3,	r5,			lsr r12
 | 
			
		||||
		str			r4, [r0], #4
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
		bhs			1b
 | 
			
		||||
 | 
			
		||||
partial_word_tail:
 | 
			
		||||
		/* we have a partial word in the input buffer */
 | 
			
		||||
		movs		r5, lr, lsl #(31-3)
 | 
			
		||||
		strmib		r3, [r0], #1
 | 
			
		||||
		movmi		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		movcs		r3, r3, lsr #8
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
		/* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
		ldmfd		sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
copy_last_3_and_return:
 | 
			
		||||
		movs		r2, r2, lsl #31	/* copy remaining 0, 1, 2 or 3 bytes */
 | 
			
		||||
		ldrmib		r2, [r1], #1
 | 
			
		||||
		ldrcsb		r3, [r1], #1
 | 
			
		||||
		ldrcsb		r12,[r1]
 | 
			
		||||
		strmib		r2, [r0], #1
 | 
			
		||||
		strcsb		r3, [r0], #1
 | 
			
		||||
		strcsb		r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
		ldmfd		sp!, {r0, r4, lr}
 | 
			
		||||
		bx			lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif    /* __ARM_ARCH__ < 7 */
 | 
			
		||||
							
								
								
									
										406
									
								
								libc/arch-arm/bionic/memcpy.a15.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								libc/arch-arm/bionic/memcpy.a15.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,406 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    /* Prototype: void *memcpy (void *dst, const void *src, size_t count).  */
 | 
			
		||||
 | 
			
		||||
        /* Use the version of memcpy implemented using LDRD and STRD.
 | 
			
		||||
           This version is tuned for Cortex-A15.
 | 
			
		||||
           This might not be the best for other ARMv7-A CPUs,
 | 
			
		||||
           but there is no predefine to distinguish between
 | 
			
		||||
           different CPUs in the same architecture,
 | 
			
		||||
           and this version is better than the plain memcpy provided in newlib.
 | 
			
		||||
 | 
			
		||||
           Therefore, we use this version for all ARMv7-A CPUS.  */
 | 
			
		||||
 | 
			
		||||
        /* To make the same code compile for both ARM and Thumb instruction
 | 
			
		||||
       sets, switch to unified syntax at the beginning of this function.
 | 
			
		||||
           However, by using the same code, we may be missing optimization
 | 
			
		||||
       opportunities.  For instance, in LDRD/STRD instructions, the first
 | 
			
		||||
       destination register must be even and the second consecutive in
 | 
			
		||||
       ARM state, but not in Thumb state.  */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
        .syntax         unified
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
       /* Assumes that n >= 0, and dst, src are valid pointers.
 | 
			
		||||
          If there is at least 8 bytes to copy, use LDRD/STRD.
 | 
			
		||||
          If src and dst are misaligned with different offsets,
 | 
			
		||||
          first copy byte by byte until dst is aligned,
 | 
			
		||||
          and then copy using LDRD/STRD and shift if needed.
 | 
			
		||||
          When less than 8 left, copy a word and then byte by byte.  */
 | 
			
		||||
 | 
			
		||||
       /* Save registers (r0 holds the return value):
 | 
			
		||||
          optimized push {r0, r4, r5, r6, r7, lr}.
 | 
			
		||||
          To try and improve performance, stack layout changed,
 | 
			
		||||
          i.e., not keeping the stack looking like users expect
 | 
			
		||||
          (highest numbered register at highest address).  */
 | 
			
		||||
        .save   {r0, lr}
 | 
			
		||||
        push    {r0, lr}
 | 
			
		||||
        .save   {r4, r5}
 | 
			
		||||
        strd    r4, r5, [sp, #-8]!
 | 
			
		||||
        .save   {r6, r7}
 | 
			
		||||
        strd    r6, r7, [sp, #-8]!
 | 
			
		||||
 | 
			
		||||
       /* TODO: Add debug frame directives.
 | 
			
		||||
          We don't need exception unwind directives, because the code below
 | 
			
		||||
      does not throw any exceptions and does not call any other functions.
 | 
			
		||||
          Generally, newlib functions like this lack debug information for
 | 
			
		||||
      assembler source.  */
 | 
			
		||||
 | 
			
		||||
        /* Get copying of tiny blocks out of the way first.  */
 | 
			
		||||
        /* Is there at least 4 bytes to copy?  */
 | 
			
		||||
        subs    r2, r2, #4
 | 
			
		||||
        blt     copy_less_than_4                 /* If n < 4.  */
 | 
			
		||||
 | 
			
		||||
        /* Check word alignment.  */
 | 
			
		||||
        ands    ip, r0, #3                       /* ip = last 2 bits of dst.  */
 | 
			
		||||
        bne     dst_not_word_aligned             /* If dst is not word-aligned.  */
 | 
			
		||||
 | 
			
		||||
        /* Get here if dst is word-aligned.  */
 | 
			
		||||
        ands    ip, r1, #3                      /* ip = last 2 bits of src.  */
 | 
			
		||||
        bne     src_not_word_aligned            /* If src is not word-aligned.  */
 | 
			
		||||
word_aligned:
 | 
			
		||||
        /* Get here if source and dst both are word-aligned.
 | 
			
		||||
           The number of bytes remaining to copy is r2+4.  */
 | 
			
		||||
 | 
			
		||||
        /* Is there is at least 64 bytes to copy?  */
 | 
			
		||||
        subs    r2, r2, #60
 | 
			
		||||
        blt     copy_less_than_64                /* If r2 + 4 < 64.  */
 | 
			
		||||
 | 
			
		||||
        /* First, align the destination buffer to 8-bytes,
 | 
			
		||||
           to make sure double loads and stores don't cross cache line boundary,
 | 
			
		||||
           as they are then more expensive even if the data is in the cache
 | 
			
		||||
           (require two load/store issue cycles instead of one).
 | 
			
		||||
           If only one of the buffers is not 8-bytes aligned,
 | 
			
		||||
           then it's more important to align dst than src,
 | 
			
		||||
           because there is more penalty for stores
 | 
			
		||||
           than loads that cross cacheline boundary.
 | 
			
		||||
           This check and realignment are only worth doing
 | 
			
		||||
           if there is a lot to copy.  */
 | 
			
		||||
 | 
			
		||||
        /* Get here if dst is word aligned,
 | 
			
		||||
           i.e., the 2 least significant bits are 0.
 | 
			
		||||
           If dst is not 2w aligned (i.e., the 3rd bit is not set in dst),
 | 
			
		||||
           then copy 1 word (4 bytes).  */
 | 
			
		||||
        ands    r3, r0, #4
 | 
			
		||||
        beq     11f                  /* If dst already two-word aligned.  */
 | 
			
		||||
        ldr     r3, [r1], #4
 | 
			
		||||
        str     r3, [r0], #4
 | 
			
		||||
        subs    r2, r2, #4
 | 
			
		||||
        blt     copy_less_than_64
 | 
			
		||||
 | 
			
		||||
11:
 | 
			
		||||
        /* TODO: Align to cacheline (useful for PLD optimization).  */
 | 
			
		||||
 | 
			
		||||
        /* Every loop iteration copies 64 bytes.  */
 | 
			
		||||
1:
 | 
			
		||||
        .irp    offset, #0, #8, #16, #24, #32, #40, #48, #56
 | 
			
		||||
        ldrd    r4, r5, [r1, \offset]
 | 
			
		||||
        strd    r4, r5, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
 | 
			
		||||
        add     r0, r0, #64
 | 
			
		||||
        add     r1, r1, #64
 | 
			
		||||
        subs    r2, r2, #64
 | 
			
		||||
        bge     1b                            /* If there is more to copy.  */
 | 
			
		||||
 | 
			
		||||
copy_less_than_64:
 | 
			
		||||
 | 
			
		||||
        /* Get here if less than 64 bytes to copy, -64 <= r2 < 0.
 | 
			
		||||
           Restore the count if there is more than 7 bytes to copy.  */
 | 
			
		||||
        adds    r2, r2, #56
 | 
			
		||||
        blt     copy_less_than_8
 | 
			
		||||
 | 
			
		||||
        /* Copy 8 bytes at a time.  */
 | 
			
		||||
2:
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        strd    r4, r5, [r0], #8
 | 
			
		||||
        subs    r2, r2, #8
 | 
			
		||||
        bge     2b                            /* If there is more to copy.  */
 | 
			
		||||
 | 
			
		||||
copy_less_than_8:
 | 
			
		||||
 | 
			
		||||
        /* Get here if less than 8 bytes to copy, -8 <= r2 < 0.
 | 
			
		||||
           Check if there is more to copy.  */
 | 
			
		||||
        cmn     r2, #8
 | 
			
		||||
        beq     return                          /* If r2 + 8 == 0.  */
 | 
			
		||||
 | 
			
		||||
        /* Restore the count if there is more than 3 bytes to copy.  */
 | 
			
		||||
        adds    r2, r2, #4
 | 
			
		||||
        blt     copy_less_than_4
 | 
			
		||||
 | 
			
		||||
        /* Copy 4 bytes.  */
 | 
			
		||||
        ldr     r3, [r1], #4
 | 
			
		||||
        str     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
copy_less_than_4:
 | 
			
		||||
        /* Get here if less than 4 bytes to copy, -4 <= r2 < 0.  */
 | 
			
		||||
 | 
			
		||||
        /* Restore the count, check if there is more to copy.  */
 | 
			
		||||
        adds    r2, r2, #4
 | 
			
		||||
        beq     return                          /* If r2 == 0.  */
 | 
			
		||||
 | 
			
		||||
        /* Get here with r2 is in {1,2,3}={01,10,11}.  */
 | 
			
		||||
        /* Logical shift left r2, insert 0s, update flags.  */
 | 
			
		||||
        lsls    r2, r2, #31
 | 
			
		||||
 | 
			
		||||
        /* Copy byte by byte.
 | 
			
		||||
           Condition ne means the last bit of r2 is 0.
 | 
			
		||||
           Condition cs means the second to last bit of r2 is set,
 | 
			
		||||
           i.e., r2 is 1 or 3.  */
 | 
			
		||||
        itt     ne
 | 
			
		||||
        ldrbne  r3, [r1], #1
 | 
			
		||||
        strbne  r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        itttt   cs
 | 
			
		||||
        ldrbcs  r4, [r1], #1
 | 
			
		||||
        ldrbcs  r5, [r1]
 | 
			
		||||
        strbcs  r4, [r0], #1
 | 
			
		||||
        strbcs  r5, [r0]
 | 
			
		||||
 | 
			
		||||
return:
 | 
			
		||||
        /* Restore registers: optimized pop {r0, r4, r5, r6, r7, pc}   */
 | 
			
		||||
        /* This is the only return point of memcpy.  */
 | 
			
		||||
        ldrd r6, r7, [sp], #8
 | 
			
		||||
        ldrd r4, r5, [sp], #8
 | 
			
		||||
        pop {r0, pc}
 | 
			
		||||
 | 
			
		||||
#ifndef __ARM_FEATURE_UNALIGNED
 | 
			
		||||
 | 
			
		||||
       /* The following assembly macro implements misaligned copy in software.
 | 
			
		||||
          Assumes that dst is word aligned, src is at offset "pull" bits from
 | 
			
		||||
      word, push = 32 - pull, and the number of bytes that remain to copy
 | 
			
		||||
      is r2 + 4, r2 >= 0.  */
 | 
			
		||||
 | 
			
		||||
       /* In the code below, r2 is the number of bytes that remain to be
 | 
			
		||||
      written.  The number of bytes read is always larger, because we have
 | 
			
		||||
      partial words in the shift queue.  */
 | 
			
		||||
 | 
			
		||||
        .macro  miscopy pull push shiftleft shiftright
 | 
			
		||||
 | 
			
		||||
        /* Align src to the previous word boundary.  */
 | 
			
		||||
        bic     r1, r1, #3
 | 
			
		||||
 | 
			
		||||
        /* Initialize the shift queue.  */
 | 
			
		||||
        ldr     r5, [r1], #4                   /* Load a word from source.  */
 | 
			
		||||
 | 
			
		||||
        subs    r2, r2, #4
 | 
			
		||||
        blt     6f          /* Go to misaligned copy of less than 8 bytes.  */
 | 
			
		||||
 | 
			
		||||
       /* Get here if there is more than 8 bytes to copy.
 | 
			
		||||
          The number of bytes to copy is r2+8, r2 >= 0.  */
 | 
			
		||||
 | 
			
		||||
       subs     r2, r2, #56
 | 
			
		||||
       blt      4f         /* Go to misaligned copy of less than 64 bytes.  */
 | 
			
		||||
 | 
			
		||||
3:
 | 
			
		||||
       /* Get here if there is more than 64 bytes to copy.
 | 
			
		||||
          The number of bytes to copy is r2+64, r2 >= 0.  */
 | 
			
		||||
 | 
			
		||||
       /* Copy 64 bytes in every iteration.
 | 
			
		||||
          Use a partial word from the shift queue.  */
 | 
			
		||||
        .irp    offset, #0, #8, #16, #24, #32, #40, #48, #56
 | 
			
		||||
        mov     r6, r5, \shiftleft #\pull
 | 
			
		||||
        ldrd    r4, r5, [r1, \offset]
 | 
			
		||||
        orr     r6, r6, r4, \shiftright #\push
 | 
			
		||||
        mov     r7, r4, \shiftleft #\pull
 | 
			
		||||
        orr     r7, r7, r5, \shiftright #\push
 | 
			
		||||
        strd    r6, r7, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
 | 
			
		||||
        add     r1, r1, #64
 | 
			
		||||
        add     r0, r0, #64
 | 
			
		||||
        subs    r2, r2, #64
 | 
			
		||||
        bge     3b
 | 
			
		||||
 | 
			
		||||
4:
 | 
			
		||||
       /* Get here if there is less than 64 bytes to copy (-64 <= r2 < 0)
 | 
			
		||||
      and they are misaligned.  */
 | 
			
		||||
 | 
			
		||||
       /* Restore the count if there is more than 7 bytes to copy.  */
 | 
			
		||||
        adds    r2, r2, #56
 | 
			
		||||
 | 
			
		||||
        blt     6f          /* Go to misaligned copy of less than 8 bytes.  */
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
        /* Copy 8 bytes at a time.
 | 
			
		||||
           Use a partial word from the shift queue.  */
 | 
			
		||||
        mov     r6, r5, \shiftleft #\pull
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        orr     r6, r6, r4, \shiftright #\push
 | 
			
		||||
        mov     r7, r4, \shiftleft #\pull
 | 
			
		||||
        orr     r7, r7, r5, \shiftright #\push
 | 
			
		||||
        strd    r6, r7, [r0], #8
 | 
			
		||||
 | 
			
		||||
        subs    r2, r2, #8
 | 
			
		||||
        bge     5b                        /* If there is more to copy.  */
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
        /* Get here if there less than 8 bytes to copy (-8 <= r2 < 0)
 | 
			
		||||
           and they are misaligned.  */
 | 
			
		||||
 | 
			
		||||
        /* Check if there is more to copy.  */
 | 
			
		||||
        cmn     r2, #8
 | 
			
		||||
        beq     return
 | 
			
		||||
 | 
			
		||||
        /* Check if there is less than 4 bytes to copy.  */
 | 
			
		||||
        cmn     r2, #4
 | 
			
		||||
 | 
			
		||||
        itt     lt
 | 
			
		||||
        /* Restore src offset from word-align.  */
 | 
			
		||||
        sublt   r1, r1, #(\push / 8)
 | 
			
		||||
        blt     copy_less_than_4
 | 
			
		||||
 | 
			
		||||
        /* Use a partial word from the shift queue.  */
 | 
			
		||||
        mov     r3, r5, \shiftleft #\pull
 | 
			
		||||
        /* Load a word from src, but without writeback
 | 
			
		||||
           (this word is not fully written to dst).  */
 | 
			
		||||
        ldr     r5, [r1]
 | 
			
		||||
 | 
			
		||||
        /* Restore src offset from word-align.  */
 | 
			
		||||
        add     r1, r1, #(\pull / 8)
 | 
			
		||||
 | 
			
		||||
        /* Shift bytes to create one dst word and store it.  */
 | 
			
		||||
        orr     r3, r3, r5, \shiftright #\push
 | 
			
		||||
        str     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
        /* Use single byte copying of the remaining bytes.  */
 | 
			
		||||
        b       copy_less_than_4
 | 
			
		||||
 | 
			
		||||
        .endm
 | 
			
		||||
 | 
			
		||||
#endif /* not __ARM_FEATURE_UNALIGNED  */
 | 
			
		||||
 | 
			
		||||
dst_not_word_aligned:
 | 
			
		||||
 | 
			
		||||
       /* Get here when dst is not aligned and ip has the last 2 bits of dst,
 | 
			
		||||
          i.e., ip is the offset of dst from word.
 | 
			
		||||
          The number of bytes that remains to copy is r2 + 4,
 | 
			
		||||
          i.e., there are at least 4 bytes to copy.
 | 
			
		||||
          Write a partial word (0 to 3 bytes), such that dst becomes
 | 
			
		||||
      word-aligned.  */
 | 
			
		||||
 | 
			
		||||
       /* If dst is at ip bytes offset from a word (with 0 < ip < 4),
 | 
			
		||||
          then there are (4 - ip) bytes to fill up to align dst to the next
 | 
			
		||||
      word.  */
 | 
			
		||||
        rsb     ip, ip, #4                        /* ip = #4 - ip.  */
 | 
			
		||||
        cmp     ip, #2
 | 
			
		||||
 | 
			
		||||
       /* Copy byte by byte with conditionals.  */
 | 
			
		||||
        itt     gt
 | 
			
		||||
        ldrbgt  r3, [r1], #1
 | 
			
		||||
        strbgt  r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        itt     ge
 | 
			
		||||
        ldrbge  r4, [r1], #1
 | 
			
		||||
        strbge  r4, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldrb    lr, [r1], #1
 | 
			
		||||
        strb    lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
       /* Update the count.
 | 
			
		||||
          ip holds the number of bytes we have just copied.  */
 | 
			
		||||
        subs    r2, r2, ip                        /* r2 = r2 - ip.  */
 | 
			
		||||
        blt     copy_less_than_4                  /* If r2 < ip.  */
 | 
			
		||||
 | 
			
		||||
       /* Get here if there are more than 4 bytes to copy.
 | 
			
		||||
          Check if src is aligned.  If beforehand src and dst were not word
 | 
			
		||||
      aligned but congruent (same offset), then now they are both
 | 
			
		||||
      word-aligned, and we can copy the rest efficiently (without
 | 
			
		||||
      shifting).  */
 | 
			
		||||
        ands    ip, r1, #3                    /* ip = last 2 bits of src.  */
 | 
			
		||||
        beq     word_aligned                  /* If r1 is word-aligned.  */
 | 
			
		||||
 | 
			
		||||
src_not_word_aligned:
 | 
			
		||||
       /* Get here when src is not word-aligned, but dst is word-aligned.
 | 
			
		||||
          The number of bytes that remains to copy is r2+4.  */
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_FEATURE_UNALIGNED
 | 
			
		||||
       /* Copy word by word using LDR when alignment can be done in hardware,
 | 
			
		||||
          i.e., SCTLR.A is set, supporting unaligned access in LDR and STR.  */
 | 
			
		||||
        subs    r2, r2, #60
 | 
			
		||||
        blt     8f
 | 
			
		||||
 | 
			
		||||
7:
 | 
			
		||||
        /* Copy 64 bytes in every loop iteration.  */
 | 
			
		||||
        .irp    offset, #0, #4, #8, #12, #16, #20, #24, #28, #32, #36, #40, #44, #48, #52, #56, #60
 | 
			
		||||
        ldr     r3, [r1, \offset]
 | 
			
		||||
        str     r3, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
 | 
			
		||||
        add     r0, r0, #64
 | 
			
		||||
        add     r1, r1, #64
 | 
			
		||||
        subs    r2, r2, #64
 | 
			
		||||
        bge     7b
 | 
			
		||||
 | 
			
		||||
8:
 | 
			
		||||
        /* Get here if less than 64 bytes to copy, -64 <= r2 < 0.
 | 
			
		||||
           Check if there is more than 3 bytes to copy.  */
 | 
			
		||||
        adds    r2, r2, #60
 | 
			
		||||
        blt     copy_less_than_4
 | 
			
		||||
 | 
			
		||||
9:
 | 
			
		||||
       /* Get here if there is less than 64 but at least 4 bytes to copy,
 | 
			
		||||
          where the number of bytes to copy is r2+4.  */
 | 
			
		||||
        ldr     r3, [r1], #4
 | 
			
		||||
        str     r3, [r0], #4
 | 
			
		||||
        subs    r2, r2, #4
 | 
			
		||||
        bge     9b
 | 
			
		||||
 | 
			
		||||
        b       copy_less_than_4
 | 
			
		||||
 | 
			
		||||
#else /* not __ARM_FEATURE_UNALIGNED  */
 | 
			
		||||
 | 
			
		||||
       /* ip has last 2 bits of src,
 | 
			
		||||
          i.e., ip is the offset of src from word, and ip > 0.
 | 
			
		||||
          Compute shifts needed to copy from src to dst.  */
 | 
			
		||||
        cmp     ip, #2
 | 
			
		||||
        beq     miscopy_16_16             /* If ip == 2.  */
 | 
			
		||||
        bge     miscopy_24_8              /* If ip == 3.  */
 | 
			
		||||
 | 
			
		||||
        /* Get here if ip == 1.  */
 | 
			
		||||
 | 
			
		||||
        /* Endian independent macros for shifting bytes within registers.  */
 | 
			
		||||
 | 
			
		||||
#ifndef __ARMEB__
 | 
			
		||||
miscopy_8_24:   miscopy pull=8 push=24 shiftleft=lsr shiftright=lsl
 | 
			
		||||
miscopy_16_16:  miscopy pull=16 push=16 shiftleft=lsr shiftright=lsl
 | 
			
		||||
miscopy_24_8:   miscopy pull=24 push=8 shiftleft=lsr shiftright=lsl
 | 
			
		||||
#else  /* not __ARMEB__ */
 | 
			
		||||
miscopy_8_24:   miscopy pull=8 push=24 shiftleft=lsl shiftright=lsr
 | 
			
		||||
miscopy_16_16:  miscopy pull=16 push=16 shiftleft=lsl shiftright=lsr
 | 
			
		||||
miscopy_24_8:   miscopy pull=24 push=8 shiftleft=lsl shiftright=lsr
 | 
			
		||||
#endif  /* not __ARMEB__ */
 | 
			
		||||
 | 
			
		||||
#endif  /* not __ARM_FEATURE_UNALIGNED  */
 | 
			
		||||
 | 
			
		||||
END(memcpy)
 | 
			
		||||
							
								
								
									
										200
									
								
								libc/arch-arm/bionic/memset.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								libc/arch-arm/bionic/memset.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_NEON__)
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov     r2, r1
 | 
			
		||||
        mov     r1, #0
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
#if defined(__ARM_NEON__)
 | 
			
		||||
 | 
			
		||||
#ifdef  NEON_MEMSET_DIVIDER
 | 
			
		||||
        cmp         r2, #NEON_MEMSET_DIVIDER
 | 
			
		||||
        bhi         11f
 | 
			
		||||
#endif
 | 
			
		||||
        .save       {r0}
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        /* do we have at least 16-bytes to write (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* write up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
 | 
			
		||||
        // writes 4 bytes, 32-bits aligned
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
 | 
			
		||||
        // writes 8 bytes, 64-bits aligned
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
#endif
 | 
			
		||||
        /* make sure we have at least 32 bytes to write */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         2f
 | 
			
		||||
        vmov        q1, q0
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop writes 32 bytes at a time */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
#else
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
#endif
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        // writes 16 bytes, 128-bits aligned
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
#else
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
#endif
 | 
			
		||||
3:      /* write up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
11:
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
		/* compute the offset to align the destination
 | 
			
		||||
		 * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
        .save       {r0, r4-r7, lr}
 | 
			
		||||
		stmfd		sp!, {r0, r4-r7, lr}
 | 
			
		||||
		rsb			r3, r0, #0
 | 
			
		||||
		ands		r3, r3, #3
 | 
			
		||||
        cmp         r3, r2
 | 
			
		||||
        movhi       r3, r2
 | 
			
		||||
 | 
			
		||||
        /* splat r1 */
 | 
			
		||||
        mov         r1, r1, lsl #24
 | 
			
		||||
        orr         r1, r1, r1, lsr #8
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
		movs		r12, r3, lsl #31
 | 
			
		||||
		strcsb		r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
		strcsb		r1, [r0], #1
 | 
			
		||||
		strmib		r1, [r0], #1
 | 
			
		||||
		subs		r2, r2, r3
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
		/* align the destination to a cache-line */
 | 
			
		||||
        mov         r12, r1
 | 
			
		||||
        mov         lr, r1
 | 
			
		||||
        mov         r4, r1
 | 
			
		||||
        mov         r5, r1
 | 
			
		||||
        mov         r6, r1
 | 
			
		||||
        mov         r7, r1
 | 
			
		||||
 | 
			
		||||
		rsb         r3, r0, #0
 | 
			
		||||
		ands		r3, r3, #0x1C
 | 
			
		||||
		beq         3f
 | 
			
		||||
		cmp         r3, r2
 | 
			
		||||
		andhi		r3, r2, #0x1C
 | 
			
		||||
		sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
		/* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
		movs		r3, r3, lsl #28
 | 
			
		||||
		stmcsia		r0!, {r1, lr}
 | 
			
		||||
		stmcsia		r0!, {r1, lr}
 | 
			
		||||
		stmmiia		r0!, {r1, lr}
 | 
			
		||||
		movs		r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
3:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        mov         r3, r1
 | 
			
		||||
        bmi         2f
 | 
			
		||||
1:      subs        r2, r2, #32
 | 
			
		||||
        stmia		r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
 | 
			
		||||
        bhs         1b
 | 
			
		||||
2:      add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
		/* conditionally stores 0 to 31 bytes */
 | 
			
		||||
		movs		r2, r2, lsl #28
 | 
			
		||||
		stmcsia		r0!, {r1,r3,r12,lr}
 | 
			
		||||
		stmmiia		r0!, {r1, lr}
 | 
			
		||||
		movs		r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
		strmih		r1, [r0], #2
 | 
			
		||||
		movs		r2, r2, lsl #2
 | 
			
		||||
		strcsb		r1, [r0]
 | 
			
		||||
        ldmfd		sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
/*	$OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1997 Mark Brinicombe
 | 
			
		||||
 * Copyright (c) 2010 Android Open Source Project.
 | 
			
		||||
@@ -31,143 +34,109 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
// According to the ARM AAPCS document, we only need to save
 | 
			
		||||
// the following registers:
 | 
			
		||||
//
 | 
			
		||||
//  Core   r4-r14
 | 
			
		||||
//
 | 
			
		||||
//  VFP    d8-d15  (see section 5.1.2.1)
 | 
			
		||||
//
 | 
			
		||||
//      Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
 | 
			
		||||
//      calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
 | 
			
		||||
//      (and can be used for passing arguments or returning results in standard
 | 
			
		||||
//      procedure-call variants). Registers d16-d31 (q8-q15), if present, do
 | 
			
		||||
//      not need to be preserved.
 | 
			
		||||
//
 | 
			
		||||
//  FPSCR  saved because glibc does.
 | 
			
		||||
 | 
			
		||||
// The internal structure of a jmp_buf is totally private.
 | 
			
		||||
// Current layout (may change in the future):
 | 
			
		||||
//
 | 
			
		||||
// word   name         description
 | 
			
		||||
// 0      magic        magic number
 | 
			
		||||
// 1      sigmask      signal mask (not used with _setjmp / _longjmp)
 | 
			
		||||
// 2      float_base   base of float registers (d8 to d15)
 | 
			
		||||
// 18     float_state  floating-point status and control register
 | 
			
		||||
// 19     core_base    base of core registers (r4 to r14)
 | 
			
		||||
// 30     reserved     reserved entries (room to grow)
 | 
			
		||||
// 64
 | 
			
		||||
//
 | 
			
		||||
// NOTE: float_base must be at an even word index, since the
 | 
			
		||||
//       FP registers will be loaded/stored with instructions
 | 
			
		||||
//       that expect 8-byte alignment.
 | 
			
		||||
 | 
			
		||||
#define _JB_SIGFLAG     0
 | 
			
		||||
#define _JB_SIGMASK     (_JB_SIGFLAG+1)
 | 
			
		||||
#define _JB_FLOAT_BASE  (_JB_SIGMASK+1)
 | 
			
		||||
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
 | 
			
		||||
#define _JB_CORE_BASE   (_JB_FLOAT_STATE+1)
 | 
			
		||||
/*
 | 
			
		||||
 * 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)
 | 
			
		||||
  mov r1, #1
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
	/* Block all signals and retrieve the old signal mask */
 | 
			
		||||
	stmfd	sp!, {r0, r14}
 | 
			
		||||
	mov	r0, #0x00000000
 | 
			
		||||
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(sigblock), PLT)
 | 
			
		||||
	mov	r1, r0
 | 
			
		||||
 | 
			
		||||
	ldmfd	sp!, {r0, r14}
 | 
			
		||||
 | 
			
		||||
	/* Store signal mask */
 | 
			
		||||
	str	r1, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
 | 
			
		||||
	ldr	r1, .Lsetjmp_magic
 | 
			
		||||
	str	r1, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
 | 
			
		||||
	/* Store core registers */
 | 
			
		||||
	add     r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	stmia   r1, {r4-r14}
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Store floating-point registers */
 | 
			
		||||
	add     r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vstmia  r1, {d8-d15}
 | 
			
		||||
	/* Store floating-point state */
 | 
			
		||||
	fmrx    r1, fpscr
 | 
			
		||||
	str     r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#endif  /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
	mov	r0, #0x00000000
 | 
			
		||||
	bx      lr
 | 
			
		||||
END(setjmp)
 | 
			
		||||
 | 
			
		||||
ENTRY(_setjmp)
 | 
			
		||||
  mov r1, #0
 | 
			
		||||
  b sigsetjmp
 | 
			
		||||
END(_setjmp)
 | 
			
		||||
.Lsetjmp_magic:
 | 
			
		||||
	.word	_JB_MAGIC_SETJMP
 | 
			
		||||
 | 
			
		||||
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
  // Record whether or not we're saving the signal mask.
 | 
			
		||||
  str r1, [r0, #(_JB_SIGFLAG * 4)]
 | 
			
		||||
 | 
			
		||||
  // Do we need to save the signal mask?
 | 
			
		||||
  teq r1, #0
 | 
			
		||||
  beq 1f
 | 
			
		||||
ENTRY(longjmp)
 | 
			
		||||
	ldr	r2, .Lsetjmp_magic
 | 
			
		||||
	ldr	r3, [r0, #(_JB_MAGIC * 4)]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	bne	botch
 | 
			
		||||
 | 
			
		||||
  // Get current signal mask.
 | 
			
		||||
  stmfd sp!, {r0, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 8
 | 
			
		||||
  .cfi_rel_offset r0, 0
 | 
			
		||||
  .cfi_rel_offset r14, 4
 | 
			
		||||
  mov r0, #0
 | 
			
		||||
  bl sigblock
 | 
			
		||||
  mov r1, r0
 | 
			
		||||
  ldmfd sp!, {r0, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 0
 | 
			
		||||
	/* Fetch signal mask */
 | 
			
		||||
	ldr	r2, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
 | 
			
		||||
  // Save the signal mask.
 | 
			
		||||
  str r1, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
	/* Set signal mask */
 | 
			
		||||
	stmfd	sp!, {r0, r1, r14}
 | 
			
		||||
	sub	sp, sp, #4	/* align the stack */
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Save core registers.
 | 
			
		||||
  add r1, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
  stmia r1, {r4-r14}
 | 
			
		||||
	mov	r0, r2
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(sigsetmask), PLT)
 | 
			
		||||
 | 
			
		||||
  // Save floating-point registers.
 | 
			
		||||
  add r1, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
  vstmia  r1, {d8-d15}
 | 
			
		||||
	add	sp, sp, #4	/* unalign the stack */
 | 
			
		||||
	ldmfd	sp!, {r0, r1, r14} 
 | 
			
		||||
 | 
			
		||||
  // Save floating-point state.
 | 
			
		||||
  fmrx r1, fpscr
 | 
			
		||||
  str r1, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Restore floating-point registers */
 | 
			
		||||
	add     r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
	vldmia  r2, {d8-d15}
 | 
			
		||||
	/* Restore floating-point state */
 | 
			
		||||
	ldr     r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
	fmxr    fpscr, r2
 | 
			
		||||
#endif /* __ARM_HAVE_VFP */
 | 
			
		||||
 | 
			
		||||
  mov r0, #0
 | 
			
		||||
  bx lr
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
	/* Restore core registers */
 | 
			
		||||
	add     r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
	ldmia   r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
// void siglongjmp(sigjmp_buf env, int value);
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
  // Do we need to restore the signal mask?
 | 
			
		||||
  ldr r2, [r0, #(_JB_SIGFLAG * 4)]
 | 
			
		||||
  teq r2, #0
 | 
			
		||||
  beq 1f
 | 
			
		||||
	/* Validate sp and r14 */
 | 
			
		||||
	teq	sp, #0
 | 
			
		||||
	teqne	r14, #0
 | 
			
		||||
	beq	botch
 | 
			
		||||
 | 
			
		||||
  // Restore the signal mask.
 | 
			
		||||
  stmfd sp!, {r0, r1, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 12
 | 
			
		||||
  .cfi_rel_offset r0, 0
 | 
			
		||||
  .cfi_rel_offset r1, 4
 | 
			
		||||
  .cfi_rel_offset r14, 8
 | 
			
		||||
  sub sp, sp, #4 // Align the stack.
 | 
			
		||||
  .cfi_adjust_cfa_offset 4
 | 
			
		||||
	/* Set return value */
 | 
			
		||||
 | 
			
		||||
  ldr r0, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
  bl sigsetmask
 | 
			
		||||
	mov	r0, r1
 | 
			
		||||
	teq	r0, #0x00000000
 | 
			
		||||
	moveq	r0, #0x00000001
 | 
			
		||||
        bx      lr
 | 
			
		||||
#ifdef __ARM_26__
 | 
			
		||||
	mov	r15, r14
 | 
			
		||||
#else
 | 
			
		||||
	mov	r15, r14
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  add sp, sp, #4 // Unalign the stack.
 | 
			
		||||
  .cfi_adjust_cfa_offset -4
 | 
			
		||||
  ldmfd sp!, {r0, r1, r14}
 | 
			
		||||
  .cfi_def_cfa_offset 0
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
  // Restore floating-point registers.
 | 
			
		||||
  add r2, r0, #(_JB_FLOAT_BASE * 4)
 | 
			
		||||
  vldmia r2, {d8-d15}
 | 
			
		||||
 | 
			
		||||
  // Restore floating-point state.
 | 
			
		||||
  ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
 | 
			
		||||
  fmxr fpscr, r2
 | 
			
		||||
 | 
			
		||||
  // Restore core registers.
 | 
			
		||||
  add r2, r0, #(_JB_CORE_BASE * 4)
 | 
			
		||||
  ldmia r2, {r4-r14}
 | 
			
		||||
 | 
			
		||||
  // Validate sp and r14.
 | 
			
		||||
  teq sp, #0
 | 
			
		||||
  teqne r14, #0
 | 
			
		||||
  bleq longjmperror
 | 
			
		||||
 | 
			
		||||
  // Set return value.
 | 
			
		||||
  mov r0, r1
 | 
			
		||||
  teq r0, #0
 | 
			
		||||
  moveq r0, #1
 | 
			
		||||
  bx lr
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
 | 
			
		||||
ALIAS_SYMBOL(longjmp, siglongjmp)
 | 
			
		||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(abort), PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(longjmp)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								libc/arch-arm/bionic/sigsetjmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libc/arch-arm/bionic/sigsetjmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
/*	$OpenBSD: sigsetjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _ALIGN_TEXT .align 0
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
ENTRY(siglongjmp)
 | 
			
		||||
	ldr	r2, .L_setjmp_magic
 | 
			
		||||
	ldr	r3, [r0]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	beq	PIC_SYM(_C_LABEL(_longjmp), PLT)
 | 
			
		||||
	b	PIC_SYM(_C_LABEL(longjmp), PLT)
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
							
								
								
									
										317
									
								
								libc/arch-arm/bionic/strcmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								libc/arch-arm/bionic/strcmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,317 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2011 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2008 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/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
	.text
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define SHFT2LSB lsl
 | 
			
		||||
#define SHFT2LSBEQ lsleq
 | 
			
		||||
#define SHFT2MSB lsr
 | 
			
		||||
#define SHFT2MSBEQ lsreq
 | 
			
		||||
#define MSB 0x000000ff
 | 
			
		||||
#define LSB 0xff000000
 | 
			
		||||
#else
 | 
			
		||||
#define SHFT2LSB lsr
 | 
			
		||||
#define SHFT2LSBEQ lsreq
 | 
			
		||||
#define SHFT2MSB lsl
 | 
			
		||||
#define SHFT2MSBEQ lsleq
 | 
			
		||||
#define MSB 0xff000000
 | 
			
		||||
#define LSB 0x000000ff
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define magic1(REG) REG
 | 
			
		||||
#define magic2(REG) REG, lsl #7
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
	PLD(r0, #0)
 | 
			
		||||
	PLD(r1, #0)
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
 | 
			
		||||
	/* Strings not at same byte offset from a word boundary.  */
 | 
			
		||||
	bne	.Lstrcmp_unaligned
 | 
			
		||||
	ands	r2, r0, #3
 | 
			
		||||
	bic	r0, r0, #3
 | 
			
		||||
	bic	r1, r1, #3
 | 
			
		||||
	ldr	ip, [r0], #4
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	beq	1f
 | 
			
		||||
 | 
			
		||||
	/* Although s1 and s2 have identical initial alignment, they are
 | 
			
		||||
	 * not currently word aligned.  Rather than comparing bytes,
 | 
			
		||||
	 * make sure that any bytes fetched from before the addressed
 | 
			
		||||
	 * bytes are forced to 0xff.  Then they will always compare
 | 
			
		||||
	 * equal.
 | 
			
		||||
	 */
 | 
			
		||||
	eor	r2, r2, #3
 | 
			
		||||
	lsl	r2, r2, #3
 | 
			
		||||
	mvn	r3, #MSB
 | 
			
		||||
	SHFT2LSB	r2, r3, r2
 | 
			
		||||
	ldr	r3, [r1], #4
 | 
			
		||||
	orr	ip, ip, r2
 | 
			
		||||
	orr	r3, r3, r2
 | 
			
		||||
1:
 | 
			
		||||
	/* Load the 'magic' constant 0x01010101. */
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	mov	r4, #1
 | 
			
		||||
	orr	r4, r4, r4, lsl #8
 | 
			
		||||
	orr	r4, r4, r4, lsl #16
 | 
			
		||||
	.p2align	2
 | 
			
		||||
4:
 | 
			
		||||
	PLD(r0, #8)
 | 
			
		||||
	PLD(r1, #8)
 | 
			
		||||
	sub	r2, ip, magic1(r4)
 | 
			
		||||
	cmp	ip, r3
 | 
			
		||||
	itttt	eq
 | 
			
		||||
 | 
			
		||||
	/* check for any zero bytes in first word */
 | 
			
		||||
	biceq	r2, r2, ip
 | 
			
		||||
	tsteq	r2, magic2(r4)
 | 
			
		||||
	ldreq	ip, [r0], #4
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	beq	4b
 | 
			
		||||
2:
 | 
			
		||||
	/* There's a zero or a different byte in the word */
 | 
			
		||||
	SHFT2MSB	r0, ip, #24
 | 
			
		||||
	SHFT2LSB	ip, ip, #8
 | 
			
		||||
	cmp	r0, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r0, r3, SHFT2MSB #24
 | 
			
		||||
	it	eq
 | 
			
		||||
	SHFT2LSBEQ r3, r3, #8
 | 
			
		||||
	beq	2b
 | 
			
		||||
	/* On a big-endian machine, r0 contains the desired byte in bits
 | 
			
		||||
	 * 0-7; on a little-endian machine they are in bits 24-31.  In
 | 
			
		||||
	 * both cases the other bits in r0 are all zero.  For r3 the
 | 
			
		||||
	 * interesting byte is at the other end of the word, but the
 | 
			
		||||
	 * other bits are not necessarily zero.  We need a signed result
 | 
			
		||||
	 * representing the differnece in the unsigned bytes, so for the
 | 
			
		||||
	 * little-endian case we can't just shift the interesting bits up.
 | 
			
		||||
	 */
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	sub	r0, r0, r3, lsr #24
 | 
			
		||||
#else
 | 
			
		||||
	and	r3, r3, #255
 | 
			
		||||
	/* No RSB instruction in Thumb2 */
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
	lsr	r0, r0, #24
 | 
			
		||||
	sub	r0, r0, r3
 | 
			
		||||
#else
 | 
			
		||||
	rsb	r0, r3, r0, lsr #24
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lstrcmp_unaligned:
 | 
			
		||||
	wp1 .req r0
 | 
			
		||||
	wp2 .req r1
 | 
			
		||||
	b1  .req r2
 | 
			
		||||
	w1  .req r4
 | 
			
		||||
	w2  .req r5
 | 
			
		||||
	t1  .req ip
 | 
			
		||||
	@ r3 is scratch
 | 
			
		||||
 | 
			
		||||
	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
 | 
			
		||||
1:
 | 
			
		||||
	tst	wp1, #3
 | 
			
		||||
	beq	2f
 | 
			
		||||
	ldrb	r2, [wp1], #1
 | 
			
		||||
	ldrb	r3, [wp2], #1
 | 
			
		||||
	cmp	r2, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r2, r3
 | 
			
		||||
	beq	1b
 | 
			
		||||
	sub	r0, r2, r3
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
	str	r5, [sp, #-4]!
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	mov	b1, #1
 | 
			
		||||
	orr	b1, b1, b1, lsl #8
 | 
			
		||||
	orr	b1, b1, b1, lsl #16
 | 
			
		||||
 | 
			
		||||
	and	t1, wp2, #3
 | 
			
		||||
	bic	wp2, wp2, #3
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	ldr	w2, [wp2], #4
 | 
			
		||||
	cmp	t1, #2
 | 
			
		||||
	beq	2f
 | 
			
		||||
	bhi	3f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 3 bytes initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
1:
 | 
			
		||||
	bic	t1, w1, #MSB
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #8
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #24
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	1b
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #8
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #0xff000000
 | 
			
		||||
	itt	ne
 | 
			
		||||
	tstne	w1, #0x00ff0000
 | 
			
		||||
	tstne	w1, #0x0000ff00
 | 
			
		||||
	beq	7f
 | 
			
		||||
#else
 | 
			
		||||
	bics	r3, r3, #0xff000000
 | 
			
		||||
	bne	7f
 | 
			
		||||
#endif
 | 
			
		||||
	ldrb	w2, [wp2]
 | 
			
		||||
	SHFT2LSB	t1, w1, #24
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	lsl	w2, w2, #24
 | 
			
		||||
#endif
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2LSB	t1, w1, #24
 | 
			
		||||
	and	w2, w2, #LSB
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 2 bytes initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
2:
 | 
			
		||||
	SHFT2MSB	t1, w1, #16
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	SHFT2LSB	t1, t1, #16
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #16
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #16
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	2b
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #0xff000000
 | 
			
		||||
	it	ne
 | 
			
		||||
	tstne	w1, #0x00ff0000
 | 
			
		||||
	beq	7f
 | 
			
		||||
#else
 | 
			
		||||
	lsls	r3, r3, #16
 | 
			
		||||
	bne	7f
 | 
			
		||||
#endif
 | 
			
		||||
	ldrh	w2, [wp2]
 | 
			
		||||
	SHFT2LSB	t1, w1, #16
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	lsl	w2, w2, #16
 | 
			
		||||
#endif
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2MSB	w2, w2, #16
 | 
			
		||||
	SHFT2LSB	t1, w1, #16
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #16
 | 
			
		||||
	b	8f
 | 
			
		||||
 | 
			
		||||
	/* Critical inner Loop: Block with 1 byte initial overlap */
 | 
			
		||||
	.p2align	2
 | 
			
		||||
3:
 | 
			
		||||
	and	t1, w1, #LSB
 | 
			
		||||
	cmp	t1, w2, SHFT2LSB #24
 | 
			
		||||
	sub	r3, w1, b1
 | 
			
		||||
	bic	r3, r3, w1
 | 
			
		||||
	bne	4f
 | 
			
		||||
	ands	r3, r3, b1, lsl #7
 | 
			
		||||
	it	eq
 | 
			
		||||
	ldreq	w2, [wp2], #4
 | 
			
		||||
	bne	5f
 | 
			
		||||
	eor	t1, t1, w1
 | 
			
		||||
	cmp	t1, w2, SHFT2MSB #8
 | 
			
		||||
	bne	6f
 | 
			
		||||
	ldr	w1, [wp1], #4
 | 
			
		||||
	b	3b
 | 
			
		||||
4:
 | 
			
		||||
	SHFT2LSB	w2, w2, #24
 | 
			
		||||
	b	8f
 | 
			
		||||
5:
 | 
			
		||||
	/* The syndrome value may contain false ones if the string ends
 | 
			
		||||
	 * with the bytes 0x01 0x00
 | 
			
		||||
	 */
 | 
			
		||||
	tst	w1, #LSB
 | 
			
		||||
	beq	7f
 | 
			
		||||
	ldr	w2, [wp2], #4
 | 
			
		||||
6:
 | 
			
		||||
	SHFT2LSB	t1, w1, #8
 | 
			
		||||
	bic	w2, w2, #MSB
 | 
			
		||||
	b	8f
 | 
			
		||||
7:
 | 
			
		||||
	mov	r0, #0
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
8:
 | 
			
		||||
	and	r2, t1, #LSB
 | 
			
		||||
	and	r0, w2, #LSB
 | 
			
		||||
	cmp	r0, #1
 | 
			
		||||
	it	cs
 | 
			
		||||
	cmpcs	r0, r2
 | 
			
		||||
	itt	eq
 | 
			
		||||
	SHFT2LSBEQ	t1, t1, #8
 | 
			
		||||
	SHFT2LSBEQ	w2, w2, #8
 | 
			
		||||
	beq	8b
 | 
			
		||||
	sub	r0, r2, r0
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(strcmp)
 | 
			
		||||
							
								
								
									
										787
									
								
								libc/arch-arm/bionic/strcmp.a15.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										787
									
								
								libc/arch-arm/bionic/strcmp.a15.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,787 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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 "arm_asm.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define S2LOMEM lsl
 | 
			
		||||
#define S2LOMEMEQ lsleq
 | 
			
		||||
#define S2HIMEM 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  __ARMEB__ */
 | 
			
		||||
#define S2LOMEM lsr
 | 
			
		||||
#define S2LOMEMEQ lsreq
 | 
			
		||||
#define S2HIMEM 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  __ARMEB__ */
 | 
			
		||||
 | 
			
		||||
.syntax         unified
 | 
			
		||||
 | 
			
		||||
#if defined (__thumb__)
 | 
			
		||||
        .thumb
 | 
			
		||||
        .thumb_func
 | 
			
		||||
#endif
 | 
			
		||||
        .global strcmp
 | 
			
		||||
        .type   strcmp, %function
 | 
			
		||||
strcmp:
 | 
			
		||||
 | 
			
		||||
#if (defined (__thumb__) && !defined (__thumb2__))
 | 
			
		||||
1:
 | 
			
		||||
        ldrb    r2, [r0]
 | 
			
		||||
        ldrb    r3, [r1]
 | 
			
		||||
        adds    r0, r0, #1
 | 
			
		||||
        adds    r1, r1, #1
 | 
			
		||||
        cmp     r2, #0
 | 
			
		||||
        beq     2f
 | 
			
		||||
        cmp     r2, r3
 | 
			
		||||
        beq     1b
 | 
			
		||||
2:
 | 
			
		||||
        subs    r0, r2, r3
 | 
			
		||||
        bx      lr
 | 
			
		||||
#elif (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
 | 
			
		||||
1:
 | 
			
		||||
        ldrb    r2, [r0], #1
 | 
			
		||||
        ldrb    r3, [r1], #1
 | 
			
		||||
        cmp     r2, #1
 | 
			
		||||
        it      cs
 | 
			
		||||
        cmpcs   r2, r3
 | 
			
		||||
        beq     1b
 | 
			
		||||
        subs    r0, r2, r3
 | 
			
		||||
        RETURN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#elif (defined (_ISA_THUMB_2) || defined (_ISA_ARM_6))
 | 
			
		||||
      /* Use LDRD whenever possible.  */
 | 
			
		||||
 | 
			
		||||
/* The main thing to look out for when comparing large blocks is that
 | 
			
		||||
   the loads do not cross a page boundary when loading past the index
 | 
			
		||||
   of the byte with the first difference or the first string-terminator.
 | 
			
		||||
 | 
			
		||||
   For example, if the strings are identical and the string-terminator
 | 
			
		||||
   is at index k, byte by byte comparison will not load beyond address
 | 
			
		||||
   s1+k and s2+k; word by word comparison may load up to 3 bytes beyond
 | 
			
		||||
   k; double word - up to 7 bytes.  If the load of these bytes crosses
 | 
			
		||||
   a page boundary, it might cause a memory fault (if the page is not mapped)
 | 
			
		||||
   that would not have happened in byte by byte comparison.
 | 
			
		||||
 | 
			
		||||
   If an address is (double) word aligned, then a load of a (double) word
 | 
			
		||||
   from that address will not cross a page boundary.
 | 
			
		||||
   Therefore, the algorithm below considers word and double-word alignment
 | 
			
		||||
   of strings separately.  */
 | 
			
		||||
 | 
			
		||||
/* High-level description of the algorithm.
 | 
			
		||||
 | 
			
		||||
   * The fast path: if both strings are double-word aligned,
 | 
			
		||||
     use LDRD to load two words from each string in every loop iteration.
 | 
			
		||||
   * If the strings have the same offset from a word boundary,
 | 
			
		||||
     use LDRB to load and compare byte by byte until
 | 
			
		||||
     the first string is aligned to a word boundary (at most 3 bytes).
 | 
			
		||||
     This is optimized for quick return on short unaligned strings.
 | 
			
		||||
   * If the strings have the same offset from a double-word boundary,
 | 
			
		||||
     use LDRD to load two words from each string in every loop iteration, as in the fast path.
 | 
			
		||||
   * If the strings do not have the same offset from a double-word boundary,
 | 
			
		||||
     load a word from the second string before the loop to initialize the queue.
 | 
			
		||||
     Use LDRD to load two words from every string in every loop iteration.
 | 
			
		||||
     Inside the loop, load the second word from the second string only after comparing
 | 
			
		||||
     the first word, using the queued value, to guarantee safety across page boundaries.
 | 
			
		||||
   * If the strings do not have the same offset from a word boundary,
 | 
			
		||||
     use LDR and a shift queue. Order of loads and comparisons matters,
 | 
			
		||||
     similarly to the previous case.
 | 
			
		||||
 | 
			
		||||
   * Use UADD8 and SEL to compare words, and use REV and CLZ to compute the return value.
 | 
			
		||||
   * The only difference between ARM and Thumb modes is the use of CBZ instruction.
 | 
			
		||||
   * The only difference between big and little endian is the use of REV in little endian
 | 
			
		||||
     to compute the return value, instead of MOV.
 | 
			
		||||
   * No preload. [TODO.]
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
        .macro m_cbz reg label
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
        cbz     \reg, \label
 | 
			
		||||
#else   /* not defined __thumb2__ */
 | 
			
		||||
        cmp     \reg, #0
 | 
			
		||||
        beq     \label
 | 
			
		||||
#endif /* not defined __thumb2__ */
 | 
			
		||||
        .endm /* m_cbz */
 | 
			
		||||
 | 
			
		||||
        .macro m_cbnz reg label
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
        cbnz    \reg, \label
 | 
			
		||||
#else   /* not defined __thumb2__ */
 | 
			
		||||
        cmp     \reg, #0
 | 
			
		||||
        bne     \label
 | 
			
		||||
#endif /* not defined __thumb2__ */
 | 
			
		||||
        .endm /* m_cbnz */
 | 
			
		||||
 | 
			
		||||
        .macro  init
 | 
			
		||||
        /* Macro to save temporary registers and prepare magic values.  */
 | 
			
		||||
        subs    sp, sp, #16
 | 
			
		||||
        strd    r4, r5, [sp, #8]
 | 
			
		||||
        strd    r6, r7, [sp]
 | 
			
		||||
        mvn     r6, #0  /* all F */
 | 
			
		||||
        mov     r7, #0  /* all 0 */
 | 
			
		||||
        .endm   /* init */
 | 
			
		||||
 | 
			
		||||
        .macro  magic_compare_and_branch w1 w2 label
 | 
			
		||||
        /* Macro to compare registers w1 and w2 and conditionally branch to label.  */
 | 
			
		||||
        cmp     \w1, \w2        /* Are w1 and w2 the same?  */
 | 
			
		||||
        magic_find_zero_bytes \w1
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   ip, #0          /* Is there a zero byte in w1?  */
 | 
			
		||||
        bne     \label
 | 
			
		||||
        .endm /* magic_compare_and_branch */
 | 
			
		||||
 | 
			
		||||
        .macro  magic_find_zero_bytes w1
 | 
			
		||||
        /* Macro to find all-zero bytes in w1, result is in ip.  */
 | 
			
		||||
#if (defined (__ARM_FEATURE_DSP))
 | 
			
		||||
        uadd8   ip, \w1, r6
 | 
			
		||||
        sel     ip, r7, r6
 | 
			
		||||
#else /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        /* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
 | 
			
		||||
        Coincidently, these processors only have Thumb-2 mode, where we can use the
 | 
			
		||||
        the (large) magic constant available directly as an immediate in instructions.
 | 
			
		||||
        Note that we cannot use the magic constant in ARM mode, where we need
 | 
			
		||||
        to create the constant in a register.  */
 | 
			
		||||
        sub     ip, \w1, #0x01010101
 | 
			
		||||
        bic     ip, ip, \w1
 | 
			
		||||
        and     ip, ip, #0x80808080
 | 
			
		||||
#endif /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        .endm /* magic_find_zero_bytes */
 | 
			
		||||
 | 
			
		||||
        .macro  setup_return w1 w2
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        mov     r1, \w1
 | 
			
		||||
        mov     r2, \w2
 | 
			
		||||
#else /* not  __ARMEB__ */
 | 
			
		||||
        rev     r1, \w1
 | 
			
		||||
        rev     r2, \w2
 | 
			
		||||
#endif /* not  __ARMEB__ */
 | 
			
		||||
        .endm /* setup_return */
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
        optpld r0, #0
 | 
			
		||||
        optpld r1, #0
 | 
			
		||||
        */
 | 
			
		||||
 | 
			
		||||
        /* Are both strings double-word aligned?  */
 | 
			
		||||
        orr     ip, r0, r1
 | 
			
		||||
        tst     ip, #7
 | 
			
		||||
        bne     do_align
 | 
			
		||||
 | 
			
		||||
        /* Fast path.  */
 | 
			
		||||
        init
 | 
			
		||||
 | 
			
		||||
doubleword_aligned:
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are double-word aligned.  */
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
2:
 | 
			
		||||
        /*
 | 
			
		||||
        optpld r0, #16
 | 
			
		||||
        optpld r1, #16
 | 
			
		||||
        */
 | 
			
		||||
 | 
			
		||||
        /* Load the next double-word from each string.  */
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
 | 
			
		||||
        magic_compare_and_branch w1=r2, w2=r4, label=return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=return_35
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
do_align:
 | 
			
		||||
        /* Is the first string word-aligned?  */
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        beq     word_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* Fast compare byte by byte until the first string is word-aligned.  */
 | 
			
		||||
        /* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
 | 
			
		||||
        to read until the next word boudnary is 4-ip.  */
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        lsls    ip, ip, #31
 | 
			
		||||
        beq     byte2
 | 
			
		||||
        bcs     byte3
 | 
			
		||||
 | 
			
		||||
byte1:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE1_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
byte2:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE2_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
byte3:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE3_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbnz  reg=r3, label=word_aligned_r0
 | 
			
		||||
 | 
			
		||||
fast_return:
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
word_aligned_r0:
 | 
			
		||||
        init
 | 
			
		||||
        /* The first string is word-aligned.  */
 | 
			
		||||
        /* Is the second string word-aligned?  */
 | 
			
		||||
        ands    ip, r1, #3
 | 
			
		||||
        bne     strcmp_unaligned
 | 
			
		||||
 | 
			
		||||
word_aligned:
 | 
			
		||||
        /* The strings are word-aligned. */
 | 
			
		||||
        /* Is the first string double-word aligned?  */
 | 
			
		||||
        tst     r0, #4
 | 
			
		||||
        beq     doubleword_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* If r0 is not double-word aligned yet, align it by loading
 | 
			
		||||
        and comparing the next word from each string.  */
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        ldr     r4, [r1], #4
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r4 label=return_24
 | 
			
		||||
 | 
			
		||||
doubleword_aligned_r0:
 | 
			
		||||
        /* Get here when r0 is double-word aligned.  */
 | 
			
		||||
        /* Is r1 doubleword_aligned?  */
 | 
			
		||||
        tst     r1, #4
 | 
			
		||||
        beq     doubleword_aligned
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are word-aligned,
 | 
			
		||||
        r0 is double-word aligned, but r1 is not double-word aligned.  */
 | 
			
		||||
 | 
			
		||||
        /* Initialize the queue.  */
 | 
			
		||||
        ldr     r5, [r1], #4
 | 
			
		||||
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
3:
 | 
			
		||||
        /*
 | 
			
		||||
        optpld r0, #16
 | 
			
		||||
        optpld r1, #16
 | 
			
		||||
        */
 | 
			
		||||
 | 
			
		||||
        /* Load the next double-word from each string and compare.  */
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r5 label=return_25
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=return_34
 | 
			
		||||
        b       3b
 | 
			
		||||
 | 
			
		||||
        .macro miscmp_word offsetlo offsethi
 | 
			
		||||
        /* Macro to compare misaligned strings.  */
 | 
			
		||||
        /* r0, r1 are word-aligned, and at least one of the strings
 | 
			
		||||
        is not double-word aligned.  */
 | 
			
		||||
        /* Compare one word in every loop iteration.  */
 | 
			
		||||
        /* OFFSETLO is the original bit-offset of r1 from a word-boundary,
 | 
			
		||||
        OFFSETHI is 32 - OFFSETLO (i.e., offset from the next word).  */
 | 
			
		||||
 | 
			
		||||
        /* Initialize the shift queue.  */
 | 
			
		||||
        ldr     r5, [r1], #4
 | 
			
		||||
 | 
			
		||||
        /* Compare one word from each string in every loop iteration.  */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
7:
 | 
			
		||||
        ldr     r3, [r0], #4
 | 
			
		||||
        S2LOMEM r5, r5, #\offsetlo
 | 
			
		||||
        magic_find_zero_bytes w1=r3
 | 
			
		||||
        cmp     r7, ip, S2HIMEM #\offsetlo
 | 
			
		||||
        and     r2, r3, r6, S2LOMEM #\offsetlo
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r2, r5
 | 
			
		||||
        bne     return_25
 | 
			
		||||
        ldr     r5, [r1], #4
 | 
			
		||||
        cmp     ip, #0
 | 
			
		||||
        eor r3, r2, r3
 | 
			
		||||
        S2HIMEM r2, r5, #\offsethi
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r3, r2
 | 
			
		||||
        bne     return_32
 | 
			
		||||
        b       7b
 | 
			
		||||
        .endm /* miscmp_word */
 | 
			
		||||
 | 
			
		||||
strcmp_unaligned:
 | 
			
		||||
        /* r0 is word-aligned, r1 is at offset ip from a word.  */
 | 
			
		||||
        /* Align r1 to the (previous) word-boundary.  */
 | 
			
		||||
        bic     r1, r1, #3
 | 
			
		||||
 | 
			
		||||
        /* Unaligned comparison word by word using LDRs. */
 | 
			
		||||
        cmp     ip, #2
 | 
			
		||||
        beq     miscmp_word_16                    /* If ip == 2.  */
 | 
			
		||||
        bge     miscmp_word_24                    /* If ip == 3.  */
 | 
			
		||||
        miscmp_word offsetlo=8 offsethi=24        /* If ip == 1.  */
 | 
			
		||||
miscmp_word_16:  miscmp_word offsetlo=16 offsethi=16
 | 
			
		||||
miscmp_word_24:  miscmp_word offsetlo=24 offsethi=8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
return_32:
 | 
			
		||||
        setup_return w1=r3, w2=r2
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_34:
 | 
			
		||||
        setup_return w1=r3, w2=r4
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_25:
 | 
			
		||||
        setup_return w1=r2, w2=r5
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_35:
 | 
			
		||||
        setup_return w1=r3, w2=r5
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_24:
 | 
			
		||||
        setup_return w1=r2, w2=r4
 | 
			
		||||
 | 
			
		||||
do_return:
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
#else /* not  __ARMEB__ */
 | 
			
		||||
        rev     r0, ip
 | 
			
		||||
#endif /* not  __ARMEB__ */
 | 
			
		||||
 | 
			
		||||
        /* Restore temporaries early, before computing the return value.  */
 | 
			
		||||
        ldrd    r6, r7, [sp]
 | 
			
		||||
        ldrd    r4, r5, [sp, #8]
 | 
			
		||||
        adds    sp, sp, #16
 | 
			
		||||
 | 
			
		||||
        /* There is a zero or a different byte between r1 and r2.  */
 | 
			
		||||
        /* r0 contains a mask of all-zero bytes in r1.  */
 | 
			
		||||
        /* Using r0 and not ip here because cbz requires low register.  */
 | 
			
		||||
        m_cbz   reg=r0, label=compute_return_value
 | 
			
		||||
        clz     r0, r0
 | 
			
		||||
        /* r0 contains the number of bits on the left of the first all-zero byte in r1.  */
 | 
			
		||||
        rsb     r0, r0, #24
 | 
			
		||||
        /* Here, r0 contains the number of bits on the right of the first all-zero byte in r1.  */
 | 
			
		||||
        lsr     r1, r1, r0
 | 
			
		||||
        lsr     r2, r2, r0
 | 
			
		||||
 | 
			
		||||
compute_return_value:
 | 
			
		||||
        movs    r0, #1
 | 
			
		||||
        cmp     r1, r2
 | 
			
		||||
        /* The return value is computed as follows.
 | 
			
		||||
        If r1>r2 then (C==1 and Z==0) and LS doesn't hold and r0 is #1 at return.
 | 
			
		||||
        If r1<r2 then (C==0 and Z==0) and we execute SBC with carry_in=0,
 | 
			
		||||
        which means r0:=r0-r0-1 and r0 is #-1 at return.
 | 
			
		||||
        If r1=r2 then (C==1 and Z==1) and we execute SBC with carry_in=1,
 | 
			
		||||
        which means r0:=r0-r0 and r0 is #0 at return.
 | 
			
		||||
        (C==0 and Z==1) cannot happen because the carry bit is "not borrow".  */
 | 
			
		||||
        it      ls
 | 
			
		||||
        sbcls   r0, r0, r0
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else   /* !(defined (_ISA_THUMB_2) || defined (_ISA_ARM_6)
 | 
			
		||||
             defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) ||
 | 
			
		||||
             (defined (__thumb__) && !defined (__thumb2__))) */
 | 
			
		||||
 | 
			
		||||
        /* Use LDR whenever possible. */
 | 
			
		||||
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
#define magic1(REG) 0x01010101
 | 
			
		||||
#define magic2(REG) 0x80808080
 | 
			
		||||
#else
 | 
			
		||||
#define magic1(REG) REG
 | 
			
		||||
#define magic2(REG) REG, lsl #7
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        optpld  r0
 | 
			
		||||
        optpld  r1
 | 
			
		||||
        eor     r2, r0, r1
 | 
			
		||||
        tst     r2, #3
 | 
			
		||||
        /* Strings not at same byte offset from a word boundary.  */
 | 
			
		||||
        bne     strcmp_unaligned
 | 
			
		||||
        ands    r2, r0, #3
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        bic     r1, r1, #3
 | 
			
		||||
        ldr     ip, [r0], #4
 | 
			
		||||
        it      eq
 | 
			
		||||
        ldreq   r3, [r1], #4
 | 
			
		||||
        beq     1f
 | 
			
		||||
        /* Although s1 and s2 have identical initial alignment, they are
 | 
			
		||||
        not currently word aligned.  Rather than comparing bytes,
 | 
			
		||||
    make sure that any bytes fetched from before the addressed
 | 
			
		||||
    bytes are forced to 0xff.  Then they will always compare
 | 
			
		||||
    equal.  */
 | 
			
		||||
        eor     r2, r2, #3
 | 
			
		||||
        lsl     r2, r2, #3
 | 
			
		||||
        mvn     r3, MSB
 | 
			
		||||
        S2LOMEM        r2, r3, r2
 | 
			
		||||
        ldr     r3, [r1], #4
 | 
			
		||||
        orr     ip, ip, r2
 | 
			
		||||
        orr     r3, r3, r2
 | 
			
		||||
1:
 | 
			
		||||
#ifndef __thumb2__
 | 
			
		||||
              /* Load the 'magic' constant 0x01010101.  */
 | 
			
		||||
        str     r4, [sp, #-4]!
 | 
			
		||||
        mov     r4, #1
 | 
			
		||||
        orr     r4, r4, r4, lsl #8
 | 
			
		||||
        orr     r4, r4, r4, lsl #16
 | 
			
		||||
#endif
 | 
			
		||||
        .p2align        2
 | 
			
		||||
4:
 | 
			
		||||
        optpld  r0, #8
 | 
			
		||||
        optpld  r1, #8
 | 
			
		||||
        sub     r2, ip, magic1(r4)
 | 
			
		||||
        cmp     ip, r3
 | 
			
		||||
        itttt   eq
 | 
			
		||||
        /* check for any zero bytes in first word */
 | 
			
		||||
        biceq   r2, r2, ip
 | 
			
		||||
        tsteq   r2, magic2(r4)
 | 
			
		||||
        ldreq   ip, [r0], #4
 | 
			
		||||
        ldreq   r3, [r1], #4
 | 
			
		||||
        beq     4b
 | 
			
		||||
2:
 | 
			
		||||
        /* There's a zero or a different byte in the word */
 | 
			
		||||
        S2HIMEM  r0, ip, #24
 | 
			
		||||
        S2LOMEM  ip, ip, #8
 | 
			
		||||
        cmp     r0, #1
 | 
			
		||||
        it      cs
 | 
			
		||||
        cmpcs   r0, r3, S2HIMEM #24
 | 
			
		||||
        it      eq
 | 
			
		||||
        S2LOMEMEQ r3, r3, #8
 | 
			
		||||
        beq     2b
 | 
			
		||||
        /* On a big-endian machine, r0 contains the desired byte in bits
 | 
			
		||||
        0-7; on a little-endian machine they are in bits 24-31.  In
 | 
			
		||||
        both cases the other bits in r0 are all zero.  For r3 the
 | 
			
		||||
        interesting byte is at the other end of the word, but the
 | 
			
		||||
        other bits are not necessarily zero.  We need a signed result
 | 
			
		||||
        representing the differnece in the unsigned bytes, so for the
 | 
			
		||||
        little-endian case we can't just shift the interesting bits
 | 
			
		||||
        up.  */
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        sub     r0, r0, r3, lsr #24
 | 
			
		||||
#else
 | 
			
		||||
        and     r3, r3, #255
 | 
			
		||||
#ifdef __thumb2__
 | 
			
		||||
        /* No RSB instruction in Thumb2 */
 | 
			
		||||
        lsr     r0, r0, #24
 | 
			
		||||
        sub     r0, r0, r3
 | 
			
		||||
#else
 | 
			
		||||
        rsb     r0, r3, r0, lsr #24
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef __thumb2__
 | 
			
		||||
        ldr     r4, [sp], #4
 | 
			
		||||
#endif
 | 
			
		||||
        RETURN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
strcmp_unaligned:
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
        /* The assembly code below is based on the following alogrithm.  */
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define RSHIFT <<
 | 
			
		||||
#define LSHIFT >>
 | 
			
		||||
#else
 | 
			
		||||
#define RSHIFT >>
 | 
			
		||||
#define LSHIFT <<
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define body(shift)                         \
 | 
			
		||||
  mask = 0xffffffffU RSHIFT shift;                  \
 | 
			
		||||
  w1 = *wp1++;                              \
 | 
			
		||||
  w2 = *wp2++;                              \
 | 
			
		||||
  do                                    \
 | 
			
		||||
    {                                   \
 | 
			
		||||
      t1 = w1 & mask;                           \
 | 
			
		||||
      if (__builtin_expect(t1 != w2 RSHIFT shift, 0))           \
 | 
			
		||||
    {                               \
 | 
			
		||||
      w2 RSHIFT= shift;                     \
 | 
			
		||||
      break;                            \
 | 
			
		||||
    }                               \
 | 
			
		||||
      if (__builtin_expect(((w1 - b1) & ~w1) & (b1 << 7), 0))       \
 | 
			
		||||
    {                               \
 | 
			
		||||
      /* See comment in assembler below re syndrome on big-endian */\
 | 
			
		||||
      if ((((w1 - b1) & ~w1) & (b1 << 7)) & mask)           \
 | 
			
		||||
        w2 RSHIFT= shift;                       \
 | 
			
		||||
      else                              \
 | 
			
		||||
        {                               \
 | 
			
		||||
          w2 = *wp2;                        \
 | 
			
		||||
          t1 = w1 RSHIFT (32 - shift);              \
 | 
			
		||||
          w2 = (w2 LSHIFT (32 - shift)) RSHIFT (32 - shift);    \
 | 
			
		||||
        }                               \
 | 
			
		||||
      break;                            \
 | 
			
		||||
    }                               \
 | 
			
		||||
      w2 = *wp2++;                          \
 | 
			
		||||
      t1 ^= w1;                             \
 | 
			
		||||
      if (__builtin_expect(t1 != w2 LSHIFT (32 - shift), 0))        \
 | 
			
		||||
    {                               \
 | 
			
		||||
      t1 = w1 >> (32 - shift);                  \
 | 
			
		||||
      w2 = (w2 << (32 - shift)) RSHIFT (32 - shift);        \
 | 
			
		||||
      break;                            \
 | 
			
		||||
    }                               \
 | 
			
		||||
      w1 = *wp1++;                          \
 | 
			
		||||
    } while (1)
 | 
			
		||||
 | 
			
		||||
  const unsigned* wp1;
 | 
			
		||||
  const unsigned* wp2;
 | 
			
		||||
  unsigned w1, w2;
 | 
			
		||||
  unsigned mask;
 | 
			
		||||
  unsigned shift;
 | 
			
		||||
  unsigned b1 = 0x01010101;
 | 
			
		||||
  char c1, c2;
 | 
			
		||||
  unsigned t1;
 | 
			
		||||
 | 
			
		||||
  while (((unsigned) s1) & 3)
 | 
			
		||||
    {
 | 
			
		||||
      c1 = *s1++;
 | 
			
		||||
      c2 = *s2++;
 | 
			
		||||
      if (c1 == 0 || c1 != c2)
 | 
			
		||||
    return c1 - (int)c2;
 | 
			
		||||
    }
 | 
			
		||||
  wp1 = (unsigned*) (((unsigned)s1) & ~3);
 | 
			
		||||
  wp2 = (unsigned*) (((unsigned)s2) & ~3);
 | 
			
		||||
  t1 = ((unsigned) s2) & 3;
 | 
			
		||||
  if (t1 == 1)
 | 
			
		||||
    {
 | 
			
		||||
      body(8);
 | 
			
		||||
    }
 | 
			
		||||
  else if (t1 == 2)
 | 
			
		||||
    {
 | 
			
		||||
      body(16);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      body (24);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  do
 | 
			
		||||
    {
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
      c1 = (char) t1 >> 24;
 | 
			
		||||
      c2 = (char) w2 >> 24;
 | 
			
		||||
#else /* not  __ARMEB__ */
 | 
			
		||||
      c1 = (char) t1;
 | 
			
		||||
      c2 = (char) w2;
 | 
			
		||||
#endif /* not  __ARMEB__ */
 | 
			
		||||
      t1 RSHIFT= 8;
 | 
			
		||||
      w2 RSHIFT= 8;
 | 
			
		||||
    } while (c1 != 0 && c1 == c2);
 | 
			
		||||
  return c1 - c2;
 | 
			
		||||
#endif /* 0 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        wp1 .req r0
 | 
			
		||||
        wp2 .req r1
 | 
			
		||||
        b1  .req r2
 | 
			
		||||
        w1  .req r4
 | 
			
		||||
        w2  .req r5
 | 
			
		||||
        t1  .req ip
 | 
			
		||||
        @ r3 is scratch
 | 
			
		||||
 | 
			
		||||
        /* First of all, compare bytes until wp1(sp1) is word-aligned. */
 | 
			
		||||
1:
 | 
			
		||||
        tst     wp1, #3
 | 
			
		||||
        beq     2f
 | 
			
		||||
        ldrb    r2, [wp1], #1
 | 
			
		||||
        ldrb    r3, [wp2], #1
 | 
			
		||||
        cmp     r2, #1
 | 
			
		||||
        it      cs
 | 
			
		||||
        cmpcs   r2, r3
 | 
			
		||||
        beq     1b
 | 
			
		||||
        sub     r0, r2, r3
 | 
			
		||||
        RETURN
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
        str     r5, [sp, #-4]!
 | 
			
		||||
        str     r4, [sp, #-4]!
 | 
			
		||||
        //stmfd   sp!, {r4, r5}
 | 
			
		||||
        mov     b1, #1
 | 
			
		||||
        orr     b1, b1, b1, lsl #8
 | 
			
		||||
        orr     b1, b1, b1, lsl #16
 | 
			
		||||
 | 
			
		||||
        and     t1, wp2, #3
 | 
			
		||||
        bic     wp2, wp2, #3
 | 
			
		||||
        ldr     w1, [wp1], #4
 | 
			
		||||
        ldr     w2, [wp2], #4
 | 
			
		||||
        cmp     t1, #2
 | 
			
		||||
        beq     2f
 | 
			
		||||
        bhi     3f
 | 
			
		||||
 | 
			
		||||
        /* Critical inner Loop: Block with 3 bytes initial overlap */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
1:
 | 
			
		||||
        bic     t1, w1, MSB
 | 
			
		||||
        cmp     t1, w2, S2LOMEM #8
 | 
			
		||||
        sub     r3, w1, b1
 | 
			
		||||
        bic     r3, r3, w1
 | 
			
		||||
        bne     4f
 | 
			
		||||
        ands    r3, r3, b1, lsl #7
 | 
			
		||||
        it      eq
 | 
			
		||||
        ldreq   w2, [wp2], #4
 | 
			
		||||
        bne     5f
 | 
			
		||||
        eor     t1, t1, w1
 | 
			
		||||
        cmp     t1, w2, S2HIMEM #24
 | 
			
		||||
        bne     6f
 | 
			
		||||
        ldr     w1, [wp1], #4
 | 
			
		||||
        b       1b
 | 
			
		||||
4:
 | 
			
		||||
        S2LOMEM        w2, w2, #8
 | 
			
		||||
        b       8f
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        /* The syndrome value may contain false ones if the string ends
 | 
			
		||||
        with the bytes 0x01 0x00 */
 | 
			
		||||
        tst     w1, #0xff000000
 | 
			
		||||
        itt     ne
 | 
			
		||||
        tstne   w1, #0x00ff0000
 | 
			
		||||
        tstne   w1, #0x0000ff00
 | 
			
		||||
        beq     7f
 | 
			
		||||
#else
 | 
			
		||||
        bics    r3, r3, #0xff000000
 | 
			
		||||
        bne     7f
 | 
			
		||||
#endif
 | 
			
		||||
        ldrb    w2, [wp2]
 | 
			
		||||
        S2LOMEM  t1, w1, #24
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        lsl     w2, w2, #24
 | 
			
		||||
#endif
 | 
			
		||||
        b       8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
        S2LOMEM  t1, w1, #24
 | 
			
		||||
        and     w2, w2, LSB
 | 
			
		||||
        b       8f
 | 
			
		||||
 | 
			
		||||
        /* Critical inner Loop: Block with 2 bytes initial overlap */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
2:
 | 
			
		||||
        S2HIMEM  t1, w1, #16
 | 
			
		||||
        sub     r3, w1, b1
 | 
			
		||||
        S2LOMEM  t1, t1, #16
 | 
			
		||||
        bic     r3, r3, w1
 | 
			
		||||
        cmp     t1, w2, S2LOMEM #16
 | 
			
		||||
        bne     4f
 | 
			
		||||
        ands    r3, r3, b1, lsl #7
 | 
			
		||||
        it      eq
 | 
			
		||||
        ldreq   w2, [wp2], #4
 | 
			
		||||
        bne     5f
 | 
			
		||||
        eor     t1, t1, w1
 | 
			
		||||
        cmp     t1, w2, S2HIMEM #16
 | 
			
		||||
        bne     6f
 | 
			
		||||
        ldr     w1, [wp1], #4
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
5:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        /* The syndrome value may contain false ones if the string ends
 | 
			
		||||
        with the bytes 0x01 0x00 */
 | 
			
		||||
        tst     w1, #0xff000000
 | 
			
		||||
        it      ne
 | 
			
		||||
        tstne   w1, #0x00ff0000
 | 
			
		||||
        beq     7f
 | 
			
		||||
#else
 | 
			
		||||
        lsls    r3, r3, #16
 | 
			
		||||
        bne     7f
 | 
			
		||||
#endif
 | 
			
		||||
        ldrh    w2, [wp2]
 | 
			
		||||
        S2LOMEM  t1, w1, #16
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        lsl     w2, w2, #16
 | 
			
		||||
#endif
 | 
			
		||||
        b       8f
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
        S2HIMEM  w2, w2, #16
 | 
			
		||||
        S2LOMEM  t1, w1, #16
 | 
			
		||||
4:
 | 
			
		||||
        S2LOMEM  w2, w2, #16
 | 
			
		||||
        b       8f
 | 
			
		||||
 | 
			
		||||
        /* Critical inner Loop: Block with 1 byte initial overlap */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
3:
 | 
			
		||||
        and     t1, w1, LSB
 | 
			
		||||
        cmp     t1, w2, S2LOMEM #24
 | 
			
		||||
        sub     r3, w1, b1
 | 
			
		||||
        bic     r3, r3, w1
 | 
			
		||||
        bne     4f
 | 
			
		||||
        ands    r3, r3, b1, lsl #7
 | 
			
		||||
        it      eq
 | 
			
		||||
        ldreq   w2, [wp2], #4
 | 
			
		||||
        bne     5f
 | 
			
		||||
        eor     t1, t1, w1
 | 
			
		||||
        cmp     t1, w2, S2HIMEM #8
 | 
			
		||||
        bne     6f
 | 
			
		||||
        ldr     w1, [wp1], #4
 | 
			
		||||
        b       3b
 | 
			
		||||
4:
 | 
			
		||||
        S2LOMEM  w2, w2, #24
 | 
			
		||||
        b       8f
 | 
			
		||||
5:
 | 
			
		||||
        /* The syndrome value may contain false ones if the string ends
 | 
			
		||||
        with the bytes 0x01 0x00 */
 | 
			
		||||
        tst     w1, LSB
 | 
			
		||||
        beq     7f
 | 
			
		||||
        ldr     w2, [wp2], #4
 | 
			
		||||
6:
 | 
			
		||||
        S2LOMEM  t1, w1, #8
 | 
			
		||||
        bic     w2, w2, MSB
 | 
			
		||||
        b       8f
 | 
			
		||||
7:
 | 
			
		||||
        mov     r0, #0
 | 
			
		||||
        //ldmfd   sp!, {r4, r5}
 | 
			
		||||
        ldr     r4, [sp], #4
 | 
			
		||||
        ldr     r5, [sp], #4
 | 
			
		||||
        RETURN
 | 
			
		||||
8:
 | 
			
		||||
        and     r2, t1, LSB
 | 
			
		||||
        and     r0, w2, LSB
 | 
			
		||||
        cmp     r0, #1
 | 
			
		||||
        it      cs
 | 
			
		||||
        cmpcs   r0, r2
 | 
			
		||||
        itt     eq
 | 
			
		||||
        S2LOMEMEQ        t1, t1, #8
 | 
			
		||||
        S2LOMEMEQ        w2, w2, #8
 | 
			
		||||
        beq     8b
 | 
			
		||||
        sub     r0, r2, r0
 | 
			
		||||
        //ldmfd   sp!, {r4, r5}
 | 
			
		||||
        ldr     r4, [sp], #4
 | 
			
		||||
        ldr     r5, [sp], #4
 | 
			
		||||
        RETURN
 | 
			
		||||
 | 
			
		||||
#endif /* !(defined (_ISA_THUMB_2) || defined (_ISA_ARM_6)
 | 
			
		||||
            defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) ||
 | 
			
		||||
            (defined (__thumb__) && !defined (__thumb2__))) */
 | 
			
		||||
							
								
								
									
										133
									
								
								libc/arch-arm/bionic/strcpy.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								libc/arch-arm/bionic/strcpy.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2008 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
	PLD(r1, #0)
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	mov	ip, r0
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
	bne	4f
 | 
			
		||||
	tst	r1, #3
 | 
			
		||||
	bne	3f
 | 
			
		||||
5:
 | 
			
		||||
	str	r5, [sp, #-4]!
 | 
			
		||||
	mov	r5, #0x01
 | 
			
		||||
	orr	r5, r5, r5, lsl #8
 | 
			
		||||
	orr	r5, r5, r5, lsl #16
 | 
			
		||||
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	tst	r1, #4
 | 
			
		||||
	ldr	r3, [r1], #4
 | 
			
		||||
	beq	2f
 | 
			
		||||
	sub	r2, r3, r5
 | 
			
		||||
	bics	r2, r2, r3
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	itt	eq
 | 
			
		||||
	streq	r3, [ip], #4
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	bne	1f
 | 
			
		||||
       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
 | 
			
		||||
	  can safely fetch up to two words.  This allows us to avoid
 | 
			
		||||
	  load stalls.  */
 | 
			
		||||
	.p2align 2
 | 
			
		||||
2:
 | 
			
		||||
	PLD(r1, #8)
 | 
			
		||||
	ldr	r4, [r1], #4
 | 
			
		||||
	sub	r2, r3, r5
 | 
			
		||||
	bics	r2, r2, r3
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	sub	r2, r4, r5
 | 
			
		||||
	bne	1f
 | 
			
		||||
	str	r3, [ip], #4
 | 
			
		||||
	bics	r2, r2, r4
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	itt	eq
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	streq	r4, [ip], #4
 | 
			
		||||
	beq	2b
 | 
			
		||||
	mov	r3, r4
 | 
			
		||||
1:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	rors	r3, r3, #24
 | 
			
		||||
#endif
 | 
			
		||||
	strb	r3, [ip], #1
 | 
			
		||||
	tst	r3, #0xff
 | 
			
		||||
#ifdef __ARMEL__
 | 
			
		||||
	ror	r3, r3, #8
 | 
			
		||||
#endif
 | 
			
		||||
	bne	1b
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
       /* Strings have the same offset from word alignment, but it's
 | 
			
		||||
	  not zero.  */
 | 
			
		||||
3:
 | 
			
		||||
	tst	r1, #1
 | 
			
		||||
	beq	1f
 | 
			
		||||
	ldrb	r2, [r1], #1
 | 
			
		||||
	strb	r2, [ip], #1
 | 
			
		||||
	cmp	r2, #0
 | 
			
		||||
	it	eq
 | 
			
		||||
	bxeq	lr
 | 
			
		||||
1:
 | 
			
		||||
	tst	r1, #2
 | 
			
		||||
	beq	5b
 | 
			
		||||
	ldrh	r2, [r1], #2
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	tst	r2, #0xff00
 | 
			
		||||
	iteet	ne
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	lsreq	r2, r2, #8
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff
 | 
			
		||||
#else
 | 
			
		||||
	tst	r2, #0xff
 | 
			
		||||
	itet	ne
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff00
 | 
			
		||||
#endif
 | 
			
		||||
	bne	5b
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
       /* src and dst do not have a common word-alignement.  Fall back to
 | 
			
		||||
	  byte copying.  */
 | 
			
		||||
4:
 | 
			
		||||
	ldrb	r2, [r1], #1
 | 
			
		||||
	strb	r2, [ip], #1
 | 
			
		||||
	cmp	r2, #0
 | 
			
		||||
	bne	4b
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(strcpy)
 | 
			
		||||
							
								
								
									
										129
									
								
								libc/arch-arm/bionic/strlen.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								libc/arch-arm/bionic/strlen.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <string.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
size_t strlen(const char *s)
 | 
			
		||||
{
 | 
			
		||||
    __builtin_prefetch(s);
 | 
			
		||||
    __builtin_prefetch(s+32);
 | 
			
		||||
    
 | 
			
		||||
    union {
 | 
			
		||||
        const char      *b;
 | 
			
		||||
        const uint32_t  *w;
 | 
			
		||||
        uintptr_t       i;
 | 
			
		||||
    } u;
 | 
			
		||||
    
 | 
			
		||||
    // these are some scratch variables for the asm code below
 | 
			
		||||
    uint32_t v, t;
 | 
			
		||||
    
 | 
			
		||||
    // initialize the string length to zero
 | 
			
		||||
    size_t l = 0;
 | 
			
		||||
 | 
			
		||||
    // align the pointer to a 32-bit word boundary
 | 
			
		||||
    u.b = s;
 | 
			
		||||
    while (u.i & 0x3)  {
 | 
			
		||||
        if (__builtin_expect(*u.b++ == 0, 0)) {
 | 
			
		||||
            goto done;
 | 
			
		||||
        }
 | 
			
		||||
        l++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // loop for each word, testing if it contains a zero byte
 | 
			
		||||
    // if so, exit the loop and update the length.
 | 
			
		||||
    // We need to process 32 bytes per loop to schedule PLD properly
 | 
			
		||||
    // and achieve the maximum bus speed.
 | 
			
		||||
    asm(
 | 
			
		||||
        "ldr     %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "sub     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "0:                                 \n"
 | 
			
		||||
#if __ARM_HAVE_PLD
 | 
			
		||||
        "pld     [ %[s], #64 ]              \n"
 | 
			
		||||
#endif
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
#if !defined(__OPTIMIZE_SIZE__)
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "ldreq   %[v], [ %[s] ], #4         \n"
 | 
			
		||||
#endif
 | 
			
		||||
        "beq     0b                         \n"
 | 
			
		||||
        "1:                                 \n"
 | 
			
		||||
        "add     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "tst     %[v], #0xFF                \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF00              \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF0000            \n"
 | 
			
		||||
        "addne   %[l], %[l], #1             \n"
 | 
			
		||||
        "2:                                 \n"
 | 
			
		||||
        : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
 | 
			
		||||
        : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
 | 
			
		||||
        : "cc"
 | 
			
		||||
    );
 | 
			
		||||
    
 | 
			
		||||
done:
 | 
			
		||||
    return l;
 | 
			
		||||
}
 | 
			
		||||
@@ -26,16 +26,12 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <linux/err.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(syscall)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
    mov     r7, r0
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
    mov     r1, r2
 | 
			
		||||
@@ -43,9 +39,8 @@ ENTRY(syscall)
 | 
			
		||||
    ldmfd   ip, {r3, r4, r5, r6}
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
END(syscall)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								libc/arch-arm/bionic/tgkill.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libc/arch-arm/bionic/tgkill.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <linux/err.h>
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/* unlike our auto-generated syscall stubs, this code saves lr
 | 
			
		||||
   on the stack, as well as a few other registers. this makes
 | 
			
		||||
   our stack unwinder happy, when we generate debug stack
 | 
			
		||||
   traces after the C library or other parts of the system
 | 
			
		||||
   abort due to a fatal runtime error (e.g. detection
 | 
			
		||||
   of a corrupted malloc heap).
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
ENTRY(tgkill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_tgkill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
END(tgkill)
 | 
			
		||||
							
								
								
									
										50
									
								
								libc/arch-arm/bionic/tkill.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								libc/arch-arm/bionic/tkill.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <linux/err.h>
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/* unlike our auto-generated syscall stubs, this code saves lr
 | 
			
		||||
   on the stack, as well as a few other registers. this makes
 | 
			
		||||
   our stack unwinder happy, when we generate debug stack
 | 
			
		||||
   traces after the C library or other parts of the system
 | 
			
		||||
   abort due to a fatal runtime error (e.g. detection
 | 
			
		||||
   of a corrupted malloc heap).
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
ENTRY(tkill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_tkill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno
 | 
			
		||||
END(tkill)
 | 
			
		||||
@@ -1,216 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of src string, then get the source of the dst string.
 | 
			
		||||
// Check that the two lengths together don't exceed the threshold, then
 | 
			
		||||
// do a memcpy of the data.
 | 
			
		||||
ENTRY(__strcat_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    push    {r4, r5}
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
 | 
			
		||||
    // Save the dst register to r5
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Zero out r4
 | 
			
		||||
    eor     r4, r4, r4
 | 
			
		||||
 | 
			
		||||
    // r1 contains the address of the string to count.
 | 
			
		||||
.L_strlen_start:
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_update_count_and_finish:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub8_and_finish
 | 
			
		||||
    bcs     .L_sub7_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub6_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub8_and_finish:
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub7_and_finish:
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub6_and_finish:
 | 
			
		||||
    sub     r3, r3, #6
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub4_and_finish
 | 
			
		||||
    bcs     .L_sub3_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub2_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub4_and_finish:
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub3_and_finish:
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub2_and_finish:
 | 
			
		||||
    sub     r3, r3, #2
 | 
			
		||||
 | 
			
		||||
.L_finish:
 | 
			
		||||
    cmp     r4, #0
 | 
			
		||||
    bne     .L_strlen_done
 | 
			
		||||
 | 
			
		||||
    // Time to get the dst string length.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
 | 
			
		||||
    // Save the original source address to r5.
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Save the current length (adding 1 for the terminator).
 | 
			
		||||
    add     r4, r3, #1
 | 
			
		||||
    b       .L_strlen_start
 | 
			
		||||
 | 
			
		||||
    // r0 holds the pointer to the dst string.
 | 
			
		||||
    // r3 holds the dst string length.
 | 
			
		||||
    // r4 holds the src string length + 1.
 | 
			
		||||
.L_strlen_done:
 | 
			
		||||
    add     r2, r3, r4
 | 
			
		||||
    cmp     r2, lr
 | 
			
		||||
    bhi     __strcat_chk_failed
 | 
			
		||||
 | 
			
		||||
    // Set up the registers for the memcpy code.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    mov     r2, r4
 | 
			
		||||
    add     r0, r0, r3
 | 
			
		||||
    pop     {r4, r5}
 | 
			
		||||
END(__strcat_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcat_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
 | 
			
		||||
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcat_chk_failed)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcat_chk_failed)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcat: prevented write past end of buffer"
 | 
			
		||||
@@ -1,180 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of the source string first, then do a memcpy of the data
 | 
			
		||||
// instead of a strcpy.
 | 
			
		||||
ENTRY(__strcpy_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r0], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_update_count_and_finish:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub8_and_finish
 | 
			
		||||
    bcs     .L_sub7_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub6_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub8_and_finish:
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub7_and_finish:
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub6_and_finish:
 | 
			
		||||
    sub     r3, r3, #6
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub4_and_finish
 | 
			
		||||
    bcs     .L_sub3_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub2_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub4_and_finish:
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub3_and_finish:
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub2_and_finish:
 | 
			
		||||
    sub     r3, r3, #2
 | 
			
		||||
 | 
			
		||||
.L_check_size:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    ldr     r0, [sp]
 | 
			
		||||
    cmp     r3, lr
 | 
			
		||||
    bhs     __strcpy_chk_failed
 | 
			
		||||
 | 
			
		||||
    // Add 1 for copy length to get the string terminator.
 | 
			
		||||
    add     r2, r3, #1
 | 
			
		||||
END(__strcpy_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcpy_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcpy_chk_failed)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcpy_chk_failed)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcpy: prevented write past end of buffer"
 | 
			
		||||
@@ -25,79 +25,122 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Assumes neon instructions and a cache line size of 64 bytes. */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 * This code assumes it is running on a processor that supports all arm v7
 | 
			
		||||
 * instructions, that supports neon instructions, and that has a 64 byte
 | 
			
		||||
 * cache line.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .syntax unified
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp     r2, r3
 | 
			
		||||
        bhi     __memcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
        // Fall through to memcpy...
 | 
			
		||||
END(__memcpy_chk)
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        pld     [r1, #64]
 | 
			
		||||
        push    {r0, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*0)]
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*1)]
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 16-bytes to copy (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
        /* align destination to cache-line for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         0f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
 | 
			
		||||
0:      /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*1)]
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* Preload all the cache lines we need.
 | 
			
		||||
         * NOTE: The number of pld below depends on CACHE_LINE_SIZE,
 | 
			
		||||
         * ideally we would increase the distance in the main loop to
 | 
			
		||||
         * avoid the goofy code below. In practice this doesn't seem to make
 | 
			
		||||
         * a big difference.
 | 
			
		||||
         * NOTE: The value CACHE_LINE_SIZE * 4 was chosen through
 | 
			
		||||
         * experimentation.
 | 
			
		||||
         */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*3)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*4)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0  - d3},   [r1]!
 | 
			
		||||
        vld1.8      {d4  - d7},   [r1]!
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*4)]
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0  - d3},   [r0, :128]!
 | 
			
		||||
        vst1.8      {d4  - d7},   [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3},  [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3},  [r0, :128]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memcpy_chk_fail)
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push    {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr     r0, error_message
 | 
			
		||||
        ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add     r0, pc
 | 
			
		||||
        bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word   error_string-(1b+8)
 | 
			
		||||
END(__memcpy_chk_fail)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string "memcpy: prevented write past end of buffer"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,318 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        // Assumes that n >= 0, and dst, src are valid pointers.
 | 
			
		||||
        // For any sizes less than 832 use the neon code that doesn't
 | 
			
		||||
        // care about the src alignment. This avoids any checks
 | 
			
		||||
        // for src alignment, and offers the best improvement since
 | 
			
		||||
        // smaller sized copies are dominated by the overhead of
 | 
			
		||||
        // the pre and post main loop.
 | 
			
		||||
        // For larger copies, if src and dst cannot both be aligned to
 | 
			
		||||
        // word boundaries, use the neon code.
 | 
			
		||||
        // For all other copies, align dst to a double word boundary
 | 
			
		||||
        // and copy using LDRD/STRD instructions.
 | 
			
		||||
 | 
			
		||||
        cmp     r2, #16
 | 
			
		||||
        blo     .L_copy_less_than_16_unknown_align
 | 
			
		||||
 | 
			
		||||
        // TODO: The aligned copy code is extremely slow copying some large
 | 
			
		||||
        //       buffers so always go through the unaligned path for now.
 | 
			
		||||
        //cmp     r2, #832
 | 
			
		||||
        //bge     .L_check_alignment
 | 
			
		||||
 | 
			
		||||
.L_copy_unknown_alignment:
 | 
			
		||||
        // Unknown alignment of src and dst.
 | 
			
		||||
        // Assumes that the first few bytes have already been prefetched.
 | 
			
		||||
 | 
			
		||||
        // Align destination to 128 bits. The mainloop store instructions
 | 
			
		||||
        // require this alignment or they will throw an exception.
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        // Copy up to 15 bytes (count in r3).
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      lr, [r1], #1
 | 
			
		||||
        strbmi      lr, [r0], #1
 | 
			
		||||
        itttt       cs
 | 
			
		||||
        ldrbcs      ip, [r1], #1
 | 
			
		||||
        ldrbcs      lr, [r1], #1
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
 | 
			
		||||
2:      // Make sure we have at least 64 bytes to copy.
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
1:      // The main loop copies 64 bytes at a time.
 | 
			
		||||
        vld1.8      {d0  - d3},   [r1]!
 | 
			
		||||
        vld1.8      {d4  - d7},   [r1]!
 | 
			
		||||
        pld         [r1, #(64*4)]
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0  - d3},   [r0, :128]!
 | 
			
		||||
        vst1.8      {d4  - d7},   [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      // Fix-up the remaining count and make sure we have >= 32 bytes left.
 | 
			
		||||
        adds        r2, r2, #32
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        // 32 bytes. These cache lines were already preloaded.
 | 
			
		||||
        vld1.8      {d0 - d3},  [r1]!
 | 
			
		||||
        sub         r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3},  [r0, :128]!
 | 
			
		||||
3:      // Less than 32 left.
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         .L_copy_less_than_16_unknown_align
 | 
			
		||||
        // Copies 16 bytes, destination 128 bits aligned.
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
 | 
			
		||||
.L_copy_less_than_16_unknown_align:
 | 
			
		||||
        // Copy up to 15 bytes (count in r2).
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
 | 
			
		||||
 | 
			
		||||
2:      // Copy 0 to 4 bytes.
 | 
			
		||||
        lsls        r2, r2, #31
 | 
			
		||||
        itt         ne
 | 
			
		||||
        ldrbne      lr, [r1], #1
 | 
			
		||||
        strbne      lr, [r0], #1
 | 
			
		||||
        itttt       cs
 | 
			
		||||
        ldrbcs      ip, [r1], #1
 | 
			
		||||
        ldrbcs      lr, [r1]
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0]
 | 
			
		||||
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_check_alignment:
 | 
			
		||||
        // If src and dst cannot both be aligned to a word boundary,
 | 
			
		||||
        // use the unaligned copy version.
 | 
			
		||||
        eor     r3, r0, r1
 | 
			
		||||
        ands    r3, r3, #0x3
 | 
			
		||||
        bne     .L_copy_unknown_alignment
 | 
			
		||||
END(MEMCPY_BASE)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        // To try and improve performance, stack layout changed,
 | 
			
		||||
        // i.e., not keeping the stack looking like users expect
 | 
			
		||||
        // (highest numbered register at highest address).
 | 
			
		||||
        strd    r4, r5, [sp, #-8]!
 | 
			
		||||
        .cfi_adjust_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset r5, 4
 | 
			
		||||
        strd    r6, r7, [sp, #-8]!
 | 
			
		||||
        .cfi_adjust_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r6, 0
 | 
			
		||||
        .cfi_rel_offset r7, 0
 | 
			
		||||
        strd    r8, r9, [sp, #-8]!
 | 
			
		||||
        .cfi_adjust_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r8, 0
 | 
			
		||||
        .cfi_rel_offset r9, 4
 | 
			
		||||
 | 
			
		||||
        // Optimized for already aligned dst code.
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        bne     .L_dst_not_word_aligned
 | 
			
		||||
 | 
			
		||||
.L_word_aligned:
 | 
			
		||||
        // Align the destination buffer to 8 bytes, to make sure double
 | 
			
		||||
        // loads and stores don't cross a cache line boundary,
 | 
			
		||||
        // as they are then more expensive even if the data is in the cache
 | 
			
		||||
        // (require two load/store issue cycles instead of one).
 | 
			
		||||
        // If only one of the buffers is not 8 bytes aligned,
 | 
			
		||||
        // then it's more important to align dst than src,
 | 
			
		||||
        // because there is more penalty for stores
 | 
			
		||||
        // than loads that cross a cacheline boundary.
 | 
			
		||||
        // This check and realignment are only done if there is >= 832
 | 
			
		||||
        // bytes to copy.
 | 
			
		||||
 | 
			
		||||
        // Dst is word aligned, but check if it is already double word aligned.
 | 
			
		||||
        ands    r3, r0, #4
 | 
			
		||||
        beq     1f
 | 
			
		||||
        ldr     r3, [r1], #4
 | 
			
		||||
        str     r3, [r0], #4
 | 
			
		||||
        sub     r2, #4
 | 
			
		||||
 | 
			
		||||
1:      // Can only get here if > 64 bytes to copy, so don't do check r2.
 | 
			
		||||
        sub     r2, #64
 | 
			
		||||
 | 
			
		||||
2:      // Every loop iteration copies 64 bytes.
 | 
			
		||||
        .irp    offset, #0, #8, #16, #24, #32
 | 
			
		||||
        ldrd    r4, r5, [r1, \offset]
 | 
			
		||||
        strd    r4, r5, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
 | 
			
		||||
        ldrd    r4, r5, [r1, #40]
 | 
			
		||||
        ldrd    r6, r7, [r1, #48]
 | 
			
		||||
        ldrd    r8, r9, [r1, #56]
 | 
			
		||||
 | 
			
		||||
        // Keep the pld as far from the next load as possible.
 | 
			
		||||
        // The amount to prefetch was determined experimentally using
 | 
			
		||||
        // large sizes, and verifying the prefetch size does not affect
 | 
			
		||||
        // the smaller copies too much.
 | 
			
		||||
        // WARNING: If the ldrd and strd instructions get too far away
 | 
			
		||||
        //          from each other, performance suffers. Three loads
 | 
			
		||||
        //          in a row is the best tradeoff.
 | 
			
		||||
        pld     [r1, #(64*16)]
 | 
			
		||||
        strd    r4, r5, [r0, #40]
 | 
			
		||||
        strd    r6, r7, [r0, #48]
 | 
			
		||||
        strd    r8, r9, [r0, #56]
 | 
			
		||||
 | 
			
		||||
        add     r0, r0, #64
 | 
			
		||||
        add     r1, r1, #64
 | 
			
		||||
        subs    r2, r2, #64
 | 
			
		||||
        bge     2b
 | 
			
		||||
 | 
			
		||||
        // Fix-up the remaining count and make sure we have >= 32 bytes left.
 | 
			
		||||
        adds    r2, r2, #32
 | 
			
		||||
        blo     4f
 | 
			
		||||
 | 
			
		||||
        // Copy 32 bytes. These cache lines were already preloaded.
 | 
			
		||||
        .irp    offset, #0, #8, #16, #24
 | 
			
		||||
        ldrd    r4, r5, [r1, \offset]
 | 
			
		||||
        strd    r4, r5, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
        add     r1, r1, #32
 | 
			
		||||
        add     r0, r0, #32
 | 
			
		||||
        sub     r2, r2, #32
 | 
			
		||||
4:      // Less than 32 left.
 | 
			
		||||
        add     r2, r2, #32
 | 
			
		||||
        tst     r2, #0x10
 | 
			
		||||
        beq     5f
 | 
			
		||||
        // Copy 16 bytes.
 | 
			
		||||
        .irp    offset, #0, #8
 | 
			
		||||
        ldrd    r4, r5, [r1, \offset]
 | 
			
		||||
        strd    r4, r5, [r0, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
        add     r1, r1, #16
 | 
			
		||||
        add     r0, r0, #16
 | 
			
		||||
 | 
			
		||||
5:      // Copy up to 15 bytes (count in r2).
 | 
			
		||||
        movs    ip, r2, lsl #29
 | 
			
		||||
        bcc     1f
 | 
			
		||||
        // Copy 8 bytes.
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        strd    r4, r5, [r0], #8
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        // Copy 4 bytes.
 | 
			
		||||
        ldr     r4, [r1], #4
 | 
			
		||||
        str     r4, [r0], #4
 | 
			
		||||
2:      // Copy 0 to 4 bytes.
 | 
			
		||||
        lsls    r2, r2, #31
 | 
			
		||||
        itt     ne
 | 
			
		||||
        ldrbne  lr, [r1], #1
 | 
			
		||||
        strbne  lr, [r0], #1
 | 
			
		||||
        itttt   cs
 | 
			
		||||
        ldrbcs  ip, [r1], #1
 | 
			
		||||
        ldrbcs  lr, [r1]
 | 
			
		||||
        strbcs  ip, [r0], #1
 | 
			
		||||
        strbcs  lr, [r0]
 | 
			
		||||
 | 
			
		||||
        // Restore registers: optimized pop {r0, pc}
 | 
			
		||||
        ldrd    r8, r9, [sp], #8
 | 
			
		||||
        ldrd    r6, r7, [sp], #8
 | 
			
		||||
        ldrd    r4, r5, [sp], #8
 | 
			
		||||
        pop     {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_dst_not_word_aligned:
 | 
			
		||||
        // Align dst to word.
 | 
			
		||||
        rsb     ip, ip, #4
 | 
			
		||||
        cmp     ip, #2
 | 
			
		||||
 | 
			
		||||
        itt     gt
 | 
			
		||||
        ldrbgt  lr, [r1], #1
 | 
			
		||||
        strbgt  lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        itt     ge
 | 
			
		||||
        ldrbge  lr, [r1], #1
 | 
			
		||||
        strbge  lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldrb    lr, [r1], #1
 | 
			
		||||
        strb    lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        sub     r2, r2, ip
 | 
			
		||||
 | 
			
		||||
        // Src is guaranteed to be at least word aligned by this point.
 | 
			
		||||
        b       .L_word_aligned
 | 
			
		||||
END(MEMCPY_BASE_ALIGNED)
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -27,165 +27,80 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memset() for ARM.
 | 
			
		||||
		/*
 | 
			
		||||
		 * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
        .fpu        neon
 | 
			
		||||
        .syntax     unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         .L_done
 | 
			
		||||
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push        {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr         r0, error_message
 | 
			
		||||
        ldr         r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add         r0, pc
 | 
			
		||||
        bl          __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word       error_string-(1b+8)
 | 
			
		||||
END(__memset_chk)
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov         r2, r1
 | 
			
		||||
        mov         r1, #0
 | 
			
		||||
.L_done:
 | 
			
		||||
        mov     r2, r1
 | 
			
		||||
        mov     r1, #0
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        .save       {r0}
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
 | 
			
		||||
        // The new algorithm is slower for copies < 16 so use the old
 | 
			
		||||
        // neon code in that case.
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 16-bytes to write (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         .L_set_less_than_16_unknown_align
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        // Use strd which requires an even and odd register so move the
 | 
			
		||||
        // values so that:
 | 
			
		||||
        //   r0 and r1 contain the memset value
 | 
			
		||||
        //   r2 is the number of bytes to set
 | 
			
		||||
        //   r3 is the destination pointer
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        // Copy the byte value in every byte of r1.
 | 
			
		||||
        mov         r1, r1, lsl #24
 | 
			
		||||
        orr         r1, r1, r1, lsr #8
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
        /* write up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
 | 
			
		||||
.L_check_alignment:
 | 
			
		||||
        // Align destination to a double word to avoid the strd crossing
 | 
			
		||||
        // a cache line boundary.
 | 
			
		||||
        ands        ip, r3, #7
 | 
			
		||||
        bne         .L_do_double_word_align
 | 
			
		||||
        // writes 4 bytes, 32-bits aligned
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
 | 
			
		||||
.L_double_word_aligned:
 | 
			
		||||
        mov         r0, r1
 | 
			
		||||
        // writes 8 bytes, 64-bits aligned
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* make sure we have at least 32 bytes to write */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         2f
 | 
			
		||||
        vmov        q1, q0
 | 
			
		||||
 | 
			
		||||
        subs        r2, #64
 | 
			
		||||
        blo         .L_set_less_than_64
 | 
			
		||||
1:      /* The main loop writes 32 bytes at a time */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
1:      // Main loop sets 64 bytes at a time.
 | 
			
		||||
        .irp        offset, #0, #8, #16, #24, #32, #40, #48, #56
 | 
			
		||||
        strd        r0, r1, [r3, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
2:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        add         r3, #64
 | 
			
		||||
        subs        r2, #64
 | 
			
		||||
        bge         1b
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_64:
 | 
			
		||||
        // Restore r2 to the count of bytes left to set.
 | 
			
		||||
        add         r2, #64
 | 
			
		||||
        lsls        ip, r2, #27
 | 
			
		||||
        bcc         .L_set_less_than_32
 | 
			
		||||
        // Set 32 bytes.
 | 
			
		||||
        .irp        offset, #0, #8, #16, #24
 | 
			
		||||
        strd        r0, r1, [r3, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
        add         r3, #32
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_32:
 | 
			
		||||
        bpl         .L_set_less_than_16
 | 
			
		||||
        // Set 16 bytes.
 | 
			
		||||
        .irp        offset, #0, #8
 | 
			
		||||
        strd        r0, r1, [r3, \offset]
 | 
			
		||||
        .endr
 | 
			
		||||
        add         r3, #16
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_16:
 | 
			
		||||
        // Less than 16 bytes to set.
 | 
			
		||||
        lsls        ip, r2, #29
 | 
			
		||||
        bcc         .L_set_less_than_8
 | 
			
		||||
 | 
			
		||||
        // Set 8 bytes.
 | 
			
		||||
        strd        r0, r1, [r3], #8
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_8:
 | 
			
		||||
        bpl         .L_set_less_than_4
 | 
			
		||||
        // Set 4 bytes
 | 
			
		||||
        str         r1, [r3], #4
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_4:
 | 
			
		||||
        lsls        ip, r2, #31
 | 
			
		||||
        it          ne
 | 
			
		||||
        strbne      r1, [r3], #1
 | 
			
		||||
        itt         cs
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3]
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
.L_do_double_word_align:
 | 
			
		||||
        rsb         ip, ip, #8
 | 
			
		||||
        sub         r2, r2, ip
 | 
			
		||||
        movs        r0, ip, lsl #31
 | 
			
		||||
        it          mi
 | 
			
		||||
        strbmi      r1, [r3], #1
 | 
			
		||||
        itt         cs
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
 | 
			
		||||
        // Dst is at least word aligned by this point.
 | 
			
		||||
        cmp         ip, #4
 | 
			
		||||
        blo         .L_double_word_aligned
 | 
			
		||||
        str         r1, [r3], #4
 | 
			
		||||
        b           .L_double_word_aligned
 | 
			
		||||
 | 
			
		||||
.L_set_less_than_16_unknown_align:
 | 
			
		||||
        // Set up to 15 bytes.
 | 
			
		||||
        vdup.8      d0, r1
 | 
			
		||||
        // writes 16 bytes, 128-bits aligned
 | 
			
		||||
        vst1.8      {d0, d1}, [r0, :128]!
 | 
			
		||||
3:      /* write up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        it          mi
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        itt         cs
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memset: prevented write past end of buffer"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define STPCPY
 | 
			
		||||
#include "string_copy.S"
 | 
			
		||||
@@ -1,568 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r0, r4, r5, lr}
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
 | 
			
		||||
    .macro m_pop
 | 
			
		||||
    pop     {r0, r4, r5, pc}
 | 
			
		||||
    .endm // m_pop
 | 
			
		||||
 | 
			
		||||
    .macro m_scan_byte
 | 
			
		||||
    ldrb    r3, [r0]
 | 
			
		||||
    cbz     r3, strcat_r0_scan_done
 | 
			
		||||
    add     r0, #1
 | 
			
		||||
    .endm // m_scan_byte
 | 
			
		||||
 | 
			
		||||
    .macro m_copy_byte reg, cmd, label
 | 
			
		||||
    ldrb    \reg, [r1], #1
 | 
			
		||||
    strb    \reg, [r0], #1
 | 
			
		||||
    \cmd    \reg, \label
 | 
			
		||||
    .endm // m_copy_byte
 | 
			
		||||
 | 
			
		||||
ENTRY(strcat)
 | 
			
		||||
    // Quick check to see if src is empty.
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    cbnz    r2, strcat_continue
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
strcat_continue:
 | 
			
		||||
    // To speed up really small dst strings, unroll checking the first 4 bytes.
 | 
			
		||||
    m_push
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     strcat_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcat_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r5, [r0]
 | 
			
		||||
    cbz     r5, strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
 | 
			
		||||
strcat_align_to_32:
 | 
			
		||||
    bcc     strcat_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0]
 | 
			
		||||
    cbz     r2, strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
    ldrb    r4, [r0]
 | 
			
		||||
    cbz     r4, strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
 | 
			
		||||
strcat_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     strcat_mainloop
 | 
			
		||||
    ldr     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
 | 
			
		||||
strcat_r0_scan_done:
 | 
			
		||||
    // For short copies, hard-code checking the first 8 bytes since this
 | 
			
		||||
    // new code doesn't win until after about 8 bytes.
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
 | 
			
		||||
 | 
			
		||||
strcpy_finish:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_continue:
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     strcpy_check_src_align
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcpy_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
 | 
			
		||||
strcpy_align_to_32:
 | 
			
		||||
    bcc     strcpy_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
 | 
			
		||||
strcpy_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     strcpy_check_src_align
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
 | 
			
		||||
strcpy_check_src_align:
 | 
			
		||||
    // At this point dst is aligned to a double word, check if src
 | 
			
		||||
    // is also aligned to a double word.
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    bne     strcpy_unaligned_copy
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcpy_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_mainloop
 | 
			
		||||
 | 
			
		||||
strcpy_complete:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_first_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcpy_copy1byte
 | 
			
		||||
    bcs     strcpy_copy2bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcpy_copy3bytes
 | 
			
		||||
 | 
			
		||||
strcpy_copy4bytes:
 | 
			
		||||
    // Copy 4 bytes to the destiniation.
 | 
			
		||||
    str     r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy2bytes:
 | 
			
		||||
    strh    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy3bytes:
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r2, #16
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_second_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcpy_copy5bytes
 | 
			
		||||
    bcs     strcpy_copy6bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcpy_copy7bytes
 | 
			
		||||
 | 
			
		||||
    // Copy 8 bytes to the destination.
 | 
			
		||||
    strd    r2, r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strh    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r3, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unaligned_copy:
 | 
			
		||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
			
		||||
    // There are 7 different versions of the unaligned copy code
 | 
			
		||||
    // to prevent overreading the src. The mainloop of every single version
 | 
			
		||||
    // will store 64 bits per loop. The difference is how much of src can
 | 
			
		||||
    // be read without potentially crossing a page boundary.
 | 
			
		||||
    tbb     [pc, r3]
 | 
			
		||||
strcpy_unaligned_branchtable:
 | 
			
		||||
    .byte 0
 | 
			
		||||
    .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 7 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign7:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r3, [r1]
 | 
			
		||||
    cbz     r3, strcpy_unalign7_copy5bytes
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, strcpy_unalign7_copy6bytes
 | 
			
		||||
    ldrb    r5, [r1, #2]
 | 
			
		||||
    cbz     r5, strcpy_unalign7_copy7bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign7
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
strcpy_unalign_return:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0], #1
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 6 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign6:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
    ldrb    r5, [r1, #1]
 | 
			
		||||
    cbz     r5, strcpy_unalign_copy6bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r3, #0xff0000
 | 
			
		||||
    beq     strcpy_copy7bytes
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign6
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 5 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign5:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign5
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 4 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign4:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign4
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 3 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign3:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign3_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, strcpy_unalign3_copy2bytes
 | 
			
		||||
    ldrb    r4, [r1, #2]
 | 
			
		||||
    cbz     r4, strcpy_unalign3_copy3bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    lr, r2, #24
 | 
			
		||||
    beq     strcpy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign3
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy3bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 2 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign2:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy2bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r2, #0xff0000
 | 
			
		||||
    beq     strcpy_copy3bytes
 | 
			
		||||
    lsrs    ip, r2, #24
 | 
			
		||||
    beq     strcpy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign2
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 1 byte before possibly crossing a page.
 | 
			
		||||
strcpy_unalign1:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign1
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcat_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r0], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
 | 
			
		||||
strcat_zero_in_first_register:
 | 
			
		||||
    // Prefetch the src now, it's going to be used soon.
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcat_sub8
 | 
			
		||||
    bcs     strcat_sub7
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcat_sub6
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #5
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub8:
 | 
			
		||||
    sub     r0, r0, #8
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub7:
 | 
			
		||||
    sub     r0, r0, #7
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub6:
 | 
			
		||||
    sub     r0, r0, #6
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_zero_in_second_register:
 | 
			
		||||
    // Prefetch the src now, it's going to be used soon.
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcat_sub4
 | 
			
		||||
    bcs     strcat_sub3
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcat_sub2
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub4:
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub3:
 | 
			
		||||
    sub     r0, r0, #3
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub2:
 | 
			
		||||
    sub     r0, r0, #2
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
END(strcat)
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define S2LOMEM lsl
 | 
			
		||||
@@ -123,13 +123,8 @@ ENTRY(strcmp)
 | 
			
		||||
        .macro  init
 | 
			
		||||
        /* Macro to save temporary registers and prepare magic values.  */
 | 
			
		||||
        subs    sp, sp, #16
 | 
			
		||||
        .cfi_def_cfa_offset 16
 | 
			
		||||
        strd    r4, r5, [sp, #8]
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset r5, 4
 | 
			
		||||
        strd    r6, r7, [sp]
 | 
			
		||||
        .cfi_rel_offset r6, 8
 | 
			
		||||
        .cfi_rel_offset r7, 12
 | 
			
		||||
        mvn     r6, #0  /* all F */
 | 
			
		||||
        mov     r7, #0  /* all 0 */
 | 
			
		||||
        .endm   /* init */
 | 
			
		||||
@@ -145,8 +140,19 @@ ENTRY(strcmp)
 | 
			
		||||
 | 
			
		||||
        .macro  magic_find_zero_bytes w1
 | 
			
		||||
        /* Macro to find all-zero bytes in w1, result is in ip.  */
 | 
			
		||||
#if (defined (__ARM_FEATURE_DSP))
 | 
			
		||||
        uadd8   ip, \w1, r6
 | 
			
		||||
        sel     ip, r7, r6
 | 
			
		||||
#else /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        /* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
 | 
			
		||||
        Coincidently, these processors only have Thumb-2 mode, where we can use the
 | 
			
		||||
        the (large) magic constant available directly as an immediate in instructions.
 | 
			
		||||
        Note that we cannot use the magic constant in ARM mode, where we need
 | 
			
		||||
        to create the constant in a register.  */
 | 
			
		||||
        sub     ip, \w1, #0x01010101
 | 
			
		||||
        bic     ip, ip, \w1
 | 
			
		||||
        and     ip, ip, #0x80808080
 | 
			
		||||
#endif /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        .endm /* magic_find_zero_bytes */
 | 
			
		||||
 | 
			
		||||
        .macro  setup_return w1 w2
 | 
			
		||||
@@ -165,12 +171,12 @@ ENTRY(strcmp)
 | 
			
		||||
        /* Are both strings double-word aligned?  */
 | 
			
		||||
        orr     ip, r0, r1
 | 
			
		||||
        tst     ip, #7
 | 
			
		||||
        bne     .L_do_align
 | 
			
		||||
        bne     do_align
 | 
			
		||||
 | 
			
		||||
        /* Fast path.  */
 | 
			
		||||
        init
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned:
 | 
			
		||||
doubleword_aligned:
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are double-word aligned.  */
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
@@ -183,14 +189,14 @@ ENTRY(strcmp)
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
 | 
			
		||||
        magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
 | 
			
		||||
        magic_compare_and_branch w1=r2, w2=r4, label=return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=return_35
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
.L_do_align:
 | 
			
		||||
do_align:
 | 
			
		||||
        /* Is the first string word-aligned?  */
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        beq     .L_word_aligned_r0
 | 
			
		||||
        beq     word_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* Fast compare byte by byte until the first string is word-aligned.  */
 | 
			
		||||
        /* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
 | 
			
		||||
@@ -198,58 +204,58 @@ ENTRY(strcmp)
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        lsls    ip, ip, #31
 | 
			
		||||
        beq     .L_byte2
 | 
			
		||||
        bcs     .L_byte3
 | 
			
		||||
        beq     byte2
 | 
			
		||||
        bcs     byte3
 | 
			
		||||
 | 
			
		||||
.L_byte1:
 | 
			
		||||
byte1:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE1_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=.L_fast_return
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
.L_byte2:
 | 
			
		||||
byte2:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE2_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=.L_fast_return
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
.L_byte3:
 | 
			
		||||
byte3:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE3_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbnz  reg=r3, label=.L_word_aligned_r0
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbnz  reg=r3, label=word_aligned_r0
 | 
			
		||||
 | 
			
		||||
.L_fast_return:
 | 
			
		||||
fast_return:
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
.L_word_aligned_r0:
 | 
			
		||||
word_aligned_r0:
 | 
			
		||||
        init
 | 
			
		||||
        /* The first string is word-aligned.  */
 | 
			
		||||
        /* Is the second string word-aligned?  */
 | 
			
		||||
        ands    ip, r1, #3
 | 
			
		||||
        bne     .L_strcmp_unaligned
 | 
			
		||||
        bne     strcmp_unaligned
 | 
			
		||||
 | 
			
		||||
.L_word_aligned:
 | 
			
		||||
word_aligned:
 | 
			
		||||
        /* The strings are word-aligned. */
 | 
			
		||||
        /* Is the first string double-word aligned?  */
 | 
			
		||||
        tst     r0, #4
 | 
			
		||||
        beq     .L_doubleword_aligned_r0
 | 
			
		||||
        beq     doubleword_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* If r0 is not double-word aligned yet, align it by loading
 | 
			
		||||
        and comparing the next word from each string.  */
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        ldr     r4, [r1], #4
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r4 label=return_24
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned_r0:
 | 
			
		||||
doubleword_aligned_r0:
 | 
			
		||||
        /* Get here when r0 is double-word aligned.  */
 | 
			
		||||
        /* Is r1 doubleword_aligned?  */
 | 
			
		||||
        tst     r1, #4
 | 
			
		||||
        beq     .L_doubleword_aligned
 | 
			
		||||
        beq     doubleword_aligned
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are word-aligned,
 | 
			
		||||
        r0 is double-word aligned, but r1 is not double-word aligned.  */
 | 
			
		||||
@@ -265,9 +271,9 @@ ENTRY(strcmp)
 | 
			
		||||
 | 
			
		||||
        /* Load the next double-word from each string and compare.  */
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r5 label=return_25
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=return_34
 | 
			
		||||
        b       3b
 | 
			
		||||
 | 
			
		||||
        .macro miscmp_word offsetlo offsethi
 | 
			
		||||
@@ -291,47 +297,47 @@ ENTRY(strcmp)
 | 
			
		||||
        and     r2, r3, r6, S2LOMEM #\offsetlo
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r2, r5
 | 
			
		||||
        bne     .L_return_25
 | 
			
		||||
        bne     return_25
 | 
			
		||||
        ldr     r5, [r1], #4
 | 
			
		||||
        cmp     ip, #0
 | 
			
		||||
        eor r3, r2, r3
 | 
			
		||||
        S2HIMEM r2, r5, #\offsethi
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r3, r2
 | 
			
		||||
        bne     .L_return_32
 | 
			
		||||
        bne     return_32
 | 
			
		||||
        b       7b
 | 
			
		||||
        .endm /* miscmp_word */
 | 
			
		||||
 | 
			
		||||
.L_strcmp_unaligned:
 | 
			
		||||
strcmp_unaligned:
 | 
			
		||||
        /* r0 is word-aligned, r1 is at offset ip from a word.  */
 | 
			
		||||
        /* Align r1 to the (previous) word-boundary.  */
 | 
			
		||||
        bic     r1, r1, #3
 | 
			
		||||
 | 
			
		||||
        /* Unaligned comparison word by word using LDRs. */
 | 
			
		||||
        cmp     ip, #2
 | 
			
		||||
        beq     .L_miscmp_word_16                 /* If ip == 2.  */
 | 
			
		||||
        bge     .L_miscmp_word_24                 /* If ip == 3.  */
 | 
			
		||||
        beq     miscmp_word_16                    /* If ip == 2.  */
 | 
			
		||||
        bge     miscmp_word_24                    /* If ip == 3.  */
 | 
			
		||||
        miscmp_word offsetlo=8 offsethi=24        /* If ip == 1.  */
 | 
			
		||||
.L_miscmp_word_16:  miscmp_word offsetlo=16 offsethi=16
 | 
			
		||||
.L_miscmp_word_24:  miscmp_word offsetlo=24 offsethi=8
 | 
			
		||||
miscmp_word_16:  miscmp_word offsetlo=16 offsethi=16
 | 
			
		||||
miscmp_word_24:  miscmp_word offsetlo=24 offsethi=8
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.L_return_32:
 | 
			
		||||
return_32:
 | 
			
		||||
        setup_return w1=r3, w2=r2
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_34:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_34:
 | 
			
		||||
        setup_return w1=r3, w2=r4
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_25:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_25:
 | 
			
		||||
        setup_return w1=r2, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_35:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_35:
 | 
			
		||||
        setup_return w1=r3, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_24:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_24:
 | 
			
		||||
        setup_return w1=r2, w2=r4
 | 
			
		||||
 | 
			
		||||
.L_do_return:
 | 
			
		||||
do_return:
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
@@ -343,16 +349,11 @@ ENTRY(strcmp)
 | 
			
		||||
        ldrd    r6, r7, [sp]
 | 
			
		||||
        ldrd    r4, r5, [sp, #8]
 | 
			
		||||
        adds    sp, sp, #16
 | 
			
		||||
        .cfi_def_cfa_offset 0
 | 
			
		||||
        .cfi_restore r4
 | 
			
		||||
        .cfi_restore r5
 | 
			
		||||
        .cfi_restore r6
 | 
			
		||||
        .cfi_restore r7
 | 
			
		||||
 | 
			
		||||
        /* There is a zero or a different byte between r1 and r2.  */
 | 
			
		||||
        /* r0 contains a mask of all-zero bytes in r1.  */
 | 
			
		||||
        /* Using r0 and not ip here because cbz requires low register.  */
 | 
			
		||||
        m_cbz   reg=r0, label=.L_compute_return_value
 | 
			
		||||
        m_cbz   reg=r0, label=compute_return_value
 | 
			
		||||
        clz     r0, r0
 | 
			
		||||
        /* r0 contains the number of bits on the left of the first all-zero byte in r1.  */
 | 
			
		||||
        rsb     r0, r0, #24
 | 
			
		||||
@@ -360,7 +361,7 @@ ENTRY(strcmp)
 | 
			
		||||
        lsr     r1, r1, r0
 | 
			
		||||
        lsr     r2, r2, r0
 | 
			
		||||
 | 
			
		||||
.L_compute_return_value:
 | 
			
		||||
compute_return_value:
 | 
			
		||||
        movs    r0, #1
 | 
			
		||||
        cmp     r1, r2
 | 
			
		||||
        /* The return value is computed as follows.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define STRCPY
 | 
			
		||||
#include "string_copy.S"
 | 
			
		||||
@@ -1,513 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(STPCPY) && !defined(STRCPY)
 | 
			
		||||
#error "Either STPCPY or STRCPY must be defined."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r4, r5, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 12
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset lr, 8
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
#else
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r0, r4, r5, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset r4, 4
 | 
			
		||||
    .cfi_rel_offset r5, 8
 | 
			
		||||
    .cfi_rel_offset lr, 12
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    .macro m_pop
 | 
			
		||||
    pop     {r4, r5, pc}
 | 
			
		||||
    .endm // m_pop
 | 
			
		||||
#else
 | 
			
		||||
    .macro m_pop
 | 
			
		||||
    pop     {r0, r4, r5, pc}
 | 
			
		||||
    .endm // m_pop
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    .macro m_copy_byte reg, cmd, label
 | 
			
		||||
    ldrb    \reg, [r1], #1
 | 
			
		||||
    strb    \reg, [r0], #1
 | 
			
		||||
    \cmd    \reg, \label
 | 
			
		||||
    .endm // m_copy_byte
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
ENTRY(stpcpy)
 | 
			
		||||
#else
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
#endif
 | 
			
		||||
    // For short copies, hard-code checking the first 8 bytes since this
 | 
			
		||||
    // new code doesn't win until after about 8 bytes.
 | 
			
		||||
    m_push
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=.Lstringcopy_continue
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_finish:
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_continue:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     .Lstringcopy_check_src_align
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .Lstringcopy_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .Lstringcopy_complete
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_align_to_32:
 | 
			
		||||
    bcc     .Lstringcopy_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .Lstringcopy_complete
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .Lstringcopy_complete
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .Lstringcopy_check_src_align
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_check_src_align:
 | 
			
		||||
    // At this point dst is aligned to a double word, check if src
 | 
			
		||||
    // is also aligned to a double word.
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    bne     .Lstringcopy_unaligned_copy
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.Lstringcopy_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_mainloop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_complete:
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_zero_in_first_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     .Lstringcopy_copy1byte
 | 
			
		||||
    bcs     .Lstringcopy_copy2bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .Lstringcopy_copy3bytes
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy4bytes:
 | 
			
		||||
    // Copy 4 bytes to the destiniation.
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    str     r2, [r0], #3
 | 
			
		||||
#else
 | 
			
		||||
    str     r2, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy2bytes:
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    strh    r2, [r0], #1
 | 
			
		||||
#else
 | 
			
		||||
    strh    r2, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy3bytes:
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r2, #16
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_zero_in_second_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     .Lstringcopy_copy5bytes
 | 
			
		||||
    bcs     .Lstringcopy_copy6bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .Lstringcopy_copy7bytes
 | 
			
		||||
 | 
			
		||||
    // Copy 8 bytes to the destination.
 | 
			
		||||
    strd    r2, r3, [r0]
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    add     r0, r0, #7
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    strh    r3, [r0], #1
 | 
			
		||||
#else
 | 
			
		||||
    strh    r3, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r3, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unaligned_copy:
 | 
			
		||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
			
		||||
    // There are 7 different versions of the unaligned copy code
 | 
			
		||||
    // to prevent overreading the src. The mainloop of every single version
 | 
			
		||||
    // will store 64 bits per loop. The difference is how much of src can
 | 
			
		||||
    // be read without potentially crossing a page boundary.
 | 
			
		||||
    tbb     [pc, r3]
 | 
			
		||||
.Lstringcopy_unaligned_branchtable:
 | 
			
		||||
    .byte 0
 | 
			
		||||
    .byte ((.Lstringcopy_unalign7 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign6 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign5 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign4 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign3 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign2 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign1 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 7 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign7:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r3, [r1]
 | 
			
		||||
    cbz     r3, .Lstringcopy_unalign7_copy5bytes
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign7_copy6bytes
 | 
			
		||||
    ldrb    r5, [r1, #2]
 | 
			
		||||
    cbz     r5, .Lstringcopy_unalign7_copy7bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    beq     .Lstringcopy_finish
 | 
			
		||||
#else
 | 
			
		||||
    beq     .Lstringcopy_unalign_return
 | 
			
		||||
#endif
 | 
			
		||||
    b       .Lstringcopy_unalign7
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
.Lstringcopy_unalign_return:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 6 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign6:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign_copy5bytes
 | 
			
		||||
    ldrb    r5, [r1, #1]
 | 
			
		||||
    cbz     r5, .Lstringcopy_unalign_copy6bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r3, #0xff0000
 | 
			
		||||
    beq     .Lstringcopy_copy7bytes
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    beq     .Lstringcopy_finish
 | 
			
		||||
#else
 | 
			
		||||
    beq     .Lstringcopy_unalign_return
 | 
			
		||||
#endif
 | 
			
		||||
    b       .Lstringcopy_unalign6
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 5 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign5:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign_copy5bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_unalign5
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 4 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign4:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_unalign4
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 3 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign3:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign3_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, .Lstringcopy_unalign3_copy2bytes
 | 
			
		||||
    ldrb    r4, [r1, #2]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign3_copy3bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    lr, r2, #24
 | 
			
		||||
    beq     .Lstringcopy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_unalign3
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy3bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 2 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign2:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign_copy1byte
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign_copy2bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r2, #0xff0000
 | 
			
		||||
    beq     .Lstringcopy_copy3bytes
 | 
			
		||||
    lsrs    ip, r2, #24
 | 
			
		||||
    beq     .Lstringcopy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_unalign2
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 1 byte before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign1:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign_copy1byte
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       .Lstringcopy_unalign1
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
END(stpcpy)
 | 
			
		||||
#else
 | 
			
		||||
END(strcpy)
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,165 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
ENTRY(strlen)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    mov     r1, r0
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, update_count_and_return
 | 
			
		||||
 | 
			
		||||
align_to_32:
 | 
			
		||||
    bcc     align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, update_count_and_return
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, update_count_and_return
 | 
			
		||||
 | 
			
		||||
align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     mainloop
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
    b       mainloop
 | 
			
		||||
 | 
			
		||||
update_count_and_return:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
zero_in_first_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    lsls    r3, ip, #17
 | 
			
		||||
    bne     sub8_and_return
 | 
			
		||||
    bcs     sub7_and_return
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     sub6_and_return
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #5
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub8_and_return:
 | 
			
		||||
    sub     r0, r0, #8
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub7_and_return:
 | 
			
		||||
    sub     r0, r0, #7
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub6_and_return:
 | 
			
		||||
    sub     r0, r0, #6
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
zero_in_second_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    lsls    r3, ip, #17
 | 
			
		||||
    bne     sub4_and_return
 | 
			
		||||
    bcs     sub3_and_return
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     sub2_and_return
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub4_and_return:
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub3_and_return:
 | 
			
		||||
    sub     r0, r0, #3
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub2_and_return:
 | 
			
		||||
    sub     r0, r0, #2
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(strlen)
 | 
			
		||||
@@ -1,16 +1,5 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/memset.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/stpcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcat.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/__strcat_chk.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/__strcpy_chk.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strlen.S \
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a15/bionic/memcpy.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a15/bionic/memset.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a15/bionic/strcmp.S)
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
include bionic/libc/arch-arm/generic/generic.mk
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm/cortex-a15/cortex-a15.mk
 | 
			
		||||
@@ -1,220 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of src string, then get the source of the dst string.
 | 
			
		||||
// Check that the two lengths together don't exceed the threshold, then
 | 
			
		||||
// do a memcpy of the data.
 | 
			
		||||
ENTRY(__strcat_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    push    {r4, r5}
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
 | 
			
		||||
    // Save the dst register to r5
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Zero out r4
 | 
			
		||||
    eor     r4, r4, r4
 | 
			
		||||
 | 
			
		||||
    // r1 contains the address of the string to count.
 | 
			
		||||
.L_strlen_start:
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     .L_align_src
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldmia   r1!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     .L_check_byte1_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_check_byte1_reg1:
 | 
			
		||||
    bcc     .L_check_byte2_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_check_byte2_reg1:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r3, r3, #6
 | 
			
		||||
    bne     .L_finish
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     .L_check_byte1_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_check_byte1_reg2:
 | 
			
		||||
    bcc     .L_check_byte2_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_check_byte2_reg2:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r3, r3, #2
 | 
			
		||||
    bne     .L_finish
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_align_src:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_done:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
 | 
			
		||||
.L_finish:
 | 
			
		||||
    cmp     r4, #0
 | 
			
		||||
    bne     .L_strlen_done
 | 
			
		||||
 | 
			
		||||
    // Time to get the dst string length.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
 | 
			
		||||
    // Save the original source address to r5.
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Save the current length (adding 1 for the terminator).
 | 
			
		||||
    add     r4, r3, #1
 | 
			
		||||
    b       .L_strlen_start
 | 
			
		||||
 | 
			
		||||
    // r0 holds the pointer to the dst string.
 | 
			
		||||
    // r3 holds the dst string length.
 | 
			
		||||
    // r4 holds the src string length + 1.
 | 
			
		||||
.L_strlen_done:
 | 
			
		||||
    add     r2, r3, r4
 | 
			
		||||
    cmp     r2, lr
 | 
			
		||||
    bhi     __strcat_chk_fail
 | 
			
		||||
 | 
			
		||||
    // Set up the registers for the memcpy code.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    mov     r2, r4
 | 
			
		||||
    add     r0, r0, r3
 | 
			
		||||
    pop     {r4, r5}
 | 
			
		||||
 | 
			
		||||
    // Fall through into the memcpy_base function.
 | 
			
		||||
END(__strcat_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcat_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcat_chk_fail)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcat_chk_fail)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcat: prevented write past end of buffer"
 | 
			
		||||
@@ -1,185 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of the source string first, then do a memcpy of the data
 | 
			
		||||
// instead of a strcpy.
 | 
			
		||||
ENTRY(__strcpy_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     .L_align_src
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldmia   r0!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     .L_check_byte1_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_check_byte1_reg1:
 | 
			
		||||
    bcc     .L_check_byte2_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_check_byte2_reg1:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r3, r3, #6
 | 
			
		||||
    bne     .L_check_size
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     .L_check_byte1_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_check_byte1_reg2:
 | 
			
		||||
    bcc     .L_check_byte2_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_check_byte2_reg2:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r3, r3, #2
 | 
			
		||||
    bne     .L_check_size
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_align_src:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_done
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r2, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_done:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
 | 
			
		||||
.L_check_size:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    ldr     r0, [sp]
 | 
			
		||||
    cmp     r3, lr
 | 
			
		||||
    bhs     __strcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
    // Add 1 for copy length to get the string terminator.
 | 
			
		||||
    add     r2, r3, #1
 | 
			
		||||
 | 
			
		||||
    // Fall through into the memcpy_base function.
 | 
			
		||||
END(__strcpy_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcpy_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcpy_chk_fail)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcpy_chk_fail)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcpy: prevented write past end of buffer"
 | 
			
		||||
@@ -26,8 +26,8 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This code assumes it is running on a processor that supports all arm v7
 | 
			
		||||
@@ -35,48 +35,177 @@
 | 
			
		||||
 * cache line.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
        .syntax unified
 | 
			
		||||
        .text
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
        .thumb
 | 
			
		||||
        .thumb_func
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
        // Fall through to memcpy...
 | 
			
		||||
END(__memcpy_chk)
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        pld     [r1, #0]
 | 
			
		||||
        stmfd   sp!, {r0, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
        pld     [r1, #64]
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        // Check so divider is at least 16 bytes, needed for alignment code.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
        cmp         r2, #224
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
3:
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 4)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 6)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 6)]
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
11:
 | 
			
		||||
        /* Simple arm-only copy loop to handle aligned copy operations */
 | 
			
		||||
        stmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 4)]
 | 
			
		||||
 | 
			
		||||
        /* Check alignment */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, #3
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
         * stall 2 cycles.
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r5, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r5, [r0], #1
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blt         4f
 | 
			
		||||
 | 
			
		||||
3:      /* Main copy loop, copying 64 bytes at a time */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 8)]
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        bge         3b
 | 
			
		||||
 | 
			
		||||
4:      /* Check if there are > 32 bytes left */
 | 
			
		||||
        adds        r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blt         5f
 | 
			
		||||
 | 
			
		||||
        /* Copy 32 bytes */
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, #32
 | 
			
		||||
 | 
			
		||||
5:      /* Handle any remaining bytes */
 | 
			
		||||
        adds        r2, #32
 | 
			
		||||
        beq         6f
 | 
			
		||||
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r3, r4, r5, r6}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r7, r8}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r3, r4, r5, r6}
 | 
			
		||||
        stmmiia     r0!, {r7, r8}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
6:
 | 
			
		||||
        ldmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memcpy_chk_fail)
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push    {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr     r0, error_message
 | 
			
		||||
        ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add     r0, pc
 | 
			
		||||
        bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word   error_string-(1b+4)
 | 
			
		||||
END(__memcpy_chk_fail)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memcpy: prevented write past end of buffer"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,223 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This code assumes it is running on a processor that supports all arm v7
 | 
			
		||||
 * instructions, that supports neon instructions, and that has a 32 byte
 | 
			
		||||
 * cache line.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        // Check so divider is at least 16 bytes, needed for alignment code.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         __memcpy_base_aligned
 | 
			
		||||
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
        cmp         r2, #224
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      lr, [r1], #1
 | 
			
		||||
        strbmi      lr, [r0], #1
 | 
			
		||||
        itttt       cs
 | 
			
		||||
        ldrbcs      ip, [r1], #1
 | 
			
		||||
        ldrbcs      lr, [r1], #1
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #0]
 | 
			
		||||
        pld         [r1, #(32 * 2)]
 | 
			
		||||
3:
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need */
 | 
			
		||||
        pld         [r1, #(32 * 4)]
 | 
			
		||||
        pld         [r1, #(32 * 6)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
        pld         [r1, #(32 * 6)]
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        itttt       cs
 | 
			
		||||
        ldrbcs      ip, [r1], #1
 | 
			
		||||
        ldrbcs      lr, [r1], #1
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(MEMCPY_BASE)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        /* Simple arm-only copy loop to handle aligned copy operations */
 | 
			
		||||
        stmfd       sp!, {r4-r8}
 | 
			
		||||
        .cfi_adjust_cfa_offset 20
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset r5, 4
 | 
			
		||||
        .cfi_rel_offset r6, 8
 | 
			
		||||
        .cfi_rel_offset r7, 12
 | 
			
		||||
        .cfi_rel_offset r8, 16
 | 
			
		||||
        pld         [r1, #(32 * 4)]
 | 
			
		||||
 | 
			
		||||
        /* Check alignment */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, #3
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
         * stall 2 cycles.
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        itttt       cs
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r5, [r1], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r5, [r0], #1
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blt         4f
 | 
			
		||||
 | 
			
		||||
3:      /* Main copy loop, copying 64 bytes at a time */
 | 
			
		||||
        pld         [r1, #(32 * 8)]
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        bge         3b
 | 
			
		||||
 | 
			
		||||
4:      /* Check if there are > 32 bytes left */
 | 
			
		||||
        adds        r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blt         5f
 | 
			
		||||
 | 
			
		||||
        /* Copy 32 bytes */
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, #32
 | 
			
		||||
 | 
			
		||||
5:      /* Handle any remaining bytes */
 | 
			
		||||
        adds        r2, #32
 | 
			
		||||
        beq         6f
 | 
			
		||||
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        itt         cs
 | 
			
		||||
        ldmiacs     r1!, {r3, r4, r5, r6}   /* 16 bytes */
 | 
			
		||||
        stmiacs     r0!, {r3, r4, r5, r6}
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldmiami     r1!, {r7, r8}           /*  8 bytes */
 | 
			
		||||
        stmiami     r0!, {r7, r8}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        itt         cs
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        itt         ne
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
6:
 | 
			
		||||
        ldmfd       sp!, {r4-r8}
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(MEMCPY_BASE_ALIGNED)
 | 
			
		||||
@@ -26,8 +26,8 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This code assumes it is running on a processor that supports all arm v7
 | 
			
		||||
@@ -35,45 +35,20 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         .L_done
 | 
			
		||||
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push        {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr         r0, error_message
 | 
			
		||||
        ldr         r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add         r0, pc
 | 
			
		||||
        bl          __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word       error_string-(1b+8)
 | 
			
		||||
END(__memset_chk)
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov     r2, r1
 | 
			
		||||
        mov     r1, #0
 | 
			
		||||
 | 
			
		||||
.L_done:
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
/* memset() returns its first argument.  */
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        // The neon memset only wins for less than 132.
 | 
			
		||||
        # The neon memset only wins for less than 132.
 | 
			
		||||
        cmp         r2, #132
 | 
			
		||||
        bhi         __memset_large_copy
 | 
			
		||||
        bhi         11f
 | 
			
		||||
 | 
			
		||||
        .save       {r0}
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
@@ -101,26 +76,18 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
11:
 | 
			
		||||
        /* compute the offset to align the destination
 | 
			
		||||
         * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
         */
 | 
			
		||||
        stmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 24
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset r4, 4
 | 
			
		||||
        .cfi_rel_offset r5, 8
 | 
			
		||||
        .cfi_rel_offset r6, 12
 | 
			
		||||
        .cfi_rel_offset r7, 16
 | 
			
		||||
        .cfi_rel_offset lr, 20
 | 
			
		||||
 | 
			
		||||
        .save       {r0, r4-r7, lr}
 | 
			
		||||
        stmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #3
 | 
			
		||||
        cmp         r3, r2
 | 
			
		||||
@@ -132,11 +99,11 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -156,9 +123,9 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -173,17 +140,13 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memset: prevented write past end of buffer"
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define STPCPY
 | 
			
		||||
#include "string_copy.S"
 | 
			
		||||
@@ -1,548 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r0, r4, r5, lr}
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
 | 
			
		||||
    .macro m_ret inst
 | 
			
		||||
    \inst   {r0, r4, r5, pc}
 | 
			
		||||
    .endm // m_ret
 | 
			
		||||
 | 
			
		||||
    .macro m_scan_byte
 | 
			
		||||
    ldrb    r3, [r0]
 | 
			
		||||
    cbz     r3, strcat_r0_scan_done
 | 
			
		||||
    add     r0, #1
 | 
			
		||||
    .endm // m_scan_byte
 | 
			
		||||
 | 
			
		||||
    .macro m_copy_byte reg, cmd, label
 | 
			
		||||
    ldrb    \reg, [r1], #1
 | 
			
		||||
    strb    \reg, [r0], #1
 | 
			
		||||
    \cmd    \reg, \label
 | 
			
		||||
    .endm // m_copy_byte
 | 
			
		||||
 | 
			
		||||
ENTRY(strcat)
 | 
			
		||||
    // Quick check to see if src is empty.
 | 
			
		||||
    ldrb        r2, [r1]
 | 
			
		||||
    pld         [r1, #0]
 | 
			
		||||
    cbnz        r2, strcat_continue
 | 
			
		||||
    bx          lr
 | 
			
		||||
 | 
			
		||||
strcat_continue:
 | 
			
		||||
    // To speed up really small dst strings, unroll checking the first 4 bytes.
 | 
			
		||||
    m_push
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     strcat_align_src
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcat_mainloop:
 | 
			
		||||
    ldmia   r0!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
 | 
			
		||||
strcat_zero_in_first_register:
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
 | 
			
		||||
strcat_zero_in_second_register:
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    tst     ip, #0x80
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r0, r0, #4
 | 
			
		||||
    bne     strcat_r0_scan_done
 | 
			
		||||
    // Check for zero in byte 1.
 | 
			
		||||
    tst     ip, #0x8000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r0, r0, #3
 | 
			
		||||
    bne     strcat_r0_scan_done
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    it      ne
 | 
			
		||||
    subne   r0, r0, #2
 | 
			
		||||
    it      eq
 | 
			
		||||
    // Zero is in byte 3.
 | 
			
		||||
    subeq   r0, r0, #1
 | 
			
		||||
 | 
			
		||||
strcat_r0_scan_done:
 | 
			
		||||
    // Unroll the first 8 bytes that will be copied.
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
 | 
			
		||||
 | 
			
		||||
strcpy_finish:
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_continue:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     strcpy_align_dst
 | 
			
		||||
 | 
			
		||||
strcpy_check_src_align:
 | 
			
		||||
    // At this point dst is aligned to a double word, check if src
 | 
			
		||||
    // is also aligned to a double word.
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    bne     strcpy_unaligned_copy
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcpy_mainloop:
 | 
			
		||||
    ldmia   r1!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_mainloop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_first_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    itt     ne
 | 
			
		||||
    strbne  r2, [r0]
 | 
			
		||||
    m_ret   inst=popne
 | 
			
		||||
    itt     cs
 | 
			
		||||
    strhcs  r2, [r0]
 | 
			
		||||
    m_ret   inst=popcs
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    itt     eq
 | 
			
		||||
    streq   r2, [r0]
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r3, r2, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_second_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    ittt    ne
 | 
			
		||||
    stmiane r0!, {r2}
 | 
			
		||||
    strbne  r3, [r0]
 | 
			
		||||
    m_ret   inst=popne
 | 
			
		||||
    ittt    cs
 | 
			
		||||
    strcs   r2, [r0], #4
 | 
			
		||||
    strhcs  r3, [r0]
 | 
			
		||||
    m_ret   inst=popcs
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    itt     eq
 | 
			
		||||
    stmiaeq r0, {r2, r3}
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r4, r3, #16
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_align_dst:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcpy_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
 | 
			
		||||
strcpy_align_to_32:
 | 
			
		||||
    bcc     strcpy_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    cmp     r4, #0
 | 
			
		||||
    it      eq
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    ldrb    r5, [r1], #1
 | 
			
		||||
    strb    r5, [r0], #1
 | 
			
		||||
    cmp     r5, #0
 | 
			
		||||
    it      eq
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
 | 
			
		||||
strcpy_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     strcpy_check_src_align
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    b       strcpy_check_src_align
 | 
			
		||||
 | 
			
		||||
strcpy_complete:
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unaligned_copy:
 | 
			
		||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
			
		||||
    // There are 7 different versions of the unaligned copy code
 | 
			
		||||
    // to prevent overreading the src. The mainloop of every single version
 | 
			
		||||
    // will store 64 bits per loop. The difference is how much of src can
 | 
			
		||||
    // be read without potentially crossing a page boundary.
 | 
			
		||||
    tbb     [pc, r3]
 | 
			
		||||
strcpy_unaligned_branchtable:
 | 
			
		||||
    .byte 0
 | 
			
		||||
    .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 7 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign7:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r3, [r1]
 | 
			
		||||
    cbz     r3, strcpy_unalign7_copy5bytes
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, strcpy_unalign7_copy6bytes
 | 
			
		||||
    ldrb    r5, [r1, #2]
 | 
			
		||||
    cbz     r5, strcpy_unalign7_copy7bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign7
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy5bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
strcpy_unalign_return:
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy6bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy7bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0], #1
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 6 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign6:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
    ldrb    r5, [r1, #1]
 | 
			
		||||
    cbz     r5, strcpy_unalign_copy6bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r3, #0xff0000
 | 
			
		||||
    beq     strcpy_unalign6_copy7bytes
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign6
 | 
			
		||||
 | 
			
		||||
strcpy_unalign6_copy7bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r3, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 5 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign5:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_unalign5
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy5bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy6bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 4 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign4:
 | 
			
		||||
    ldmia   r1!, {r2}
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldmia   r1!, {r3}
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_unalign4
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 3 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign3:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign3_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, strcpy_unalign3_copy2bytes
 | 
			
		||||
    ldrb    r4, [r1, #2]
 | 
			
		||||
    cbz     r4, strcpy_unalign3_copy3bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    lr, r2, #24
 | 
			
		||||
    beq     strcpy_unalign_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_unalign3
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy3bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 2 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign2:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, strcpy_unalign_copy2bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r2, #0xff0000
 | 
			
		||||
    beq     strcpy_unalign_copy3bytes
 | 
			
		||||
    lsrs    ip, r2, #24
 | 
			
		||||
    beq     strcpy_unalign_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_unalign2
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 1 byte before possibly crossing a page.
 | 
			
		||||
strcpy_unalign1:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       strcpy_unalign1
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy3bytes:
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r2, #16
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy4bytes:
 | 
			
		||||
    stmia   r0, {r2}
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
strcat_align_src:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcat_align_to_32
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcat_r0_update
 | 
			
		||||
 | 
			
		||||
strcat_align_to_32:
 | 
			
		||||
    bcc     strcat_align_to_64
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcat_r0_update
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcat_r0_update
 | 
			
		||||
 | 
			
		||||
strcat_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     strcat_mainloop
 | 
			
		||||
    ldr     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
 | 
			
		||||
strcat_r0_update:
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    b strcat_r0_scan_done
 | 
			
		||||
END(strcat)
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define S2LOMEM lsl
 | 
			
		||||
@@ -123,13 +123,8 @@ ENTRY(strcmp)
 | 
			
		||||
        .macro  init
 | 
			
		||||
        /* Macro to save temporary registers and prepare magic values.  */
 | 
			
		||||
        subs    sp, sp, #16
 | 
			
		||||
        .cfi_def_cfa_offset 16
 | 
			
		||||
        strd    r4, r5, [sp, #8]
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset r5, 4
 | 
			
		||||
        strd    r6, r7, [sp]
 | 
			
		||||
        .cfi_rel_offset r6, 8
 | 
			
		||||
        .cfi_rel_offset r7, 12
 | 
			
		||||
        mvn     r6, #0  /* all F */
 | 
			
		||||
        mov     r7, #0  /* all 0 */
 | 
			
		||||
        .endm   /* init */
 | 
			
		||||
@@ -145,8 +140,19 @@ ENTRY(strcmp)
 | 
			
		||||
 | 
			
		||||
        .macro  magic_find_zero_bytes w1
 | 
			
		||||
        /* Macro to find all-zero bytes in w1, result is in ip.  */
 | 
			
		||||
#if (defined (__ARM_FEATURE_DSP))
 | 
			
		||||
        uadd8   ip, \w1, r6
 | 
			
		||||
        sel     ip, r7, r6
 | 
			
		||||
#else /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        /* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
 | 
			
		||||
        Coincidently, these processors only have Thumb-2 mode, where we can use the
 | 
			
		||||
        the (large) magic constant available directly as an immediate in instructions.
 | 
			
		||||
        Note that we cannot use the magic constant in ARM mode, where we need
 | 
			
		||||
        to create the constant in a register.  */
 | 
			
		||||
        sub     ip, \w1, #0x01010101
 | 
			
		||||
        bic     ip, ip, \w1
 | 
			
		||||
        and     ip, ip, #0x80808080
 | 
			
		||||
#endif /* not defined (__ARM_FEATURE_DSP) */
 | 
			
		||||
        .endm /* magic_find_zero_bytes */
 | 
			
		||||
 | 
			
		||||
        .macro  setup_return w1 w2
 | 
			
		||||
@@ -165,12 +171,12 @@ ENTRY(strcmp)
 | 
			
		||||
        /* Are both strings double-word aligned?  */
 | 
			
		||||
        orr     ip, r0, r1
 | 
			
		||||
        tst     ip, #7
 | 
			
		||||
        bne     .L_do_align
 | 
			
		||||
        bne     do_align
 | 
			
		||||
 | 
			
		||||
        /* Fast path.  */
 | 
			
		||||
        init
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned:
 | 
			
		||||
doubleword_aligned:
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are double-word aligned.  */
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
@@ -183,14 +189,14 @@ ENTRY(strcmp)
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
 | 
			
		||||
        magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
 | 
			
		||||
        magic_compare_and_branch w1=r2, w2=r4, label=return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=return_35
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
.L_do_align:
 | 
			
		||||
do_align:
 | 
			
		||||
        /* Is the first string word-aligned?  */
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        beq     .L_word_aligned_r0
 | 
			
		||||
        beq     word_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* Fast compare byte by byte until the first string is word-aligned.  */
 | 
			
		||||
        /* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
 | 
			
		||||
@@ -198,58 +204,58 @@ ENTRY(strcmp)
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        lsls    ip, ip, #31
 | 
			
		||||
        beq     .L_byte2
 | 
			
		||||
        bcs     .L_byte3
 | 
			
		||||
        beq     byte2
 | 
			
		||||
        bcs     byte3
 | 
			
		||||
 | 
			
		||||
.L_byte1:
 | 
			
		||||
byte1:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE1_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=.L_fast_return
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
.L_byte2:
 | 
			
		||||
byte2:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE2_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=.L_fast_return
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbz   reg=r3, label=fast_return
 | 
			
		||||
 | 
			
		||||
.L_byte3:
 | 
			
		||||
byte3:
 | 
			
		||||
        ldrb    ip, [r1], #1
 | 
			
		||||
        uxtb    r3, r2, ror #BYTE3_OFFSET
 | 
			
		||||
        subs    ip, r3, ip
 | 
			
		||||
        bne     .L_fast_return
 | 
			
		||||
        m_cbnz  reg=r3, label=.L_word_aligned_r0
 | 
			
		||||
        bne     fast_return
 | 
			
		||||
        m_cbnz  reg=r3, label=word_aligned_r0
 | 
			
		||||
 | 
			
		||||
.L_fast_return:
 | 
			
		||||
fast_return:
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
.L_word_aligned_r0:
 | 
			
		||||
word_aligned_r0:
 | 
			
		||||
        init
 | 
			
		||||
        /* The first string is word-aligned.  */
 | 
			
		||||
        /* Is the second string word-aligned?  */
 | 
			
		||||
        ands    ip, r1, #3
 | 
			
		||||
        bne     .L_strcmp_unaligned
 | 
			
		||||
        bne     strcmp_unaligned
 | 
			
		||||
 | 
			
		||||
.L_word_aligned:
 | 
			
		||||
word_aligned:
 | 
			
		||||
        /* The strings are word-aligned. */
 | 
			
		||||
        /* Is the first string double-word aligned?  */
 | 
			
		||||
        tst     r0, #4
 | 
			
		||||
        beq     .L_doubleword_aligned_r0
 | 
			
		||||
        beq     doubleword_aligned_r0
 | 
			
		||||
 | 
			
		||||
        /* If r0 is not double-word aligned yet, align it by loading
 | 
			
		||||
        and comparing the next word from each string.  */
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        ldr     r4, [r1], #4
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r4 label=return_24
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned_r0:
 | 
			
		||||
doubleword_aligned_r0:
 | 
			
		||||
        /* Get here when r0 is double-word aligned.  */
 | 
			
		||||
        /* Is r1 doubleword_aligned?  */
 | 
			
		||||
        tst     r1, #4
 | 
			
		||||
        beq     .L_doubleword_aligned
 | 
			
		||||
        beq     doubleword_aligned
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are word-aligned,
 | 
			
		||||
        r0 is double-word aligned, but r1 is not double-word aligned.  */
 | 
			
		||||
@@ -265,9 +271,9 @@ ENTRY(strcmp)
 | 
			
		||||
 | 
			
		||||
        /* Load the next double-word from each string and compare.  */
 | 
			
		||||
        ldrd    r2, r3, [r0], #8
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
 | 
			
		||||
        magic_compare_and_branch w1=r2 w2=r5 label=return_25
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=return_34
 | 
			
		||||
        b       3b
 | 
			
		||||
 | 
			
		||||
        .macro miscmp_word offsetlo offsethi
 | 
			
		||||
@@ -291,33 +297,33 @@ ENTRY(strcmp)
 | 
			
		||||
        and     r2, r3, r6, S2LOMEM #\offsetlo
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r2, r5
 | 
			
		||||
        bne     .L_return_25
 | 
			
		||||
        bne     return_25
 | 
			
		||||
        ldr     r5, [r1], #4
 | 
			
		||||
        cmp     ip, #0
 | 
			
		||||
        eor r3, r2, r3
 | 
			
		||||
        S2HIMEM r2, r5, #\offsethi
 | 
			
		||||
        it      eq
 | 
			
		||||
        cmpeq   r3, r2
 | 
			
		||||
        bne     .L_return_32
 | 
			
		||||
        bne     return_32
 | 
			
		||||
        b       7b
 | 
			
		||||
        .endm /* miscmp_word */
 | 
			
		||||
 | 
			
		||||
.L_return_32:
 | 
			
		||||
return_32:
 | 
			
		||||
        setup_return w1=r3, w2=r2
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_34:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_34:
 | 
			
		||||
        setup_return w1=r3, w2=r4
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_25:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_25:
 | 
			
		||||
        setup_return w1=r2, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_35:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_35:
 | 
			
		||||
        setup_return w1=r3, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_24:
 | 
			
		||||
        b       do_return
 | 
			
		||||
return_24:
 | 
			
		||||
        setup_return w1=r2, w2=r4
 | 
			
		||||
 | 
			
		||||
.L_do_return:
 | 
			
		||||
do_return:
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
@@ -329,16 +335,11 @@ ENTRY(strcmp)
 | 
			
		||||
        ldrd    r6, r7, [sp]
 | 
			
		||||
        ldrd    r4, r5, [sp, #8]
 | 
			
		||||
        adds    sp, sp, #16
 | 
			
		||||
        .cfi_def_cfa_offset 0
 | 
			
		||||
        .cfi_restore r4
 | 
			
		||||
        .cfi_restore r5
 | 
			
		||||
        .cfi_restore r6
 | 
			
		||||
        .cfi_restore r7
 | 
			
		||||
 | 
			
		||||
        /* There is a zero or a different byte between r1 and r2.  */
 | 
			
		||||
        /* r0 contains a mask of all-zero bytes in r1.  */
 | 
			
		||||
        /* Using r0 and not ip here because cbz requires low register.  */
 | 
			
		||||
        m_cbz   reg=r0, label=.L_compute_return_value
 | 
			
		||||
        m_cbz   reg=r0, label=compute_return_value
 | 
			
		||||
        clz     r0, r0
 | 
			
		||||
        /* r0 contains the number of bits on the left of the first all-zero byte in r1.  */
 | 
			
		||||
        rsb     r0, r0, #24
 | 
			
		||||
@@ -346,7 +347,7 @@ ENTRY(strcmp)
 | 
			
		||||
        lsr     r1, r1, r0
 | 
			
		||||
        lsr     r2, r2, r0
 | 
			
		||||
 | 
			
		||||
.L_compute_return_value:
 | 
			
		||||
compute_return_value:
 | 
			
		||||
        movs    r0, #1
 | 
			
		||||
        cmp     r1, r2
 | 
			
		||||
        /* The return value is computed as follows.
 | 
			
		||||
@@ -366,7 +367,7 @@ ENTRY(strcmp)
 | 
			
		||||
     * bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
 | 
			
		||||
     * version of the code.
 | 
			
		||||
     */
 | 
			
		||||
.L_strcmp_unaligned:
 | 
			
		||||
strcmp_unaligned:
 | 
			
		||||
	wp1 .req r0
 | 
			
		||||
	wp2 .req r1
 | 
			
		||||
	b1  .req r2
 | 
			
		||||
@@ -519,11 +520,6 @@ ENTRY(strcmp)
 | 
			
		||||
    ldrd    r6, r7, [sp]
 | 
			
		||||
    ldrd    r4, r5, [sp, #8]
 | 
			
		||||
    adds    sp, sp, #16
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    .cfi_restore r4
 | 
			
		||||
    .cfi_restore r5
 | 
			
		||||
    .cfi_restore r6
 | 
			
		||||
    .cfi_restore r7
 | 
			
		||||
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define STRCPY
 | 
			
		||||
#include "string_copy.S"
 | 
			
		||||
@@ -1,535 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(STPCPY) && !defined(STRCPY)
 | 
			
		||||
#error "Either STPCPY or STRCPY must be defined."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r4, r5, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 12
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset lr, 8
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
#else
 | 
			
		||||
    .macro m_push
 | 
			
		||||
    push    {r0, r4, r5, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset r4, 4
 | 
			
		||||
    .cfi_rel_offset r5, 8
 | 
			
		||||
    .cfi_rel_offset lr, 12
 | 
			
		||||
    .endm // m_push
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    .macro m_ret inst
 | 
			
		||||
    \inst   {r4, r5, pc}
 | 
			
		||||
    .endm // m_ret
 | 
			
		||||
#else
 | 
			
		||||
    .macro m_ret inst
 | 
			
		||||
    \inst   {r0, r4, r5, pc}
 | 
			
		||||
    .endm // m_ret
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    .macro m_copy_byte reg, cmd, label
 | 
			
		||||
    ldrb    \reg, [r1], #1
 | 
			
		||||
    strb    \reg, [r0], #1
 | 
			
		||||
    \cmd    \reg, \label
 | 
			
		||||
    .endm // m_copy_byte
 | 
			
		||||
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
ENTRY(stpcpy)
 | 
			
		||||
#else
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
#endif
 | 
			
		||||
    // Unroll the first 8 bytes that will be copied.
 | 
			
		||||
    m_push
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.Lstringcopy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=.Lstringcopy_continue
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_finish:
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_continue:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     .Lstringcopy_align_dst
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_check_src_align:
 | 
			
		||||
    // At this point dst is aligned to a double word, check if src
 | 
			
		||||
    // is also aligned to a double word.
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    bne     .Lstringcopy_unaligned_copy
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.Lstringcopy_mainloop:
 | 
			
		||||
    ldmia   r1!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_mainloop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_zero_in_first_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    itt     ne
 | 
			
		||||
    strbne  r2, [r0]
 | 
			
		||||
    m_ret   inst=popne
 | 
			
		||||
    itt     cs
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    strhcs  r2, [r0], #1
 | 
			
		||||
#else
 | 
			
		||||
    strhcs  r2, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popcs
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    itt     eq
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    streq   r2, [r0], #3
 | 
			
		||||
#else
 | 
			
		||||
    streq   r2, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r3, r2, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_zero_in_second_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    ittt    ne
 | 
			
		||||
    stmiane r0!, {r2}
 | 
			
		||||
    strbne  r3, [r0]
 | 
			
		||||
    m_ret   inst=popne
 | 
			
		||||
    ittt    cs
 | 
			
		||||
    strcs   r2, [r0], #4
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    strhcs  r3, [r0], #1
 | 
			
		||||
#else
 | 
			
		||||
    strhcs  r3, [r0]
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popcs
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    ittt    eq
 | 
			
		||||
#else
 | 
			
		||||
    itt     eq
 | 
			
		||||
#endif
 | 
			
		||||
    stmiaeq r0, {r2, r3}
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    addeq   r0, r0, #7
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r4, r3, #16
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_align_dst:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .Lstringcopy_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .Lstringcopy_complete
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_align_to_32:
 | 
			
		||||
    bcc     .Lstringcopy_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    cmp     r4, #0
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    itt     eq
 | 
			
		||||
    subeq   r0, r0, #1
 | 
			
		||||
#else
 | 
			
		||||
    it      eq
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
    ldrb    r5, [r1], #1
 | 
			
		||||
    strb    r5, [r0], #1
 | 
			
		||||
    cmp     r5, #0
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    itt     eq
 | 
			
		||||
    subeq   r0, r0, #1
 | 
			
		||||
#else
 | 
			
		||||
    it      eq
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=popeq
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .Lstringcopy_check_src_align
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    b       .Lstringcopy_check_src_align
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_complete:
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unaligned_copy:
 | 
			
		||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
			
		||||
    // There are 7 different versions of the unaligned copy code
 | 
			
		||||
    // to prevent overreading the src. The mainloop of every single version
 | 
			
		||||
    // will store 64 bits per loop. The difference is how much of src can
 | 
			
		||||
    // be read without potentially crossing a page boundary.
 | 
			
		||||
    tbb     [pc, r3]
 | 
			
		||||
.Lstringcopy_unaligned_branchtable:
 | 
			
		||||
    .byte 0
 | 
			
		||||
    .byte ((.Lstringcopy_unalign7 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign6 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign5 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign4 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign3 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign2 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.Lstringcopy_unalign1 - .Lstringcopy_unaligned_branchtable)/2)
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 7 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign7:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r3, [r1]
 | 
			
		||||
    cbz     r3, .Lstringcopy_unalign7_copy5bytes
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign7_copy6bytes
 | 
			
		||||
    ldrb    r5, [r1, #2]
 | 
			
		||||
    cbz     r5, .Lstringcopy_unalign7_copy7bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    beq     .Lstringcopy_finish
 | 
			
		||||
#else
 | 
			
		||||
    beq     .Lstringcopy_unalign_return
 | 
			
		||||
#endif
 | 
			
		||||
    b       .Lstringcopy_unalign7
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy5bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
.Lstringcopy_unalign_return:
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy6bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign7_copy7bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 6 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign6:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign_copy5bytes
 | 
			
		||||
    ldrb    r5, [r1, #1]
 | 
			
		||||
    cbz     r5, .Lstringcopy_unalign_copy6bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r3, #0xff0000
 | 
			
		||||
    beq     .Lstringcopy_unalign6_copy7bytes
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    beq     .Lstringcopy_finish
 | 
			
		||||
#else
 | 
			
		||||
    beq     .Lstringcopy_unalign_return
 | 
			
		||||
#endif
 | 
			
		||||
    b       .Lstringcopy_unalign6
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign6_copy7bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r3, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 5 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign5:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign_copy5bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_unalign5
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy5bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy6bytes:
 | 
			
		||||
    stmia   r0!, {r2}
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 4 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign4:
 | 
			
		||||
    ldmia   r1!, {r2}
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldmia   r1!, {r3}
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_unalign4
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 3 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign3:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign3_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, .Lstringcopy_unalign3_copy2bytes
 | 
			
		||||
    ldrb    r4, [r1, #2]
 | 
			
		||||
    cbz     r4, .Lstringcopy_unalign3_copy3bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    lr, r2, #24
 | 
			
		||||
    beq     .Lstringcopy_unalign_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_unalign3
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign3_copy3bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 2 bytes before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign2:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, .Lstringcopy_unalign_copy2bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r2, #0xff0000
 | 
			
		||||
    beq     .Lstringcopy_unalign_copy3bytes
 | 
			
		||||
    lsrs    ip, r2, #24
 | 
			
		||||
    beq     .Lstringcopy_unalign_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_unalign2
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 1 byte before possibly crossing a page.
 | 
			
		||||
.Lstringcopy_unalign1:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, .Lstringcopy_unalign_copy1byte
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .Lstringcopy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    stmia   r0!, {r2, r3}
 | 
			
		||||
    b       .Lstringcopy_unalign1
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy3bytes:
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r2, #16
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
 | 
			
		||||
.Lstringcopy_unalign_copy4bytes:
 | 
			
		||||
    stmia   r0, {r2}
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
    add     r0, r0, #3
 | 
			
		||||
#endif
 | 
			
		||||
    m_ret   inst=pop
 | 
			
		||||
#if defined(STPCPY)
 | 
			
		||||
END(stpcpy)
 | 
			
		||||
#else
 | 
			
		||||
END(strcpy)
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,167 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
ENTRY(strlen)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    mov     r1, r0
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    bne     align_src
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
mainloop:
 | 
			
		||||
    ldmia   r1!, {r2, r3}
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
    b       mainloop
 | 
			
		||||
 | 
			
		||||
zero_in_first_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     check_byte1_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #8
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
check_byte1_reg1:
 | 
			
		||||
    bcc     check_byte2_reg1
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #7
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
check_byte2_reg1:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    itt     ne
 | 
			
		||||
    subne   r0, r0, #6
 | 
			
		||||
    bxne    lr
 | 
			
		||||
    sub     r0, r0, #5
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
zero_in_second_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    // Check for zero in byte 0.
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    beq     check_byte1_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
check_byte1_reg2:
 | 
			
		||||
    bcc     check_byte2_reg2
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #3
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
check_byte2_reg2:
 | 
			
		||||
    // Check for zero in byte 2.
 | 
			
		||||
    tst     ip, #0x800000
 | 
			
		||||
    itt     ne
 | 
			
		||||
    subne   r0, r0, #2
 | 
			
		||||
    bxne    lr
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
align_src:
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, done
 | 
			
		||||
 | 
			
		||||
align_to_32:
 | 
			
		||||
    bcc     align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, done
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, done
 | 
			
		||||
 | 
			
		||||
align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     mainloop
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
    b       mainloop
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(strlen)
 | 
			
		||||
@@ -1,16 +1,5 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/memset.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/stpcpy.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strcat.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/__strcat_chk.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/__strcpy_chk.S \
 | 
			
		||||
    arch-arm/cortex-a9/bionic/strlen.S \
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a9/bionic/memcpy.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a9/bionic/memset.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a9/bionic/strcmp.S)
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
include bionic/libc/arch-arm/generic/generic.mk
 | 
			
		||||
 
 | 
			
		||||
@@ -1,216 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of src string, then get the source of the dst string.
 | 
			
		||||
// Check that the two lengths together don't exceed the threshold, then
 | 
			
		||||
// do a memcpy of the data.
 | 
			
		||||
ENTRY(__strcat_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    push    {r4, r5}
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
 | 
			
		||||
    // Save the dst register to r5
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Zero out r4
 | 
			
		||||
    eor     r4, r4, r4
 | 
			
		||||
 | 
			
		||||
    // r1 contains the address of the string to count.
 | 
			
		||||
.L_strlen_start:
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_update_count_and_finish:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub8_and_finish
 | 
			
		||||
    bcs     .L_sub7_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub6_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub8_and_finish:
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub7_and_finish:
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub6_and_finish:
 | 
			
		||||
    sub     r3, r3, #6
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r1, r0
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub4_and_finish
 | 
			
		||||
    bcs     .L_sub3_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub2_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub4_and_finish:
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub3_and_finish:
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_finish
 | 
			
		||||
 | 
			
		||||
.L_sub2_and_finish:
 | 
			
		||||
    sub     r3, r3, #2
 | 
			
		||||
 | 
			
		||||
.L_finish:
 | 
			
		||||
    cmp     r4, #0
 | 
			
		||||
    bne     .L_strlen_done
 | 
			
		||||
 | 
			
		||||
    // Time to get the dst string length.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
 | 
			
		||||
    // Save the original source address to r5.
 | 
			
		||||
    mov     r5, r0
 | 
			
		||||
 | 
			
		||||
    // Save the current length (adding 1 for the terminator).
 | 
			
		||||
    add     r4, r3, #1
 | 
			
		||||
    b       .L_strlen_start
 | 
			
		||||
 | 
			
		||||
    // r0 holds the pointer to the dst string.
 | 
			
		||||
    // r3 holds the dst string length.
 | 
			
		||||
    // r4 holds the src string length + 1.
 | 
			
		||||
.L_strlen_done:
 | 
			
		||||
    add     r2, r3, r4
 | 
			
		||||
    cmp     r2, lr
 | 
			
		||||
    bhi     __strcat_chk_failed
 | 
			
		||||
 | 
			
		||||
    // Set up the registers for the memcpy code.
 | 
			
		||||
    mov     r1, r5
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    mov     r2, r4
 | 
			
		||||
    add     r0, r0, r3
 | 
			
		||||
    pop     {r4, r5}
 | 
			
		||||
END(__strcat_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcat_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
 | 
			
		||||
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcat_chk_failed)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
    .cfi_adjust_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcat_chk_failed)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcat: prevented write past end of buffer"
 | 
			
		||||
@@ -1,180 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .thumb
 | 
			
		||||
    .thumb_func
 | 
			
		||||
 | 
			
		||||
// Get the length of the source string first, then do a memcpy of the data
 | 
			
		||||
// instead of a strcpy.
 | 
			
		||||
ENTRY(__strcpy_chk)
 | 
			
		||||
    pld     [r0, #0]
 | 
			
		||||
    push    {r0, lr}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
    ldrb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, .L_update_count_and_finish
 | 
			
		||||
 | 
			
		||||
.L_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r0], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
.L_update_count_and_finish:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub8_and_finish
 | 
			
		||||
    bcs     .L_sub7_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub6_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #5
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub8_and_finish:
 | 
			
		||||
    sub     r3, r3, #8
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub7_and_finish:
 | 
			
		||||
    sub     r3, r3, #7
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub6_and_finish:
 | 
			
		||||
    sub     r3, r3, #6
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r3, r0, r1
 | 
			
		||||
    lsls    r2, ip, #17
 | 
			
		||||
    bne     .L_sub4_and_finish
 | 
			
		||||
    bcs     .L_sub3_and_finish
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     .L_sub2_and_finish
 | 
			
		||||
 | 
			
		||||
    sub     r3, r3, #1
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub4_and_finish:
 | 
			
		||||
    sub     r3, r3, #4
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub3_and_finish:
 | 
			
		||||
    sub     r3, r3, #3
 | 
			
		||||
    b       .L_check_size
 | 
			
		||||
 | 
			
		||||
.L_sub2_and_finish:
 | 
			
		||||
    sub     r3, r3, #2
 | 
			
		||||
 | 
			
		||||
.L_check_size:
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
    ldr     r0, [sp]
 | 
			
		||||
    cmp     r3, lr
 | 
			
		||||
    bhs     __strcpy_chk_failed
 | 
			
		||||
 | 
			
		||||
    // Add 1 for copy length to get the string terminator.
 | 
			
		||||
    add     r2, r3, #1
 | 
			
		||||
END(__strcpy_chk)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __strcpy_chk_memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__strcpy_chk_failed)
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r0, 0
 | 
			
		||||
    .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
    ldr     r0, error_message
 | 
			
		||||
    ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
    add     r0, pc
 | 
			
		||||
    bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
    .word   error_string-(1b+4)
 | 
			
		||||
END(__strcpy_chk_failed)
 | 
			
		||||
 | 
			
		||||
    .data
 | 
			
		||||
error_string:
 | 
			
		||||
    .string "strcpy: prevented write past end of buffer"
 | 
			
		||||
@@ -1,103 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .syntax unified
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp     r2, r3
 | 
			
		||||
        bhi     __memcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
        // Fall through to memcpy...
 | 
			
		||||
END(__memcpy_chk)
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        pld     [r1, #64]
 | 
			
		||||
        push    {r0, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
#define MEMCPY_BASE         __memcpy_base
 | 
			
		||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
 | 
			
		||||
#include "memcpy_base.S"
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memcpy_chk_fail)
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push    {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr     r0, error_message
 | 
			
		||||
        ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add     r0, pc
 | 
			
		||||
        bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word   error_string-(1b+8)
 | 
			
		||||
END(__memcpy_chk_fail)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string "memcpy: prevented write past end of buffer"
 | 
			
		||||
@@ -1,234 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 * Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define CACHE_LINE_SIZE         (64)
 | 
			
		||||
#define PREFETCH_DISTANCE       (CACHE_LINE_SIZE*6)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #0
 | 
			
		||||
        beq         .L_memcpy_done
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        beq         .L_memcpy_done
 | 
			
		||||
 | 
			
		||||
        /* preload next cache line */
 | 
			
		||||
        pld         [r1, #CACHE_LINE_SIZE*1]
 | 
			
		||||
 | 
			
		||||
        /* Deal with very small blocks (< 32bytes) asap */
 | 
			
		||||
        cmp         r2, #32
 | 
			
		||||
        blo         .L_memcpy_lt_32bytes
 | 
			
		||||
        /* no need to align if len < 128 bytes */
 | 
			
		||||
        cmp         r2, #128
 | 
			
		||||
        blo         .L_memcpy_lt_128bytes
 | 
			
		||||
 | 
			
		||||
        /* large copy, align dest to 64 byte boundry */
 | 
			
		||||
        pld         [r1, #CACHE_LINE_SIZE*2]
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0x3F
 | 
			
		||||
        pld         [r1, #CACHE_LINE_SIZE*3]
 | 
			
		||||
        beq         .L_memcpy_dispatch
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        /* copy 1 byte */
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      ip, [r1], #1
 | 
			
		||||
        strbmi      ip, [r0], #1
 | 
			
		||||
        /* copy 2 bytes */
 | 
			
		||||
        itt         cs
 | 
			
		||||
        ldrhcs      ip, [r1], #2
 | 
			
		||||
        strhcs      ip, [r0], #2
 | 
			
		||||
        /* copy 4 bytes */
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrmi       ip, [r1], #4
 | 
			
		||||
        strmi       ip, [r0], #4
 | 
			
		||||
        /* copy 8 bytes */
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
1:      /* copy 16 bytes */
 | 
			
		||||
        movs        ip, r3, lsl #27
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vld1.8      {q0}, [r1]!
 | 
			
		||||
        vst1.8      {q0}, [r0, :128]!
 | 
			
		||||
1:      /* copy 32 bytes */
 | 
			
		||||
        bcc         .L_memcpy_dispatch
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
 | 
			
		||||
.L_memcpy_dispatch:
 | 
			
		||||
        // pre-decrement by 128 to detect nearly-done condition easily, but
 | 
			
		||||
        // also need to check if we have less than 128 bytes left at this
 | 
			
		||||
        // point due to alignment code above
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
        blo         .L_memcpy_lt_128presub
 | 
			
		||||
 | 
			
		||||
        // Denver does better if both source and dest are aligned so
 | 
			
		||||
        // we'll special-case that even though the code is virually identical
 | 
			
		||||
        tst         r1, #0xF
 | 
			
		||||
        bne         .L_memcpy_neon_unalign_src_pld
 | 
			
		||||
 | 
			
		||||
        // DRAM memcpy should be throttled slightly to get full bandwidth
 | 
			
		||||
        //
 | 
			
		||||
        cmp         r2, #32768
 | 
			
		||||
        bhi         .L_memcpy_neon_unalign_src_pld
 | 
			
		||||
        .align      4
 | 
			
		||||
1:
 | 
			
		||||
        /* copy 128 bytes in each loop */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
 | 
			
		||||
        /* preload a cache line */
 | 
			
		||||
        pld         [r1, #PREFETCH_DISTANCE]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1, :128]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1, :128]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        /* preload a cache line */
 | 
			
		||||
        pld         [r1, #PREFETCH_DISTANCE]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1, :128]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1, :128]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        bne         .L_memcpy_lt_128bytes_align
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
        .align      4
 | 
			
		||||
.L_memcpy_neon_unalign_src_pld:
 | 
			
		||||
1:
 | 
			
		||||
        /* copy 128 bytes in each loop */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
 | 
			
		||||
        /* preload a cache line */
 | 
			
		||||
        pld         [r1, #PREFETCH_DISTANCE]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        /* preload a cache line */
 | 
			
		||||
        pld         [r1, #PREFETCH_DISTANCE]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        bne         .L_memcpy_lt_128bytes_align
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_memcpy_lt_128presub:
 | 
			
		||||
        add         r2, r2, #128
 | 
			
		||||
.L_memcpy_lt_128bytes_align:
 | 
			
		||||
        /* copy 64 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #26
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
1:      /* copy 32 bytes */
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
1:      /* copy 16 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #28
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {q0}, [r1]!
 | 
			
		||||
        vst1.8      {q0}, [r0, :128]!
 | 
			
		||||
1:      /* copy 8 bytes */
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
1:      /* copy 4 bytes */
 | 
			
		||||
        tst         r2, #4
 | 
			
		||||
        itt         ne
 | 
			
		||||
        ldrne       ip, [r1], #4
 | 
			
		||||
        strne       ip, [r0], #4
 | 
			
		||||
        /* copy 2 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #31
 | 
			
		||||
        itt         cs
 | 
			
		||||
        ldrhcs      ip, [r1], #2
 | 
			
		||||
        strhcs      ip, [r0], #2
 | 
			
		||||
        /* copy 1 byte */
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      ip, [r1]
 | 
			
		||||
        strbmi      ip, [r0]
 | 
			
		||||
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_memcpy_lt_128bytes:
 | 
			
		||||
        /* copy 64 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #26
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]!
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]!
 | 
			
		||||
1:      /* copy 32 bytes */
 | 
			
		||||
        bpl	    .L_memcpy_lt_32bytes
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]!
 | 
			
		||||
.L_memcpy_lt_32bytes:
 | 
			
		||||
        /* copy 16 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #28
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {q0}, [r1]!
 | 
			
		||||
        vst1.8      {q0}, [r0]!
 | 
			
		||||
1:      /* copy 8 bytes */
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      /* copy 4 bytes */
 | 
			
		||||
        tst         r2, #4
 | 
			
		||||
        itt         ne
 | 
			
		||||
        ldrne       ip, [r1], #4
 | 
			
		||||
        strne       ip, [r0], #4
 | 
			
		||||
        /* copy 2 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #31
 | 
			
		||||
        itt         cs
 | 
			
		||||
        ldrhcs      ip, [r1], #2
 | 
			
		||||
        strhcs      ip, [r0], #2
 | 
			
		||||
        /* copy 1 byte */
 | 
			
		||||
        itt         mi
 | 
			
		||||
        ldrbmi      ip, [r1]
 | 
			
		||||
        strbmi      ip, [r0]
 | 
			
		||||
 | 
			
		||||
.L_memcpy_done:
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
END(MEMCPY_BASE)
 | 
			
		||||
@@ -1,281 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 * Copyright (c) 2013-2014 NVIDIA Corporation.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .syntax unified
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
#define CACHE_LINE_SIZE         (64)
 | 
			
		||||
#define MEMCPY_BLOCK_SIZE_SMALL (32768)
 | 
			
		||||
#define MEMCPY_BLOCK_SIZE_MID   (1048576)
 | 
			
		||||
#define PREFETCH_DISTANCE_NEAR  (CACHE_LINE_SIZE*4)
 | 
			
		||||
#define PREFETCH_DISTANCE_MID   (CACHE_LINE_SIZE*4)
 | 
			
		||||
#define PREFETCH_DISTANCE_FAR   (CACHE_LINE_SIZE*16)
 | 
			
		||||
 | 
			
		||||
ENTRY(memmove)
 | 
			
		||||
        cmp         r2, #0
 | 
			
		||||
        cmpne       r0, r1
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
        subs        r3, r0, r1
 | 
			
		||||
        bls         .L_jump_to_memcpy
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         .L_reversed_memcpy
 | 
			
		||||
 | 
			
		||||
.L_jump_to_memcpy:
 | 
			
		||||
        b           memcpy
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy:
 | 
			
		||||
        push        {r0, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        add         r0, r0, r2
 | 
			
		||||
        add         r1, r1, r2
 | 
			
		||||
 | 
			
		||||
        /* preload next cache line */
 | 
			
		||||
        pld         [r1, #-CACHE_LINE_SIZE]
 | 
			
		||||
        pld         [r1, #-CACHE_LINE_SIZE*2]
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_align_dest:
 | 
			
		||||
        /* Deal with very small blocks (< 32bytes) asap */
 | 
			
		||||
        cmp         r2, #32
 | 
			
		||||
        blo         .L_reversed_memcpy_lt_32bytes
 | 
			
		||||
        /* no need to align if len < 128 bytes */
 | 
			
		||||
        cmp         r2, #128
 | 
			
		||||
        blo         .L_reversed_memcpy_lt_128bytes
 | 
			
		||||
        /* align destination to 64 bytes (1 cache line) */
 | 
			
		||||
        ands        r3, r0, #0x3f
 | 
			
		||||
        beq         .L_reversed_memcpy_dispatch
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
0:      /* copy 1 byte */
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrbmi      ip, [r1, #-1]!
 | 
			
		||||
        strbmi      ip, [r0, #-1]!
 | 
			
		||||
1:      /* copy 2 bytes */
 | 
			
		||||
        ldrbcs      ip, [r1, #-1]!
 | 
			
		||||
        strbcs      ip, [r0, #-1]!
 | 
			
		||||
        ldrbcs      ip, [r1, #-1]!
 | 
			
		||||
        strbcs      ip, [r0, #-1]!
 | 
			
		||||
2:      /* copy 4 bytes */
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bpl         3f
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        sub         r0, r0, #4
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]
 | 
			
		||||
3:      /* copy 8 bytes */
 | 
			
		||||
        bcc         4f
 | 
			
		||||
        sub         r1, r1, #8
 | 
			
		||||
        sub         r0, r0, #8
 | 
			
		||||
        vld1.8      {d0}, [r1]
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]
 | 
			
		||||
4:      /* copy 16 bytes */
 | 
			
		||||
        movs        ip, r3, lsl #27
 | 
			
		||||
        bpl         5f
 | 
			
		||||
        sub         r1, r1, #16
 | 
			
		||||
        sub         r0, r0, #16
 | 
			
		||||
        vld1.8      {q0}, [r1]
 | 
			
		||||
        vst1.8      {q0}, [r0, :128]
 | 
			
		||||
5:      /* copy 32 bytes */
 | 
			
		||||
        bcc         .L_reversed_memcpy_dispatch
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_dispatch:
 | 
			
		||||
        /* preload more cache lines */
 | 
			
		||||
        pld         [r1, #-CACHE_LINE_SIZE*3]
 | 
			
		||||
        pld         [r1, #-CACHE_LINE_SIZE*4]
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #MEMCPY_BLOCK_SIZE_SMALL
 | 
			
		||||
        blo         .L_reversed_memcpy_neon_pld_near
 | 
			
		||||
        cmp         r2, #MEMCPY_BLOCK_SIZE_MID
 | 
			
		||||
        blo         .L_reversed_memcpy_neon_pld_mid
 | 
			
		||||
        b           .L_reversed_memcpy_neon_pld_far
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_neon_pld_near:
 | 
			
		||||
        /* less than 128 bytes? */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
        blo         1f
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        mov         r3, #-32
 | 
			
		||||
        .align      4
 | 
			
		||||
0:
 | 
			
		||||
        /* copy 128 bytes in each loop */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
 | 
			
		||||
        /* preload to cache */
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_NEAR+CACHE_LINE_SIZE*2)+32]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
 | 
			
		||||
        /* preload to cache */
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_NEAR+CACHE_LINE_SIZE*2)+32]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
 | 
			
		||||
        bhs         0b
 | 
			
		||||
        add         r1, r1, #32
 | 
			
		||||
        add         r0, r0, #32
 | 
			
		||||
1:
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        bne         .L_reversed_memcpy_lt_128bytes
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_neon_pld_mid:
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        mov         r3, #-32
 | 
			
		||||
        .align      4
 | 
			
		||||
0:
 | 
			
		||||
        /* copy 128 bytes in each loop */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
 | 
			
		||||
        /* preload to cache */
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_MID+CACHE_LINE_SIZE)+32]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
 | 
			
		||||
        /* preload to cache */
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_MID+CACHE_LINE_SIZE)+32]
 | 
			
		||||
        /* copy a cache line */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
        vld1.8      {q0, q1}, [r1], r3
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256], r3
 | 
			
		||||
 | 
			
		||||
        bhs         0b
 | 
			
		||||
        add         r1, r1, #32
 | 
			
		||||
        add         r0, r0, #32
 | 
			
		||||
1:
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        bne         .L_reversed_memcpy_lt_128bytes
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_neon_pld_far:
 | 
			
		||||
        sub         r2, r2, #128
 | 
			
		||||
        sub         r0, r0, #128
 | 
			
		||||
        sub         r1, r1, #128
 | 
			
		||||
        .align      4
 | 
			
		||||
0:
 | 
			
		||||
        /* copy 128 bytes in each loop */
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
 | 
			
		||||
        /* preload to cache */
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_FAR+CACHE_LINE_SIZE*2)+128]
 | 
			
		||||
        pld         [r1, #-(PREFETCH_DISTANCE_FAR+CACHE_LINE_SIZE)+128]
 | 
			
		||||
        /* read */
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]!
 | 
			
		||||
        vld1.8      {q2, q3}, [r1]!
 | 
			
		||||
        vld1.8      {q8, q9}, [r1]!
 | 
			
		||||
        vld1.8      {q10, q11}, [r1]!
 | 
			
		||||
        /* write */
 | 
			
		||||
        vst1.8      {q0, q1}, [r0, :256]!
 | 
			
		||||
        vst1.8      {q2, q3}, [r0, :256]!
 | 
			
		||||
        vst1.8      {q8, q9}, [r0, :256]!
 | 
			
		||||
        vst1.8      {q10, q11}, [r0, :256]!
 | 
			
		||||
 | 
			
		||||
        sub         r0, r0, #256
 | 
			
		||||
        sub         r1, r1, #256
 | 
			
		||||
        bhs         0b
 | 
			
		||||
        add         r0, r0, #128
 | 
			
		||||
        add         r1, r1, #128
 | 
			
		||||
1:
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        bne         .L_reversed_memcpy_lt_128bytes
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
.L_reversed_memcpy_lt_128bytes:
 | 
			
		||||
6:      /* copy 64 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #26
 | 
			
		||||
        bcc         5f
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]
 | 
			
		||||
5:      /* copy 32 bytes */
 | 
			
		||||
        bpl         4f
 | 
			
		||||
        sub         r1, r1, #32
 | 
			
		||||
        sub         r0, r0, #32
 | 
			
		||||
        vld1.8      {q0, q1}, [r1]
 | 
			
		||||
        vst1.8      {q0, q1}, [r0]
 | 
			
		||||
.L_reversed_memcpy_lt_32bytes:
 | 
			
		||||
4:      /* copy 16 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #28
 | 
			
		||||
        bcc         3f
 | 
			
		||||
        sub         r1, r1, #16
 | 
			
		||||
        sub         r0, r0, #16
 | 
			
		||||
        vld1.8      {q0}, [r1]
 | 
			
		||||
        vst1.8      {q0}, [r0]
 | 
			
		||||
3:      /* copy 8 bytes */
 | 
			
		||||
        bpl         2f
 | 
			
		||||
        sub         r1, r1, #8
 | 
			
		||||
        sub         r0, r0, #8
 | 
			
		||||
        vld1.8      {d0}, [r1]
 | 
			
		||||
        vst1.8      {d0}, [r0]
 | 
			
		||||
2:      /* copy 4 bytes */
 | 
			
		||||
        ands        ip, r2, #0x4
 | 
			
		||||
        beq         1f
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        sub         r0, r0, #4
 | 
			
		||||
        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]
 | 
			
		||||
        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]
 | 
			
		||||
1:      /* copy 2 bytes */
 | 
			
		||||
        movs        ip, r2, lsl #31
 | 
			
		||||
        ldrbcs      ip, [r1, #-1]!
 | 
			
		||||
        strbcs      ip, [r0, #-1]!
 | 
			
		||||
        ldrbcs      ip, [r1, #-1]!
 | 
			
		||||
        strbcs      ip, [r0, #-1]!
 | 
			
		||||
0:      /* copy 1 byte */
 | 
			
		||||
        ldrbmi      ip, [r1, #-1]!
 | 
			
		||||
        strbmi      ip, [r0, #-1]!
 | 
			
		||||
 | 
			
		||||
        pop         {r0, pc}
 | 
			
		||||
 | 
			
		||||
END(memmove)
 | 
			
		||||
@@ -1,208 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        .cpu        cortex-a15
 | 
			
		||||
        .fpu        neon
 | 
			
		||||
        .syntax     unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         .L_done
 | 
			
		||||
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push        {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ldr         r0, error_message
 | 
			
		||||
        ldr         r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add         r0, pc
 | 
			
		||||
        bl          __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word       error_string-(1b+8)
 | 
			
		||||
END(__memset_chk)
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov         r2, r1
 | 
			
		||||
        mov         r1, #0
 | 
			
		||||
.L_done:
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        pldw        [r0]
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
 | 
			
		||||
        // Duplicate the low byte of r1
 | 
			
		||||
        mov         r1, r1, lsl #24
 | 
			
		||||
        orr         r1, r1, r1, lsr #8
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         .L_less_than_16
 | 
			
		||||
 | 
			
		||||
        // This section handles regions 16 bytes or larger
 | 
			
		||||
        //
 | 
			
		||||
        // Use aligned vst1.8 and vstm when possible.  Register values will be:
 | 
			
		||||
        //   ip is scratch
 | 
			
		||||
        //   q0, q1, and r1 contain the memset value
 | 
			
		||||
        //   r2 is the number of bytes to set
 | 
			
		||||
        //   r3 is the advancing destination pointer
 | 
			
		||||
        vdup.32     q0, r1
 | 
			
		||||
 | 
			
		||||
        ands        ip, r3, 0xF
 | 
			
		||||
        beq         .L_memset_aligned
 | 
			
		||||
 | 
			
		||||
        // Align dest pointer to 16-byte boundary.
 | 
			
		||||
        pldw        [r0, #64]
 | 
			
		||||
        rsb         ip, ip, #16
 | 
			
		||||
 | 
			
		||||
        // Pre-adjust the byte count to reflect post-aligment value.  Expecting
 | 
			
		||||
        // 8-byte alignment to be rather common so we special case that one.
 | 
			
		||||
        sub         r2, r2, ip
 | 
			
		||||
 | 
			
		||||
        /* set 1 byte */
 | 
			
		||||
        tst         ip, #1
 | 
			
		||||
        it          ne
 | 
			
		||||
        strbne      r1, [r3], #1
 | 
			
		||||
        /* set 2 bytes */
 | 
			
		||||
        tst         ip, #2
 | 
			
		||||
        it          ne
 | 
			
		||||
        strhne      r1, [r3], #2
 | 
			
		||||
        /* set 4 bytes */
 | 
			
		||||
        movs        ip, ip, lsl #29
 | 
			
		||||
        it          mi
 | 
			
		||||
        strmi       r1, [r3], #4
 | 
			
		||||
        /* set 8 bytes */
 | 
			
		||||
        itt         cs
 | 
			
		||||
        strcs       r1, [r3], #4
 | 
			
		||||
        strcs       r1, [r3], #4
 | 
			
		||||
 | 
			
		||||
.L_memset_aligned:
 | 
			
		||||
        // Destination is now 16-byte aligned.  Determine how to handle
 | 
			
		||||
        // remaining bytes.
 | 
			
		||||
        vmov        q1, q0
 | 
			
		||||
        cmp         r2, #128
 | 
			
		||||
        blo         .L_less_than_128
 | 
			
		||||
 | 
			
		||||
        // We need to set a larger block of memory.  Use four Q regs to
 | 
			
		||||
        // set a full cache line in one instruction.  Pre-decrement
 | 
			
		||||
        // r2 to simplify end-of-loop detection
 | 
			
		||||
        vmov        q2, q0
 | 
			
		||||
        vmov        q3, q0
 | 
			
		||||
        pldw        [r0, #128]
 | 
			
		||||
        sub         r2, r2, #128
 | 
			
		||||
        .align 4
 | 
			
		||||
.L_memset_loop_128:
 | 
			
		||||
        pldw        [r3, #192]
 | 
			
		||||
        vstm        r3!, {q0, q1, q2, q3}
 | 
			
		||||
        vstm        r3!, {q0, q1, q2, q3}
 | 
			
		||||
        subs        r2, r2, #128
 | 
			
		||||
        bhs         .L_memset_loop_128
 | 
			
		||||
 | 
			
		||||
        // Un-bias r2 so it contains the number of bytes left.  Early
 | 
			
		||||
        // exit if we are done.
 | 
			
		||||
        adds        r2, r2, #128
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        .align 4
 | 
			
		||||
.L_less_than_128:
 | 
			
		||||
        // set 64 bytes
 | 
			
		||||
        movs        ip, r2, lsl #26
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {q0, q1}, [r3, :128]!
 | 
			
		||||
        vst1.8      {q0, q1}, [r3, :128]!
 | 
			
		||||
        beq         2f
 | 
			
		||||
1:
 | 
			
		||||
        // set 32 bytes
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vst1.8      {q0, q1}, [r3, :128]!
 | 
			
		||||
1:
 | 
			
		||||
        // set 16 bytes
 | 
			
		||||
        movs        ip, r2, lsl #28
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {q0}, [r3, :128]!
 | 
			
		||||
        beq         2f
 | 
			
		||||
1:
 | 
			
		||||
        // set 8 bytes
 | 
			
		||||
        bpl         1f
 | 
			
		||||
        vst1.8      {d0}, [r3, :64]!
 | 
			
		||||
1:
 | 
			
		||||
        // set 4 bytes
 | 
			
		||||
        tst         r2, #4
 | 
			
		||||
        it          ne
 | 
			
		||||
        strne       r1, [r3], #4
 | 
			
		||||
1:
 | 
			
		||||
        // set 2 bytes
 | 
			
		||||
        movs        ip, r2, lsl #31
 | 
			
		||||
        it          cs
 | 
			
		||||
        strhcs      r1, [r3], #2
 | 
			
		||||
        // set 1 byte
 | 
			
		||||
        it          mi
 | 
			
		||||
        strbmi      r1, [r3]
 | 
			
		||||
2:
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
.L_less_than_16:
 | 
			
		||||
        // Store up to 15 bytes without worrying about byte alignment
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        str         r1, [r3], #4
 | 
			
		||||
        str         r1, [r3], #4
 | 
			
		||||
        beq         2f
 | 
			
		||||
1:
 | 
			
		||||
        it          mi
 | 
			
		||||
        strmi       r1, [r3], #4
 | 
			
		||||
        movs        ip, r2, lsl #31
 | 
			
		||||
        it          mi
 | 
			
		||||
        strbmi      r1, [r3], #1
 | 
			
		||||
        itt         cs
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3]
 | 
			
		||||
2:
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memset: prevented write past end of buffer"
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/denver/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
    arch-arm/denver/bionic/memset.S \
 | 
			
		||||
    arch-arm/denver/bionic/__strcat_chk.S \
 | 
			
		||||
    arch-arm/denver/bionic/__strcpy_chk.S \
 | 
			
		||||
 | 
			
		||||
# Use cortex-a15 versions of strcat/strcpy/strlen.
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/stpcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcat.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/cortex-a15/bionic/strlen.S \
 | 
			
		||||
@@ -1,345 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
#else
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(memcmp)
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
        /* take of the case where length is 0 or the buffers are the same */
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 8+4 bytes, this simplify things below
 | 
			
		||||
         * and avoid some overhead for small blocks
 | 
			
		||||
         */
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
/*
 | 
			
		||||
 * Neon optimization
 | 
			
		||||
 * Comparing 32 bytes at a time
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__ARM_NEON__) && defined(NEON_UNALIGNED_ACCESS)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop compares 32 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Start subtracting the values and merge results */
 | 
			
		||||
        vsub.i8     q0, q2
 | 
			
		||||
        vsub.i8     q1, q3
 | 
			
		||||
        vorr        q2, q0, q1
 | 
			
		||||
        vorr        d4, d5
 | 
			
		||||
        vmov        r3, ip, d4
 | 
			
		||||
        /* Check if there are any differences among the 32 bytes */
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        b           3f
 | 
			
		||||
2:
 | 
			
		||||
        /* Check if the difference was in the first or last 16 bytes */
 | 
			
		||||
        sub         r0, #32
 | 
			
		||||
        vorr        d0, d1
 | 
			
		||||
        sub         r1, #32
 | 
			
		||||
        vmov        r3, ip, d0
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        /* if the first 16 bytes are equal, we only have to rewind 16 bytes */
 | 
			
		||||
        ittt        eq
 | 
			
		||||
        subeq       r2, #16
 | 
			
		||||
        addeq       r0, #16
 | 
			
		||||
        addeq       r1, #16
 | 
			
		||||
 | 
			
		||||
3:      /* fix-up the remaining count */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /* save registers */
 | 
			
		||||
        stmfd       sp!, {r4, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
 | 
			
		||||
        /* since r0 hold the result, move the first source
 | 
			
		||||
         * pointer somewhere else
 | 
			
		||||
         */
 | 
			
		||||
         mov        r4, r0
 | 
			
		||||
 | 
			
		||||
        /* align first pointer to word boundary
 | 
			
		||||
         * offset = -src & 3
 | 
			
		||||
         */
 | 
			
		||||
        rsb         r3, r4, #0
 | 
			
		||||
        ands        r3, r3, #3
 | 
			
		||||
        beq         0f
 | 
			
		||||
 | 
			
		||||
        /* align first pointer  */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
1:      ldrb        r0, [r4], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r3, r3, #1
 | 
			
		||||
        bne         1b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
0:      /* here the first pointer is aligned, and we have at least 4 bytes
 | 
			
		||||
         * to process.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* see if the pointers are congruent */
 | 
			
		||||
        eor         r0, r4, r1
 | 
			
		||||
        ands        r0, r0, #3
 | 
			
		||||
        bne         5f
 | 
			
		||||
 | 
			
		||||
        /* congruent case, 32 bytes per iteration
 | 
			
		||||
         * We need to make sure there are at least 32+4 bytes left
 | 
			
		||||
         * because we effectively read ahead one word, and we could
 | 
			
		||||
         * read past the buffer (and segfault) if we're not careful.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        ldr         ip, [r1]
 | 
			
		||||
        subs        r2, r2, #(32 + 4)
 | 
			
		||||
        bmi         1f
 | 
			
		||||
 | 
			
		||||
0:      pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        ldr         lr, [r1, #4]!
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         0b
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 4 bytes left? */
 | 
			
		||||
1:      adds        r2, r2, #(32 - 4 + 4)
 | 
			
		||||
        bmi         4f
 | 
			
		||||
 | 
			
		||||
        /* finish off 4 bytes at a time */
 | 
			
		||||
3:      ldr         r0, [r4], #4
 | 
			
		||||
        ldr         ip, [r1], #4
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #4
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
4:      adds        r2, r2, #4
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9f
 | 
			
		||||
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8f
 | 
			
		||||
 | 
			
		||||
2:      /* the last 4 bytes are different, restart them */
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
 | 
			
		||||
        /* process the last few bytes */
 | 
			
		||||
8:      ldrb        r0, [r4], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        // stall
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         8b
 | 
			
		||||
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
10:     /* process less than 12 bytes */
 | 
			
		||||
        cmp         r2, #0
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
11:
 | 
			
		||||
        ldrb        r0, [r3], #1
 | 
			
		||||
        ldrb        ip, [r1], #1
 | 
			
		||||
        subs        r0, ip
 | 
			
		||||
        bxne        lr
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         11b
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
5:      /*************** non-congruent case ***************/
 | 
			
		||||
        and         r0, r1, #3
 | 
			
		||||
        cmp         r0, #2
 | 
			
		||||
        bne         4f
 | 
			
		||||
 | 
			
		||||
        /* here, offset is 2 (16-bits aligned, special cased) */
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 16 bytes to process */
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        addmi       r2, r2, #16
 | 
			
		||||
        bmi         8b
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
 | 
			
		||||
6:      pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        mov         ip, lr, lsr #16
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        orr         ip, ip, lr, lsl #16
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         6b
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #16
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #(4+2)
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
4:      /*************** offset is 1 or 3 (less optimized) ***************/
 | 
			
		||||
 | 
			
		||||
		stmfd		sp!, {r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
        // r5 = rhs
 | 
			
		||||
        // r6 = lhs
 | 
			
		||||
        // r7 = scratch
 | 
			
		||||
 | 
			
		||||
        mov         r5, r0, lsl #3		/* r5 = right shift */
 | 
			
		||||
        rsb         r6, r5, #32         /* r6 = left shift */
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         r7, [r1], #4
 | 
			
		||||
        sub         r2, r2, #8
 | 
			
		||||
 | 
			
		||||
6:      mov         ip, r7, lsr r5
 | 
			
		||||
        ldr         r7, [r1], #4
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        orr         ip, ip, r7, lsl r6
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, r7, lsr r5
 | 
			
		||||
        ldreq       r7, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, r7, lsl r6
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
 | 
			
		||||
        sub         r1, r1, r6, lsr #3
 | 
			
		||||
		ldmfd       sp!, {r5, r6, r7}
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #8
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #4
 | 
			
		||||
        sub         r1, r1, r6, lsr #3
 | 
			
		||||
        sub         r4, r4, #4
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
		ldmfd		sp!, {r5, r6, r7}
 | 
			
		||||
        b           8b
 | 
			
		||||
END(memcmp)
 | 
			
		||||
@@ -27,8 +27,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memcpy() for ARM.
 | 
			
		||||
@@ -37,45 +36,33 @@
 | 
			
		||||
         * so we have to preserve R0.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
        // Fall through to memcpy...
 | 
			
		||||
END(__memcpy_chk)
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        /* The stack must always be 64-bits aligned to be compliant with the
 | 
			
		||||
         * ARM ABI. Since we have to save R0, we might as well save R4
 | 
			
		||||
         * which we can use for better pipelining of the reads below
 | 
			
		||||
         */
 | 
			
		||||
        .save       {r0, r4, lr}
 | 
			
		||||
        stmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 12
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        .cfi_rel_offset r4, 4
 | 
			
		||||
        .cfi_rel_offset lr, 8
 | 
			
		||||
        /* Making room for r5-r11 which will be spilled later */
 | 
			
		||||
        .pad        #28
 | 
			
		||||
        sub         sp, sp, #28
 | 
			
		||||
        .cfi_adjust_cfa_offset 28
 | 
			
		||||
 | 
			
		||||
        // preload the destination because we'll align it to a cache line
 | 
			
		||||
        // with small writes. Also start the source "pump".
 | 
			
		||||
        pld         [r0, #0]
 | 
			
		||||
        pld         [r1, #0]
 | 
			
		||||
        pld         [r1, #32]
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
        /* it simplifies things to take care of len<4 early */
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lcopy_last_3_and_return
 | 
			
		||||
        blo         copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
        /* compute the offset to align the source
 | 
			
		||||
         * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
         */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, r3, #3
 | 
			
		||||
        beq         .Lsrc_aligned
 | 
			
		||||
        beq         src_aligned
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
@@ -83,19 +70,19 @@ ENTRY(memcpy)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0], #1
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
src_aligned:
 | 
			
		||||
 | 
			
		||||
        /* see if src and dst are aligned together (congruent) */
 | 
			
		||||
        eor         r12, r0, r1
 | 
			
		||||
        tst         r12, #3
 | 
			
		||||
        bne         .Lnon_congruent
 | 
			
		||||
        bne         non_congruent
 | 
			
		||||
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
@@ -105,29 +92,29 @@ ENTRY(memcpy)
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0x1C
 | 
			
		||||
        beq         .Lcongruent_aligned32
 | 
			
		||||
        beq         congruent_aligned32
 | 
			
		||||
        cmp         r3, r2
 | 
			
		||||
        andhi       r3, r2, #0x1C
 | 
			
		||||
 | 
			
		||||
        /* conditionally copies 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r12, r3, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
.Lcongruent_aligned32:
 | 
			
		||||
congruent_aligned32:
 | 
			
		||||
        /*
 | 
			
		||||
         * here source is aligned to 32 bytes.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
.Lcached_aligned32:
 | 
			
		||||
cached_aligned32:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         .Lless_than_32_left
 | 
			
		||||
        blo         less_than_32_left
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * We preload a cache-line up to 64 bytes ahead. On the 926, this will
 | 
			
		||||
@@ -152,7 +139,7 @@ ENTRY(memcpy)
 | 
			
		||||
        add         r12, r12, #64
 | 
			
		||||
 | 
			
		||||
1:      ldmia       r1!, { r4-r11 }
 | 
			
		||||
        pld         [r12, #64]
 | 
			
		||||
        PLD         (r12, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
 | 
			
		||||
@@ -165,7 +152,10 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
.Lless_than_32_left:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
less_than_32_left:
 | 
			
		||||
        /*
 | 
			
		||||
         * less than 32 bytes left at this point (length in r2)
 | 
			
		||||
         */
 | 
			
		||||
@@ -179,18 +169,18 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
@@ -199,7 +189,7 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /********************************************************************/
 | 
			
		||||
 | 
			
		||||
.Lnon_congruent:
 | 
			
		||||
non_congruent:
 | 
			
		||||
        /*
 | 
			
		||||
         * here source is aligned to 4 bytes
 | 
			
		||||
         * but destination is not.
 | 
			
		||||
@@ -209,9 +199,9 @@ ENTRY(memcpy)
 | 
			
		||||
         * partial words in the shift queue)
 | 
			
		||||
         */
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lcopy_last_3_and_return
 | 
			
		||||
        blo         copy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
        /* Use post-increment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
        /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
 | 
			
		||||
         * frame. Don't update sp.
 | 
			
		||||
         */
 | 
			
		||||
        stmea       sp, {r5-r11}
 | 
			
		||||
@@ -230,15 +220,15 @@ ENTRY(memcpy)
 | 
			
		||||
         * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r5, r5, lsl #31
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lpartial_word_tail
 | 
			
		||||
        blo         partial_word_tail
 | 
			
		||||
 | 
			
		||||
        /* Align destination to 32 bytes (cache line boundary) */
 | 
			
		||||
1:      tst         r0, #0x1c
 | 
			
		||||
@@ -250,11 +240,11 @@ ENTRY(memcpy)
 | 
			
		||||
        str         r4, [r0], #4
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        blo         .Lpartial_word_tail
 | 
			
		||||
        blo         partial_word_tail
 | 
			
		||||
 | 
			
		||||
        /* copy 32 bytes at a time */
 | 
			
		||||
2:      subs        r2, r2, #32
 | 
			
		||||
        blo         .Lless_than_thirtytwo
 | 
			
		||||
        blo         less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
        /* Use immediate mode for the shifts, because there is an extra cycle
 | 
			
		||||
         * for register shifts, which could account for up to 50% of
 | 
			
		||||
@@ -262,15 +252,15 @@ ENTRY(memcpy)
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        cmp         r12, #24
 | 
			
		||||
        beq         .Lloop24
 | 
			
		||||
        beq         loop24
 | 
			
		||||
        cmp         r12, #8
 | 
			
		||||
        beq         .Lloop8
 | 
			
		||||
        beq         loop8
 | 
			
		||||
 | 
			
		||||
.Lloop16:
 | 
			
		||||
loop16:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
        ldmia       r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
        orr         r3, r3, r4,     lsl #16
 | 
			
		||||
@@ -291,13 +281,13 @@ ENTRY(memcpy)
 | 
			
		||||
        stmia       r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
        mov         r3, r11,        lsr #16
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        b           .Lless_than_thirtytwo
 | 
			
		||||
        b           less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
.Lloop8:
 | 
			
		||||
loop8:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
        ldmia       r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
        orr         r3, r3, r4,     lsl #24
 | 
			
		||||
@@ -318,13 +308,13 @@ ENTRY(memcpy)
 | 
			
		||||
        stmia       r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
 | 
			
		||||
        mov         r3, r11,        lsr #8
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        b           .Lless_than_thirtytwo
 | 
			
		||||
        b           less_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
.Lloop24:
 | 
			
		||||
loop24:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
        ldmia       r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
        orr         r3, r3, r4,     lsl #8
 | 
			
		||||
@@ -347,12 +337,12 @@ ENTRY(memcpy)
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.Lless_than_thirtytwo:
 | 
			
		||||
less_than_thirtytwo:
 | 
			
		||||
        /* copy the last 0 to 31 bytes of the source */
 | 
			
		||||
        rsb         r12, lr, #32        /* we corrupted r12, recompute it  */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lpartial_word_tail
 | 
			
		||||
        blo         partial_word_tail
 | 
			
		||||
 | 
			
		||||
1:      ldr         r5, [r1], #4
 | 
			
		||||
        sub         r2, r2, #4
 | 
			
		||||
@@ -362,51 +352,29 @@ ENTRY(memcpy)
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
.Lpartial_word_tail:
 | 
			
		||||
partial_word_tail:
 | 
			
		||||
        /* we have a partial word in the input buffer */
 | 
			
		||||
        movs        r5, lr, lsl #(31-3)
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        /* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
        ldmfd       sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
.Lcopy_last_3_and_return:
 | 
			
		||||
copy_last_3_and_return:
 | 
			
		||||
        movs        r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
 | 
			
		||||
        ldrbmi      r2, [r1], #1
 | 
			
		||||
        ldrbcs      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1]
 | 
			
		||||
        strbmi      r2, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0]
 | 
			
		||||
        ldrmib      r2, [r1], #1
 | 
			
		||||
        ldrcsb      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1]
 | 
			
		||||
        strmib      r2, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
        ldmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
        // Only reached when the __memcpy_chk check fails.
 | 
			
		||||
ENTRY_PRIVATE(__memcpy_chk_fail)
 | 
			
		||||
        // Preserve lr for backtrace.
 | 
			
		||||
        push    {lr}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset lr, 0
 | 
			
		||||
 | 
			
		||||
        ldr     r0, error_message
 | 
			
		||||
        ldr     r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add     r0, pc
 | 
			
		||||
        bl      __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word   error_string-(1b+8)
 | 
			
		||||
END(__memcpy_chk_fail)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memcpy: prevented write past end of buffer"
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,7 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memset() for ARM.
 | 
			
		||||
@@ -35,30 +34,9 @@
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         done
 | 
			
		||||
 | 
			
		||||
        ldr         r0, error_message
 | 
			
		||||
        ldr         r1, error_code
 | 
			
		||||
1:
 | 
			
		||||
        add         r0, pc
 | 
			
		||||
        bl          __fortify_chk_fail
 | 
			
		||||
error_code:
 | 
			
		||||
        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
 | 
			
		||||
error_message:
 | 
			
		||||
        .word       error_string-(1b+8)
 | 
			
		||||
 | 
			
		||||
END(__memset_chk)
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov     r2, r1
 | 
			
		||||
        mov     r1, #0
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
@@ -78,11 +56,11 @@ ENTRY(memset)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -102,9 +80,9 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -119,17 +97,13 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memset: prevented write past end of buffer"
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
	.text
 | 
			
		||||
 | 
			
		||||
@@ -52,8 +52,8 @@
 | 
			
		||||
#define magic2(REG) REG, lsl #7
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
	pld	[r0, #0]
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	PLD(r0, #0)
 | 
			
		||||
	PLD(r1, #0)
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
 | 
			
		||||
@@ -88,8 +88,8 @@ ENTRY(strcmp)
 | 
			
		||||
	orr	r4, r4, r4, lsl #16
 | 
			
		||||
	.p2align	2
 | 
			
		||||
4:
 | 
			
		||||
	pld	[r0, #8]
 | 
			
		||||
	pld	[r1, #8]
 | 
			
		||||
	PLD(r0, #8)
 | 
			
		||||
	PLD(r1, #8)
 | 
			
		||||
	sub	r2, ip, magic1(r4)
 | 
			
		||||
	cmp	ip, r3
 | 
			
		||||
	itttt	eq
 | 
			
		||||
 
 | 
			
		||||
@@ -1,135 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2008 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	mov	ip, r0
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
	bne	4f
 | 
			
		||||
	tst	r1, #3
 | 
			
		||||
	bne	3f
 | 
			
		||||
5:
 | 
			
		||||
	str	r5, [sp, #-4]!
 | 
			
		||||
	mov	r5, #0x01
 | 
			
		||||
	orr	r5, r5, r5, lsl #8
 | 
			
		||||
	orr	r5, r5, r5, lsl #16
 | 
			
		||||
 | 
			
		||||
	str	r4, [sp, #-4]!
 | 
			
		||||
	tst	r1, #4
 | 
			
		||||
	ldr	r3, [r1], #4
 | 
			
		||||
	beq	2f
 | 
			
		||||
	sub	r2, r3, r5
 | 
			
		||||
	bics	r2, r2, r3
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	itt	eq
 | 
			
		||||
	streq	r3, [ip], #4
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	bne	1f
 | 
			
		||||
       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
 | 
			
		||||
	  can safely fetch up to two words.  This allows us to avoid
 | 
			
		||||
	  load stalls.  */
 | 
			
		||||
	.p2align 2
 | 
			
		||||
2:
 | 
			
		||||
	pld	[r1, #8]
 | 
			
		||||
	ldr	r4, [r1], #4
 | 
			
		||||
	sub	r2, r3, r5
 | 
			
		||||
	bics	r2, r2, r3
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	sub	r2, r4, r5
 | 
			
		||||
	bne	1f
 | 
			
		||||
	str	r3, [ip], #4
 | 
			
		||||
	bics	r2, r2, r4
 | 
			
		||||
	tst	r2, r5, lsl #7
 | 
			
		||||
	itt	eq
 | 
			
		||||
	ldreq	r3, [r1], #4
 | 
			
		||||
	streq	r4, [ip], #4
 | 
			
		||||
	beq	2b
 | 
			
		||||
	mov	r3, r4
 | 
			
		||||
1:
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	rors	r3, r3, #24
 | 
			
		||||
#endif
 | 
			
		||||
	strb	r3, [ip], #1
 | 
			
		||||
	tst	r3, #0xff
 | 
			
		||||
#ifdef __ARMEL__
 | 
			
		||||
	ror	r3, r3, #8
 | 
			
		||||
#endif
 | 
			
		||||
	bne	1b
 | 
			
		||||
	ldr	r4, [sp], #4
 | 
			
		||||
	ldr	r5, [sp], #4
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
       /* Strings have the same offset from word alignment, but it's
 | 
			
		||||
	  not zero.  */
 | 
			
		||||
3:
 | 
			
		||||
	tst	r1, #1
 | 
			
		||||
	beq	1f
 | 
			
		||||
	ldrb	r2, [r1], #1
 | 
			
		||||
	strb	r2, [ip], #1
 | 
			
		||||
	cmp	r2, #0
 | 
			
		||||
	it	eq
 | 
			
		||||
	bxeq	lr
 | 
			
		||||
1:
 | 
			
		||||
	tst	r1, #2
 | 
			
		||||
	beq	5b
 | 
			
		||||
	ldrh	r2, [r1], #2
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	tst	r2, #0xff00
 | 
			
		||||
	iteet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	lsreq	r2, r2, #8
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff
 | 
			
		||||
#else
 | 
			
		||||
	tst	r2, #0xff
 | 
			
		||||
	itet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff00
 | 
			
		||||
#endif
 | 
			
		||||
	bne	5b
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
       /* src and dst do not have a common word-alignement.  Fall back to
 | 
			
		||||
	  byte copying.  */
 | 
			
		||||
4:
 | 
			
		||||
	ldrb	r2, [r1], #1
 | 
			
		||||
	strb	r2, [ip], #1
 | 
			
		||||
	cmp	r2, #0
 | 
			
		||||
	bne	4b
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(strcpy)
 | 
			
		||||
@@ -1,136 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * 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 COPYRIGHT HOLDERS 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
 | 
			
		||||
 * COPYRIGHT OWNER 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 <string.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
size_t strlen(const char *s)
 | 
			
		||||
{
 | 
			
		||||
    __builtin_prefetch(s);
 | 
			
		||||
    __builtin_prefetch(s+32);
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        const char      *b;
 | 
			
		||||
        const uint32_t  *w;
 | 
			
		||||
        uintptr_t       i;
 | 
			
		||||
    } u;
 | 
			
		||||
 | 
			
		||||
    // these are some scratch variables for the asm code below
 | 
			
		||||
    uint32_t v, t;
 | 
			
		||||
 | 
			
		||||
    // initialize the string length to zero
 | 
			
		||||
    size_t l = 0;
 | 
			
		||||
 | 
			
		||||
    // align the pointer to a 32-bit word boundary
 | 
			
		||||
    u.b = s;
 | 
			
		||||
    while (u.i & 0x3)  {
 | 
			
		||||
        if (__builtin_expect(*u.b++ == 0, 0)) {
 | 
			
		||||
            goto done;
 | 
			
		||||
        }
 | 
			
		||||
        l++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // loop for each word, testing if it contains a zero byte
 | 
			
		||||
    // if so, exit the loop and update the length.
 | 
			
		||||
    // We need to process 32 bytes per loop to schedule PLD properly
 | 
			
		||||
    // and achieve the maximum bus speed.
 | 
			
		||||
    asm(
 | 
			
		||||
        "ldr     %[v], [%[s]], #4           \n"
 | 
			
		||||
        "sub     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "0:                                 \n"
 | 
			
		||||
        "pld     [%[s], #64]                \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
#if !defined(__OPTIMIZE_SIZE__)
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
#endif
 | 
			
		||||
        "beq     0b                         \n"
 | 
			
		||||
        "1:                                 \n"
 | 
			
		||||
        "add     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "tst     %[v], #0xFF                \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF00              \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF0000            \n"
 | 
			
		||||
        "it      ne                         \n"
 | 
			
		||||
        "addne   %[l], %[l], #1             \n"
 | 
			
		||||
        "2:                                 \n"
 | 
			
		||||
        : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
 | 
			
		||||
        : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
 | 
			
		||||
        : "cc"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
    return l;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,3 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
    arch-arm/generic/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/memset.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/strlen.c \
 | 
			
		||||
    bionic/__strcat_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/memmove.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/generic/bionic/memcpy.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/generic/bionic/memset.S)
 | 
			
		||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/generic/bionic/strcmp.S)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								libc/arch-arm/include/machine/_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								libc/arch-arm/include/machine/_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
/*	$OpenBSD: _types.h,v 1.3 2006/02/14 18:12:58 miod Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 1990, 1993
 | 
			
		||||
 *	The Regents of the University of California.  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. 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 REGENTS 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 REGENTS 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.
 | 
			
		||||
 *
 | 
			
		||||
 *	@(#)types.h	8.3 (Berkeley) 1/5/94
 | 
			
		||||
 *	@(#)ansi.h	8.2 (Berkeley) 1/4/94
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM__TYPES_H_
 | 
			
		||||
#define _ARM__TYPES_H_
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.1 Exact-width integer types */
 | 
			
		||||
typedef	__signed char		__int8_t;
 | 
			
		||||
typedef	unsigned char		__uint8_t;
 | 
			
		||||
typedef	short			__int16_t;
 | 
			
		||||
typedef	unsigned short		__uint16_t;
 | 
			
		||||
typedef	int			__int32_t;
 | 
			
		||||
typedef	unsigned int		__uint32_t;
 | 
			
		||||
/* LONGLONG */
 | 
			
		||||
typedef	long long		__int64_t;
 | 
			
		||||
/* LONGLONG */
 | 
			
		||||
typedef	unsigned long long	__uint64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.2 Minimum-width integer types */
 | 
			
		||||
typedef	__int8_t		__int_least8_t;
 | 
			
		||||
typedef	__uint8_t		__uint_least8_t;
 | 
			
		||||
typedef	__int16_t		__int_least16_t;
 | 
			
		||||
typedef	__uint16_t		__uint_least16_t;
 | 
			
		||||
typedef	__int32_t		__int_least32_t;
 | 
			
		||||
typedef	__uint32_t		__uint_least32_t;
 | 
			
		||||
typedef	__int64_t		__int_least64_t;
 | 
			
		||||
typedef	__uint64_t		__uint_least64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.3 Fastest minimum-width integer types */
 | 
			
		||||
typedef	__int32_t		__int_fast8_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast8_t;
 | 
			
		||||
typedef	__int32_t		__int_fast16_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast16_t;
 | 
			
		||||
typedef	__int32_t		__int_fast32_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast32_t;
 | 
			
		||||
typedef	__int64_t		__int_fast64_t;
 | 
			
		||||
typedef	__uint64_t		__uint_fast64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.4 Integer types capable of holding object pointers */
 | 
			
		||||
typedef	int 			__intptr_t;
 | 
			
		||||
typedef	unsigned int 		__uintptr_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.5 Greatest-width integer types */
 | 
			
		||||
typedef	__int64_t		__intmax_t;
 | 
			
		||||
typedef	__uint64_t		__uintmax_t;
 | 
			
		||||
 | 
			
		||||
/* Register size */
 | 
			
		||||
typedef __int32_t		__register_t;
 | 
			
		||||
 | 
			
		||||
/* VM system types */
 | 
			
		||||
typedef unsigned long		__vaddr_t;
 | 
			
		||||
typedef unsigned long		__paddr_t;
 | 
			
		||||
typedef unsigned long		__vsize_t;
 | 
			
		||||
typedef unsigned long		__psize_t;
 | 
			
		||||
 | 
			
		||||
/* Standard system types */
 | 
			
		||||
typedef int			__clock_t;
 | 
			
		||||
typedef int			__clockid_t;
 | 
			
		||||
typedef double			__double_t;
 | 
			
		||||
typedef float			__float_t;
 | 
			
		||||
typedef long			__ptrdiff_t;
 | 
			
		||||
typedef	int			__time_t;
 | 
			
		||||
typedef int			__timer_t;
 | 
			
		||||
#if defined(__GNUC__) && __GNUC__ >= 3
 | 
			
		||||
typedef	__builtin_va_list	__va_list;
 | 
			
		||||
#else
 | 
			
		||||
typedef	char *			__va_list;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Wide character support types */
 | 
			
		||||
#ifndef __cplusplus
 | 
			
		||||
typedef	int			__wchar_t;
 | 
			
		||||
#endif
 | 
			
		||||
typedef int			__wint_t;
 | 
			
		||||
typedef	int			__rune_t;
 | 
			
		||||
typedef	void *			__wctrans_t;
 | 
			
		||||
typedef	void *			__wctype_t;
 | 
			
		||||
 | 
			
		||||
#endif	/* _ARM__TYPES_H_ */
 | 
			
		||||
@@ -38,14 +38,107 @@
 | 
			
		||||
#ifndef _ARM32_ASM_H_
 | 
			
		||||
#define _ARM32_ASM_H_
 | 
			
		||||
 | 
			
		||||
#define __bionic_asm_align 0
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
# define _C_LABEL(x)	x
 | 
			
		||||
#else
 | 
			
		||||
# ifdef __STDC__
 | 
			
		||||
#  define _C_LABEL(x)	_ ## x
 | 
			
		||||
# else
 | 
			
		||||
#  define _C_LABEL(x)	_/**/x
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
#define	_ASM_LABEL(x)	x
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_custom_entry
 | 
			
		||||
#undef __bionic_asm_custom_end
 | 
			
		||||
#define __bionic_asm_custom_entry(f) .fnstart
 | 
			
		||||
#define __bionic_asm_custom_end(f) .fnend
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
# define __CONCAT(x,y)	x ## y
 | 
			
		||||
# define __STRING(x)	#x
 | 
			
		||||
#else
 | 
			
		||||
# define __CONCAT(x,y)	x/**/y
 | 
			
		||||
# define __STRING(x)	"x"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_function_type
 | 
			
		||||
#define __bionic_asm_function_type #function
 | 
			
		||||
#ifndef _ALIGN_TEXT
 | 
			
		||||
# define _ALIGN_TEXT .align 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * gas/arm uses @ as a single comment character and thus cannot be used here
 | 
			
		||||
 * Instead it recognised the # instead of an @ symbols in .type directives
 | 
			
		||||
 * We define a couple of macros so that assembly code will not be dependant
 | 
			
		||||
 * on one or the other.
 | 
			
		||||
 */
 | 
			
		||||
#define _ASM_TYPE_FUNCTION	#function
 | 
			
		||||
#define _ASM_TYPE_OBJECT	#object
 | 
			
		||||
#define _ENTRY(x) \
 | 
			
		||||
	.text; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; x: .fnstart
 | 
			
		||||
 | 
			
		||||
#define _ASM_SIZE(x)	.size x, .-x;
 | 
			
		||||
 | 
			
		||||
#define _END(x) \
 | 
			
		||||
	.fnend; \
 | 
			
		||||
	_ASM_SIZE(x)
 | 
			
		||||
 | 
			
		||||
#ifdef GPROF
 | 
			
		||||
# ifdef __ELF__
 | 
			
		||||
#  define _PROF_PROLOGUE	\
 | 
			
		||||
	mov ip, lr; bl __mcount
 | 
			
		||||
# else
 | 
			
		||||
#  define _PROF_PROLOGUE	\
 | 
			
		||||
	mov ip,lr; bl mcount
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
# define _PROF_PROLOGUE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	ENTRY(y)	_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
 | 
			
		||||
#define	ENTRY_NP(y)	_ENTRY(_C_LABEL(y))
 | 
			
		||||
#define	END(y)		_END(_C_LABEL(y))
 | 
			
		||||
#define	ASENTRY(y)	_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
 | 
			
		||||
#define	ASENTRY_NP(y)	_ENTRY(_ASM_LABEL(y))
 | 
			
		||||
#define	ASEND(y)	_END(_ASM_LABEL(y))
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define ENTRY_PRIVATE(y)  ENTRY(y); .hidden _C_LABEL(y)
 | 
			
		||||
#else
 | 
			
		||||
#define ENTRY_PRIVATE(y)  ENTRY(y)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	ASMSTR		.asciz
 | 
			
		||||
 | 
			
		||||
#if defined(__ELF__) && defined(PIC)
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
#define	PIC_SYM(x,y)	x ## ( ## y ## )
 | 
			
		||||
#else
 | 
			
		||||
#define	PIC_SYM(x,y)	x/**/(/**/y/**/)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define	PIC_SYM(x,y)	x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define RCSID(x)	.section ".ident"; .asciz x
 | 
			
		||||
#else
 | 
			
		||||
#define RCSID(x)	.text; .asciz x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define	WEAK_ALIAS(alias,sym)						\
 | 
			
		||||
	.weak alias;							\
 | 
			
		||||
	alias = sym
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg ## ,30,0,0,0 ;					\
 | 
			
		||||
	.stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0
 | 
			
		||||
#elif defined(__ELF__)
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg,30,0,0,0 ;						\
 | 
			
		||||
	.stabs __STRING(sym),1,0,0,0
 | 
			
		||||
#else
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg,30,0,0,0 ;						\
 | 
			
		||||
	.stabs __STRING(_/**/sym),1,0,0,0
 | 
			
		||||
#endif /* __STDC__ */
 | 
			
		||||
 | 
			
		||||
#endif /* !_ARM_ASM_H_ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								libc/arch-arm/include/machine/cdefs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								libc/arch-arm/include/machine/cdefs.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
/*	$OpenBSD: cdefs.h,v 1.2 2005/11/24 20:46:44 deraadt Exp $	*/
 | 
			
		||||
 | 
			
		||||
#ifndef	_MACHINE_CDEFS_H_
 | 
			
		||||
#define	_MACHINE_CDEFS_H_
 | 
			
		||||
 | 
			
		||||
#if defined(lint)
 | 
			
		||||
#define __indr_reference(sym,alias)	__lint_equal__(sym,alias)
 | 
			
		||||
#define __warn_references(sym,msg)
 | 
			
		||||
#define __weak_alias(alias,sym)		__lint_equal__(sym,alias)
 | 
			
		||||
#elif defined(__GNUC__) && defined(__STDC__)
 | 
			
		||||
#define __weak_alias(alias,sym)					\
 | 
			
		||||
	__asm__(".weak " __STRING(alias) " ; " __STRING(alias)	\
 | 
			
		||||
	    " = " __STRING(sym));
 | 
			
		||||
#define	__warn_references(sym,msg)				\
 | 
			
		||||
	__asm__(".section .gnu.warning." __STRING(sym)		\
 | 
			
		||||
	    " ; .ascii \"" msg "\" ; .text");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* !_MACHINE_CDEFS_H_ */
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user