Compare commits
	
		
			1 Commits
		
	
	
		
			android-6.
			...
			ics-mr1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					fc89980c7b | 
@@ -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
 | 
			
		||||
# ************************************************
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
 | 
			
		||||
Bionic support for SuperH
 | 
			
		||||
-------------------------
 | 
			
		||||
Bionic support for SuperH architecture is written by
 | 
			
		||||
Shin-ichiro KAWASAKI <shinichiro.kawasaki.mg@hitachi.com>
 | 
			
		||||
and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
 | 
			
		||||
							
								
								
									
										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>
 | 
			
		||||
							
								
								
									
										10
									
								
								ThirdPartyProject.prop
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								ThirdPartyProject.prop
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Copyright 2010 Google Inc. All Rights Reserved.
 | 
			
		||||
#Fri Jul 16 10:03:08 PDT 2010
 | 
			
		||||
currentVersion=Unknown
 | 
			
		||||
version=Unknown
 | 
			
		||||
isNative=true
 | 
			
		||||
feedurl=http\://www.openbsd.org/security.html
 | 
			
		||||
name=openbsd
 | 
			
		||||
keywords=openbsd
 | 
			
		||||
onDevice=true
 | 
			
		||||
homepage=http\://openbsd.org
 | 
			
		||||
@@ -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
 | 
			
		||||
							
								
								
									
										1986
									
								
								libc/Android.mk
									
									
									
									
									
								
							
							
						
						
									
										1986
									
								
								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
 | 
			
		||||
							
								
								
									
										441
									
								
								libc/Jamfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								libc/Jamfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,441 @@
 | 
			
		||||
# This file is used to build the Bionic library with the Jam build
 | 
			
		||||
# tool. For info, see www.perforce.com/jam/jam.html
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
BIONIC_TOP ?= $(DOT) ;
 | 
			
		||||
 | 
			
		||||
DEBUG = 1 ;
 | 
			
		||||
 | 
			
		||||
# pattern used for automatic heade inclusion detection
 | 
			
		||||
HDRPATTERN = "^[ 	]*#[ 	]*include[ 	]*[<\"]([^\">]*)[\">].*$" ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# debugging support, simply define the DEBUG variable to activate verbose output
 | 
			
		||||
rule Debug
 | 
			
		||||
{
 | 
			
		||||
    if $(DEBUG) {
 | 
			
		||||
        Echo $(1) ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# return all elements from $(1) that are not in $(2)
 | 
			
		||||
rule Filter  list : filter
 | 
			
		||||
{
 | 
			
		||||
    local result = ;
 | 
			
		||||
    local item ;
 | 
			
		||||
    for item in $(list) {
 | 
			
		||||
        if ! $(item) in $(filter) {
 | 
			
		||||
            result += $(item) ;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return $(result) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# reverse a list of elements
 | 
			
		||||
rule Reverse  list
 | 
			
		||||
{
 | 
			
		||||
    local  result = ;
 | 
			
		||||
    local  item ;
 | 
			
		||||
 | 
			
		||||
    for item in $(list) {
 | 
			
		||||
        result = $(item) $(result) ;
 | 
			
		||||
    }
 | 
			
		||||
    return $(result) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# decompose a path into a list of elements
 | 
			
		||||
rule PathDecompose  dir
 | 
			
		||||
{
 | 
			
		||||
    local  result ;
 | 
			
		||||
 | 
			
		||||
    while $(dir:D)
 | 
			
		||||
    {
 | 
			
		||||
        if ! $(dir:BS) {  # for rooted paths like "/foo"
 | 
			
		||||
            break ;
 | 
			
		||||
        }
 | 
			
		||||
        result = $(dir:BS) $(result) ;
 | 
			
		||||
        dir    = $(dir:D) ;
 | 
			
		||||
    }
 | 
			
		||||
    result = $(dir) $(result) ;
 | 
			
		||||
    return $(result) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# simply a file path, i.e. get rid of . or .. when possible
 | 
			
		||||
rule _PathSimplify  dir
 | 
			
		||||
{
 | 
			
		||||
    local  result = ;
 | 
			
		||||
    local  dir2 d ;
 | 
			
		||||
 | 
			
		||||
    dir  = [ PathDecompose $(dir) ] ;
 | 
			
		||||
 | 
			
		||||
    # get rid of any single dot
 | 
			
		||||
    dir2 = ;
 | 
			
		||||
    for d in $(dir) {
 | 
			
		||||
        if $(d) = "." {
 | 
			
		||||
            continue ;
 | 
			
		||||
        }
 | 
			
		||||
        dir2 += $(d) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # get rid of .. when possible
 | 
			
		||||
    for d in $(dir2) {
 | 
			
		||||
        if $(d) = ".." && $(result) {
 | 
			
		||||
            result = $(result[2-]) ;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            result = $(d) $(result) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # now invert the result
 | 
			
		||||
    result = [ Reverse $(result) ] ;
 | 
			
		||||
    if ! $(result) {
 | 
			
		||||
        result = "." ;
 | 
			
		||||
    }
 | 
			
		||||
    return $(result:J="/") ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
rule PathSimplify  dirs
 | 
			
		||||
{
 | 
			
		||||
    local result ;
 | 
			
		||||
    local d ;
 | 
			
		||||
    for d in $(dirs) {
 | 
			
		||||
        result += [ _PathSimplify $(d) ] ;
 | 
			
		||||
    }
 | 
			
		||||
    return $(result) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# retrieve list of subdirectories
 | 
			
		||||
rule ListSubDirs  paths
 | 
			
		||||
{
 | 
			
		||||
    local  result  = ;
 | 
			
		||||
    local  entry ;
 | 
			
		||||
    for entry in [ Glob $(paths) : * ] {
 | 
			
		||||
        if ! $(entry:S) {
 | 
			
		||||
            result += $(entry) ;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return [ PathSimplify $(result) ] ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# retrieve list of sources in a given directory
 | 
			
		||||
rule ListSources  path
 | 
			
		||||
{
 | 
			
		||||
    return [ Glob $(path) : *.S *.c ] ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# find the prebuilt directory
 | 
			
		||||
#
 | 
			
		||||
if ! $(TOP) {
 | 
			
		||||
    Echo "Please define TOP as the root of your device build tree" ;
 | 
			
		||||
    Exit ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Debug "OS is" $(OS) ;
 | 
			
		||||
Debug "CPU is" $(CPU) ;
 | 
			
		||||
 | 
			
		||||
if $(OS) = LINUX
 | 
			
		||||
{
 | 
			
		||||
    PREBUILT = $(TOP)/prebuilt/Linux ;
 | 
			
		||||
}
 | 
			
		||||
else if $(OS) = MACOSX
 | 
			
		||||
{
 | 
			
		||||
    switch $(CPU) {
 | 
			
		||||
        case i386 : PREBUILT = $(TOP)/prebuilt/darwin-x86 ; break ;
 | 
			
		||||
        case ppc  : PREBUILT = $(TOP)/prebuilt/darwin-ppc ; break ;
 | 
			
		||||
        case *    : Echo "unsupported CPU" "$(CPU) !!" ;
 | 
			
		||||
                    Echo "Please contact digit@google.com for help" ;
 | 
			
		||||
                    Exit ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
else
 | 
			
		||||
{
 | 
			
		||||
    Echo "Unsupported operating system" $(OS) ;
 | 
			
		||||
    Echo "Please contact digit@google.com for help" ;
 | 
			
		||||
    Exit ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Debug "TOP is" $(TOP) ;
 | 
			
		||||
Debug "PREBUILT is" $(PREBUILT) ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# check architectures and setup toolchain variables
 | 
			
		||||
#
 | 
			
		||||
SUPPORTED_ARCHS = x86 arm ;
 | 
			
		||||
 | 
			
		||||
ARCH ?= $(SUPPORTED_ARCHS) ;
 | 
			
		||||
 | 
			
		||||
if ! $(ARCH) in $(SUPPORTED_ARCHS) {
 | 
			
		||||
    Echo "The variable ARCH contains an unsupported value, use one or more of these instead" ;
 | 
			
		||||
    Echo "separated by spaces:" $(SUPPORTED_ARCHS) ;
 | 
			
		||||
    Exit ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
x86_TOOLSET_PREFIX ?= "" ;
 | 
			
		||||
arm_TOOLSET_PREFIX ?= $(TOP)/prebuilt/Linux/toolchain-4.1.1/bin/arm-elf- ;
 | 
			
		||||
 | 
			
		||||
for arch in $(ARCH) {
 | 
			
		||||
    CC_$(arch)  = $($(arch)_TOOLSET_PREFIX)gcc ;
 | 
			
		||||
    C++_$(arch) = $($(arch)_TOOLSET_PREFIX)g++ ;
 | 
			
		||||
    AR_$(arch)  = $($(arch)_TOOLSET_PREFIX)ar ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# the list of arch-independent source subdirectories
 | 
			
		||||
BIONIC_SRC_SUBDIRS = string ;
 | 
			
		||||
BIONIC_x86_SUBDIRS = ;
 | 
			
		||||
BIONIC_arm_SUBDIRS = ;
 | 
			
		||||
 | 
			
		||||
CFLAGS   = -O0 -g -W ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# find sources in a given list of subdirectories
 | 
			
		||||
rule FindSources  dirs
 | 
			
		||||
{
 | 
			
		||||
    local dir ;
 | 
			
		||||
 | 
			
		||||
    for dir in $(dirs)
 | 
			
		||||
    {
 | 
			
		||||
        local LOCAL_SRC NO_LOCAL_SRC ;
 | 
			
		||||
 | 
			
		||||
        if [ Glob $(dir) : rules.jam ] {
 | 
			
		||||
            include $(dir)/rules.jam ;
 | 
			
		||||
            if $(LOCAL_SRC) {
 | 
			
		||||
                _sources = $(LOCAL_SRC) ;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                _sources = [ Glob $(dir) : *.S *.c ] ;
 | 
			
		||||
                _sources = $(_sources:BS) ;
 | 
			
		||||
            }
 | 
			
		||||
            if $(NO_LOCAL_SRC) {
 | 
			
		||||
                _sources = [ Filter $(_sources) : $(NO_LOCAL_SRC) ] ;
 | 
			
		||||
            }
 | 
			
		||||
            sources += $(dir)/$(_sources) ;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            sources += [ ListSources $(dir) ] ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Compile a given object file from a source
 | 
			
		||||
rule Compile  object : source
 | 
			
		||||
{
 | 
			
		||||
    Depends $(object) : $(source) ;
 | 
			
		||||
    Depends bionic : $(object) ;
 | 
			
		||||
    Clean clean : $(object) ;
 | 
			
		||||
 | 
			
		||||
    MakeLocate $(object) : $(OUT) ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    CC on $(object)       = $(CC_$(arch)) ;
 | 
			
		||||
    CFLAGS on $(object)   = $(CFLAGS) ;
 | 
			
		||||
    INCLUDES on $(object) = $(INCLUDES) ;
 | 
			
		||||
    DEFINES on $(object)  = $(DEFINES) ;
 | 
			
		||||
 | 
			
		||||
    HDRRULE on $(>) = HdrRule ;
 | 
			
		||||
    HDRSCAN on $(>) = $(HDRPATTERN) ;
 | 
			
		||||
    HDRSEARCH on $(>) = $(INCLUDES) ;
 | 
			
		||||
    HDRGRIST on $(>) = $(HDRGRIST) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
actions Compile
 | 
			
		||||
{
 | 
			
		||||
    $(CC) -c -o $(1) $(CFLAGS) -I$(INCLUDES) -D$(DEFINES) $(2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
rule RmTemps
 | 
			
		||||
{
 | 
			
		||||
    Temporary $(2) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
actions quietly updated piecemeal together RmTemps
 | 
			
		||||
{
 | 
			
		||||
    rm -f $(2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
actions Archive
 | 
			
		||||
{
 | 
			
		||||
    $(AR) ru $(1) $(2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rule Library  library : objects
 | 
			
		||||
{
 | 
			
		||||
    local  obj ;
 | 
			
		||||
 | 
			
		||||
    if ! $(library:S) {
 | 
			
		||||
        library = $(library:S=.a) ;
 | 
			
		||||
    }
 | 
			
		||||
    library = $(library:G=<$(arch)>) ;
 | 
			
		||||
 | 
			
		||||
    Depends all : $(library) ;
 | 
			
		||||
 | 
			
		||||
    if ! $(library:D) {
 | 
			
		||||
        MakeLocate $(library) $(library)($(objects:BS)) : $(OUT) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Depends $(library) : $(library)($(objects:BS)) ;
 | 
			
		||||
    for obj in $(objects) {
 | 
			
		||||
        Depends $(library)($(obj:BS)) : $(obj) ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Clean clean : $(library) ;
 | 
			
		||||
 | 
			
		||||
    AR on $(library) = $(AR_$(arch)) ;
 | 
			
		||||
    Archive $(library) : $(objects) ;
 | 
			
		||||
 | 
			
		||||
    RmTemps $(library) : $(objects) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
rule  ProcessDir
 | 
			
		||||
{
 | 
			
		||||
    local CFLAGS   = $(CFLAGS) ;
 | 
			
		||||
    local DEFINES  = $(DEFINES) ;
 | 
			
		||||
    local INCLUDES = $(INCLUDES) ;
 | 
			
		||||
    local local_rules = [ Glob $(1) : rules.jam ] ;
 | 
			
		||||
    local source sources ;
 | 
			
		||||
 | 
			
		||||
    if $(local_rules) {
 | 
			
		||||
        local LOCAL_CFLAGS LOCAL_DEFINES LOCAL_INCLUDES LOCAL_SRC NO_LOCAL_SRC ;
 | 
			
		||||
 | 
			
		||||
        include $(local_rules) ;
 | 
			
		||||
        CFLAGS   += $(LOCAL_CFLAGS) ;
 | 
			
		||||
        DEFINES  += $(LOCAL_DEFINES) ;
 | 
			
		||||
        INCLUDES += $(LOCAL_INCLUDES) ;
 | 
			
		||||
 | 
			
		||||
        if $(LOCAL_SRC) {
 | 
			
		||||
            sources = $(LOCAL_SRC) ;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            sources = [ Glob $(1) : *.S *.c ] ;
 | 
			
		||||
            sources = $(sources:BS) ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if $(NO_LOCAL_SRC) {
 | 
			
		||||
            sources = [ Filter $(sources) : $(NO_LOCAL_SRC) ] ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sources = $(1)/$(sources) ;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        sources = [ Glob $(1) : *.S *.c ] ;
 | 
			
		||||
 | 
			
		||||
    for source in $(sources) {
 | 
			
		||||
        local name = $(source:B) ;
 | 
			
		||||
 | 
			
		||||
        if $(source:S) = ".S" {
 | 
			
		||||
            # record the list of assembler sources
 | 
			
		||||
            ASSEMBLER_SOURCES += $(name) ;
 | 
			
		||||
        }
 | 
			
		||||
        else if $(source:S) = ".c" && $(name) in $(ASSEMBLER_SOURCES) {
 | 
			
		||||
            # skip C source file if corresponding assembler exists
 | 
			
		||||
            continue ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        objname = <$(arch)>$(name).o  ;
 | 
			
		||||
 | 
			
		||||
        Compile $(objname) : $(source) ;
 | 
			
		||||
        ALL_OBJECTS += $(objname) ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rule ProcessDirs
 | 
			
		||||
{
 | 
			
		||||
    local  dir ;
 | 
			
		||||
    for dir in $(1) {
 | 
			
		||||
        ProcessDir $(dir) ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INCLUDES_x86 = /usr/src/linux/include ;
 | 
			
		||||
 | 
			
		||||
INCLUDES_arm = ../kernel_headers
 | 
			
		||||
               include/arch/arm
 | 
			
		||||
               include/bits32
 | 
			
		||||
               ;
 | 
			
		||||
 | 
			
		||||
INCLUDES = include stdio string stdlib .
 | 
			
		||||
           ../msun/include
 | 
			
		||||
           ;
 | 
			
		||||
 | 
			
		||||
DEFINES  = ANDROID_CHANGES
 | 
			
		||||
           USE_LOCKS
 | 
			
		||||
           REALLOC_ZERO_BYTES_FREES
 | 
			
		||||
           _LIBC=1
 | 
			
		||||
           SOFTFLOAT
 | 
			
		||||
           FLOATING_POINT
 | 
			
		||||
           NEED_PSELECT=1
 | 
			
		||||
           ANDROID
 | 
			
		||||
           ;
 | 
			
		||||
 | 
			
		||||
CFLAGS_x86 = ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for arch in $(ARCH)
 | 
			
		||||
{
 | 
			
		||||
    local ARCH_DIR = $(BIONIC_TOP)/arch-$(arch) ;
 | 
			
		||||
    local INCLUDES = $(INCLUDES_$(arch)) $(ARCH_DIR)/include $(INCLUDES) ;
 | 
			
		||||
    local DEFINES  = $(DEFINES_$(arch)) $(DEFINES) ARCH=$(arch)  ;
 | 
			
		||||
    local CFLAGS   = $(CFLAGS) $(CFLAGS_$(arch)) ;
 | 
			
		||||
    local OUT      = out/$(arch) ;
 | 
			
		||||
    local ASSEMBLER_SOURCES ALL_OBJECTS ;
 | 
			
		||||
 | 
			
		||||
    ProcessDirs [ ListSubDirs $(ARCH_DIR) ] ;
 | 
			
		||||
    ProcessDirs stdlib stdio unistd string tzcode inet ;
 | 
			
		||||
    ProcessDirs [ ListSubDirs netbsd ] ;
 | 
			
		||||
    ProcessDirs bionic ;
 | 
			
		||||
 | 
			
		||||
    Library bionic : $(ALL_OBJECTS) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BIONIC_SEARCH = $(BIONIC_TOP)/include ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# /HdrRule source : headers ;
 | 
			
		||||
#
 | 
			
		||||
# Arranges the proper dependencies when the file _source_ includes the files
 | 
			
		||||
# _headers_ through the #include C preprocessor directive
 | 
			
		||||
#
 | 
			
		||||
# this rule is not intendend to be called explicitely. It is called
 | 
			
		||||
# automatically during header scanning on sources handled by the @Object
 | 
			
		||||
# rule (e.g. sources in @Main or @Library rules)
 | 
			
		||||
#
 | 
			
		||||
rule HdrRule
 | 
			
		||||
{
 | 
			
		||||
    # HdrRule source : headers ;
 | 
			
		||||
 | 
			
		||||
    # N.B.  This rule is called during binding, potentially after
 | 
			
		||||
    # the fate of many targets has been determined, and must be
 | 
			
		||||
    # used with caution: don't add dependencies to unrelated
 | 
			
		||||
    # targets, and don't set variables on $(<).
 | 
			
		||||
 | 
			
		||||
    # Tell Jam that anything depending on $(<) also depends on $(>),
 | 
			
		||||
    # set SEARCH so Jam can find the headers, but then say we don't
 | 
			
		||||
    # care if we can't actually find the headers (they may have been
 | 
			
		||||
    # within ifdefs),
 | 
			
		||||
 | 
			
		||||
    local s = $(>:G=$(HDRGRIST:E)) ;
 | 
			
		||||
 | 
			
		||||
    Includes $(<) : $(s) ;
 | 
			
		||||
    SEARCH on $(s) = $(HDRSEARCH) ;
 | 
			
		||||
    NoCare $(s) ;
 | 
			
		||||
 | 
			
		||||
    # Propagate on $(<) to $(>)
 | 
			
		||||
 | 
			
		||||
    HDRSEARCH on $(s) = $(HDRSEARCH) ;
 | 
			
		||||
    HDRSCAN on $(s) = $(HDRSCAN) ;
 | 
			
		||||
    HDRRULE on $(s) = $(HDRRULE) ;
 | 
			
		||||
    HDRGRIST on $(s) = $(HDRGRIST) ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5014
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										5014
									
								
								libc/NOTICE
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										54
									
								
								libc/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								libc/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
Welcome to Bionic, Android's small and custom C library for the Android
 | 
			
		||||
platform.
 | 
			
		||||
 | 
			
		||||
Bionic is mainly a port of the BSD C library to our Linux kernel with the
 | 
			
		||||
following additions/changes:
 | 
			
		||||
 | 
			
		||||
- no support for locales
 | 
			
		||||
- no support for wide chars (i.e. multi-byte characters)
 | 
			
		||||
- its own smallish implementation of pthreads based on Linux futexes
 | 
			
		||||
- support for x86, ARM and ARM thumb CPU instruction sets and kernel interfaces
 | 
			
		||||
 | 
			
		||||
Bionic is released under the standard 3-clause BSD License
 | 
			
		||||
 | 
			
		||||
Bionic doesn't want to implement all features of a traditional C library, we only
 | 
			
		||||
add features to it as we need them, and we try to keep things as simple and small
 | 
			
		||||
as possible. Our goal is not to support scaling to thousands of concurrent threads
 | 
			
		||||
on multi-processors machines; we're running this on cell-phones, damnit !!
 | 
			
		||||
 | 
			
		||||
Note that Bionic doesn't provide a libthread_db or a libm implementation.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Adding new syscalls:
 | 
			
		||||
====================
 | 
			
		||||
 | 
			
		||||
Bionic provides the gensyscalls.py Python script to automatically generate syscall
 | 
			
		||||
stubs from the list defined in the file SYSCALLS.TXT. You can thus add a new syscall
 | 
			
		||||
by doing the following:
 | 
			
		||||
 | 
			
		||||
- edit SYSCALLS.TXT
 | 
			
		||||
- add a new line describing your syscall, it should look like:
 | 
			
		||||
 | 
			
		||||
   return_type  syscall_name(parameters)    syscall_number
 | 
			
		||||
 | 
			
		||||
- in the event where you want to differentiate the syscall function from its entry name,
 | 
			
		||||
  use the alternate:
 | 
			
		||||
 | 
			
		||||
   return_type  funcname:syscall_name(parameters)  syscall_number
 | 
			
		||||
 | 
			
		||||
- additionally, if the syscall number is different between ARM and x86, use:
 | 
			
		||||
 | 
			
		||||
   return_type  funcname[:syscall_name](parameters)   arm_number,x86_number
 | 
			
		||||
 | 
			
		||||
- a syscall number can be -1 to indicate that the syscall is not implemented on
 | 
			
		||||
  a given platform, for example:
 | 
			
		||||
 | 
			
		||||
   void   __set_tls(void*)   arm_number,-1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
the comments in SYSCALLS.TXT contain more information about the line format
 | 
			
		||||
 | 
			
		||||
You can also use the 'checksyscalls.py' script to check that all the syscall
 | 
			
		||||
numbers you entered are correct. It does so by looking at the values defined in
 | 
			
		||||
your Linux kernel headers. The script indicates where the values are incorrect
 | 
			
		||||
and what is expected instead.
 | 
			
		||||
@@ -1,339 +1,274 @@
 | 
			
		||||
# This file is used to automatically generate bionic's system call stubs.
 | 
			
		||||
# this file is used to list all the syscalls that will be supported by
 | 
			
		||||
# the Bionic C library. It is used to automatically generate the syscall
 | 
			
		||||
# stubs, the list of syscall constants (__NR_xxxx) and the content of <linux/_unitsd.h>
 | 
			
		||||
#
 | 
			
		||||
# 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])  (#syscall_number|stub)
 | 
			
		||||
#
 | 
			
		||||
# where:
 | 
			
		||||
#       arch_list ::= "all" | arch+
 | 
			
		||||
#       arch      ::= "arm" | "arm64" | "mips" | "mips64" | "x86" | "x86_64"
 | 
			
		||||
#
 | 
			
		||||
# Note:
 | 
			
		||||
#      - syscall_name corresponds to the name of the syscall, which may differ from
 | 
			
		||||
# note that:
 | 
			
		||||
#      - syscall_name correspond 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
 | 
			
		||||
#
 | 
			
		||||
#      - it there is "stub" instead of a syscall number, the tool will not generate any
 | 
			
		||||
#        assembler template for the syscall; it's up to the bionic implementation to provide
 | 
			
		||||
#        a relevant C stub
 | 
			
		||||
#
 | 
			
		||||
#      - additionally, if the syscall number is different amoung ARM, x86 and SuperH, use:
 | 
			
		||||
#        return_type funcname[:syscall_name](parameters) arm_number,x86_number,superh_number
 | 
			
		||||
#
 | 
			
		||||
# the file is processed by a python script named gensyscalls.py
 | 
			
		||||
#
 | 
			
		||||
# 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)      248,252
 | 
			
		||||
void    _exit_thread:exit (int)	    1
 | 
			
		||||
pid_t   __fork:fork (void)           2
 | 
			
		||||
pid_t   _waitpid:waitpid (pid_t, int*, int, struct rusage*)   -1,7
 | 
			
		||||
int     __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*)          280,284
 | 
			
		||||
 | 
			
		||||
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*) 120
 | 
			
		||||
 | 
			
		||||
# <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*)  11
 | 
			
		||||
 | 
			
		||||
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)    213
 | 
			
		||||
uid_t   getuid:getuid32 ()         199
 | 
			
		||||
gid_t   getgid:getgid32 ()         200
 | 
			
		||||
uid_t   geteuid:geteuid32 ()       201
 | 
			
		||||
gid_t   getegid:getegid32 ()       202
 | 
			
		||||
uid_t   getresuid:getresuid32 ()   209
 | 
			
		||||
gid_t   getresgid:getresgid32 ()   211
 | 
			
		||||
pid_t   gettid()                   224
 | 
			
		||||
int     getgroups:getgroups32(int, gid_t *)    205
 | 
			
		||||
pid_t   getpgid(pid_t)             132
 | 
			
		||||
pid_t   getppid()		   64
 | 
			
		||||
pid_t   setsid()                   66
 | 
			
		||||
int     setgid:setgid32(gid_t)     214
 | 
			
		||||
int     seteuid:seteuid32(uid_t)   stub
 | 
			
		||||
int     __setreuid:setreuid32(uid_t, uid_t)   203
 | 
			
		||||
int     __setresuid:setresuid32(uid_t, uid_t, uid_t)   208
 | 
			
		||||
int     setresgid:setresgid32(gid_t, gid_t, gid_t)   210
 | 
			
		||||
void*   __brk:brk(void*)           45
 | 
			
		||||
# 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,37
 | 
			
		||||
int     tkill(pid_t tid, int sig)  -1,238
 | 
			
		||||
int     __ptrace:ptrace(int request, int pid, void* addr, void* data)  26
 | 
			
		||||
int     __set_thread_area:set_thread_area(void*  user_desc)  -1,243
 | 
			
		||||
int     __getpriority:getpriority(int, int)  96
 | 
			
		||||
int     setpriority(int, int, int)   97
 | 
			
		||||
int     setrlimit(int resource, const struct rlimit *rlp)  75
 | 
			
		||||
int     getrlimit:ugetrlimit(int resource, struct rlimit *rlp)  191
 | 
			
		||||
int     getrusage(int who, struct rusage*  r_usage)  77
 | 
			
		||||
int     setgroups:setgroups32(int, const gid_t *)   206
 | 
			
		||||
pid_t   getpgrp(void)  stub
 | 
			
		||||
int     setpgid(pid_t, pid_t)  57
 | 
			
		||||
pid_t   vfork(void)  190,-1,190
 | 
			
		||||
int     setregid:setregid32(gid_t, gid_t)  204
 | 
			
		||||
int     chroot(const char *)  61
 | 
			
		||||
# 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)  172
 | 
			
		||||
int     capget(cap_user_header_t header, cap_user_data_t data) 184
 | 
			
		||||
int     capset(cap_user_header_t header, const cap_user_data_t data) 185
 | 
			
		||||
int     sigaltstack(const stack_t*, stack_t*) 186
 | 
			
		||||
int     acct(const char*  filepath)  51
 | 
			
		||||
 | 
			
		||||
# 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)        3
 | 
			
		||||
ssize_t     write (int, const void*, size_t)       4
 | 
			
		||||
ssize_t     pread64 (int, void *, size_t, off64_t) 180
 | 
			
		||||
ssize_t     pwrite64 (int, void *, size_t, off64_t) 181
 | 
			
		||||
int         __open:open (const char*, int, mode_t)  5
 | 
			
		||||
int         __openat:openat (int, const char*, int, mode_t)  322,295
 | 
			
		||||
int         close (int)                      6
 | 
			
		||||
int         creat(const char*, mode_t)       stub
 | 
			
		||||
off_t       lseek(int, off_t, int)           19
 | 
			
		||||
int         __llseek:_llseek (int, unsigned long, unsigned long, loff_t*, int)  140
 | 
			
		||||
pid_t       getpid ()    20
 | 
			
		||||
void *      mmap(void *, size_t, int, int, int, long)  stub
 | 
			
		||||
void *      __mmap2:mmap2(void*, size_t, int, int, int, long)   192
 | 
			
		||||
int         munmap(void *, size_t)  91
 | 
			
		||||
void *      mremap(void *, size_t, size_t, unsigned long)  163
 | 
			
		||||
int         msync(const void *, size_t, int)    144
 | 
			
		||||
int         mprotect(const void *, size_t, int)  125
 | 
			
		||||
int         madvise(const void *, size_t, int)  220,219
 | 
			
		||||
int         mlock(const void *addr, size_t len)    150
 | 
			
		||||
int         munlock(const void *addr, size_t len)   151
 | 
			
		||||
int         mincore(void*  start, size_t  length, unsigned char*  vec)   219,218
 | 
			
		||||
int         __ioctl:ioctl(int, int, void *)  54
 | 
			
		||||
int         readv(int, const struct iovec *, int)   145
 | 
			
		||||
int         writev(int, const struct iovec *, int)  146
 | 
			
		||||
int         __fcntl:fcntl(int, int, void*)  55
 | 
			
		||||
int         flock(int, int)   143
 | 
			
		||||
int         fchmod(int, mode_t)  94
 | 
			
		||||
int         dup(int)  41
 | 
			
		||||
int         pipe(int *)  42,42,-1
 | 
			
		||||
int         pipe2(int *, int) 359,331
 | 
			
		||||
int         dup2(int, int)   63
 | 
			
		||||
int         select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *)  142
 | 
			
		||||
int         ftruncate(int, off_t)  93
 | 
			
		||||
int         ftruncate64(int, off64_t) 194
 | 
			
		||||
int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   217,220
 | 
			
		||||
int         fsync(int)  118
 | 
			
		||||
int         fdatasync(int) 148
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  207
 | 
			
		||||
void        sync(void)  36
 | 
			
		||||
int         __fcntl64:fcntl64(int, int, void *)  221
 | 
			
		||||
int         __fstatfs64:fstatfs64(int, size_t, struct statfs *)  267,269
 | 
			
		||||
ssize_t     sendfile(int out_fd, int in_fd, off_t *offset, size_t count)  187
 | 
			
		||||
int         fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags)   327,300
 | 
			
		||||
int         mkdirat(int dirfd, const char *pathname, mode_t mode)  323,296
 | 
			
		||||
int         fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags)  325,298
 | 
			
		||||
int         fchmodat(int dirfd, const char *path, mode_t mode, int flags)  333,306
 | 
			
		||||
int         renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)  329,302
 | 
			
		||||
 | 
			
		||||
# 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*)  9
 | 
			
		||||
int     unlink (const char*)             10
 | 
			
		||||
int     unlinkat (int, const char *, int)   328,301
 | 
			
		||||
int     chdir (const char*)              12
 | 
			
		||||
int     mknod (const char*, mode_t, dev_t)  14
 | 
			
		||||
int     chmod (const char*,mode_t)          15
 | 
			
		||||
int     chown:chown32(const char *, uid_t, gid_t)  212
 | 
			
		||||
int     lchown:lchown32 (const char*, uid_t, gid_t)  198
 | 
			
		||||
int     mount (const char*, const char*, const char*, unsigned long, const void*)  21
 | 
			
		||||
int     umount(const char*)  stub
 | 
			
		||||
int     umount2 (const char*, int)  52
 | 
			
		||||
int     fstat:fstat64(int, struct stat*)    197
 | 
			
		||||
int     stat:stat64(const char *, struct stat *)  195
 | 
			
		||||
int     lstat:lstat64(const char *, struct stat *)  196
 | 
			
		||||
int     mkdir(const char *, mode_t) 39
 | 
			
		||||
int     readlink(const char *, char *, size_t)  85
 | 
			
		||||
int     rmdir(const char *)  40
 | 
			
		||||
int     rename(const char *, const char *)  38
 | 
			
		||||
int     __getcwd:getcwd(char * buf, size_t size)  183
 | 
			
		||||
int     access(const char *, int)  33
 | 
			
		||||
int     symlink(const char *, const char *)  83
 | 
			
		||||
int     fchdir(int)    133
 | 
			
		||||
int     truncate(const char*, off_t)    92
 | 
			
		||||
int     __statfs64:statfs64(const char *, size_t, struct statfs *)  266,268
 | 
			
		||||
# 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 ()                       29
 | 
			
		||||
int           gettimeofday(struct timeval*, struct timezone*)       78
 | 
			
		||||
int           settimeofday(const struct timeval*, const struct timezone*)   79
 | 
			
		||||
clock_t       times(struct tms *)       43
 | 
			
		||||
int           nanosleep(const struct timespec *, struct timespec *)   162
 | 
			
		||||
int           clock_gettime(clockid_t clk_id, struct timespec *tp)    263,265
 | 
			
		||||
int           clock_settime(clockid_t clk_id, const struct timespec *tp)  262,264
 | 
			
		||||
int           clock_getres(clockid_t clk_id, struct timespec *res)   264,266
 | 
			
		||||
int           clock_nanosleep(const struct timespec *req, struct timespec *rem)  265,267
 | 
			
		||||
int           getitimer(int, const struct itimerval *)   105
 | 
			
		||||
int           setitimer(int, const struct itimerval *, struct itimerval *)  104
 | 
			
		||||
int           __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)    257,259
 | 
			
		||||
int           __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 258,260
 | 
			
		||||
int           __timer_gettime:timer_gettime(timer_t, struct itimerspec*)                                259,261
 | 
			
		||||
int           __timer_getoverrun:timer_getoverrun(timer_t)                                              260,262
 | 
			
		||||
int           __timer_delete:timer_delete(timer_t)                                                      261,263
 | 
			
		||||
int           utimes(const char*, const struct timeval tvp[2])                          269, 271
 | 
			
		||||
int           utimensat(int, const char *, const struct timespec times[2], int)         348, 320, 320
 | 
			
		||||
 | 
			
		||||
# 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 *)  67
 | 
			
		||||
int     sigprocmask(int, const sigset_t *, sigset_t *)  126
 | 
			
		||||
int     __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask)  72
 | 
			
		||||
int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  174
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  175
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177
 | 
			
		||||
int     sigpending(sigset_t *)  73
 | 
			
		||||
 | 
			
		||||
# 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)              281,-1
 | 
			
		||||
int           socketpair(int, int, int, int*)    288,-1
 | 
			
		||||
int           bind(int, struct sockaddr *, int)  282,-1
 | 
			
		||||
int           connect(int, struct sockaddr *, socklen_t)   283,-1
 | 
			
		||||
int           listen(int, int)                   284,-1
 | 
			
		||||
int           accept(int, struct sockaddr *, socklen_t *)  285,-1
 | 
			
		||||
int           getsockname(int, struct sockaddr *, socklen_t *)  286,-1
 | 
			
		||||
int           getpeername(int, struct sockaddr *, socklen_t *)  287,-1
 | 
			
		||||
int           sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  290,-1
 | 
			
		||||
int           recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  292,-1
 | 
			
		||||
int           shutdown(int, int)  293,-1
 | 
			
		||||
int           setsockopt(int, int, int, const void *, socklen_t)  294,-1
 | 
			
		||||
int           getsockopt(int, int, int, void *, socklen_t *)    295,-1
 | 
			
		||||
int           sendmsg(int, const struct msghdr *, unsigned int)  296,-1
 | 
			
		||||
int           recvmsg(int, struct msghdr *, unsigned int)   297,-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,102,-1
 | 
			
		||||
int           bind:socketcall:2 (int, struct sockaddr *, int)  -1,102,-1
 | 
			
		||||
int           connect:socketcall:3(int, struct sockaddr *, socklen_t)   -1,102,-1
 | 
			
		||||
int           listen:socketcall:4(int, int)                   -1,102,-1
 | 
			
		||||
int           accept:socketcall:5(int, struct sockaddr *, socklen_t *)  -1,102,-1
 | 
			
		||||
int           getsockname:socketcall:6(int, struct sockaddr *, socklen_t *)  -1,102,-1
 | 
			
		||||
int           getpeername:socketcall:7(int, struct sockaddr *, socklen_t *)  -1,102,-1
 | 
			
		||||
int           socketpair:socketcall:8(int, int, int, int*)    -1,102,-1
 | 
			
		||||
int           sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  -1,102,-1
 | 
			
		||||
int           recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  -1,102,-1
 | 
			
		||||
int           shutdown:socketcall:13(int, int)  -1,102,-1
 | 
			
		||||
int           setsockopt:socketcall:14(int, int, int, const void *, socklen_t)  -1,102,-1
 | 
			
		||||
int           getsockopt:socketcall:15(int, int, int, void *, socklen_t *)    -1,102,-1
 | 
			
		||||
int           sendmsg:socketcall:16(int, const struct msghdr *, unsigned int)  -1,102,-1
 | 
			
		||||
int           recvmsg:socketcall:17(int, struct msghdr *, unsigned int)   -1,102,-1
 | 
			
		||||
 | 
			
		||||
# sockets for sh.
 | 
			
		||||
int           __socketcall:socketcall(int, unsigned long*) -1,-1,102
 | 
			
		||||
 | 
			
		||||
# 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)  156
 | 
			
		||||
int sched_getscheduler(pid_t pid)  157
 | 
			
		||||
int sched_yield(void)  158
 | 
			
		||||
int sched_setparam(pid_t pid, const struct sched_param *param)  154
 | 
			
		||||
int sched_getparam(pid_t pid, struct sched_param *param)  155
 | 
			
		||||
int sched_get_priority_max(int policy)  159
 | 
			
		||||
int sched_get_priority_min(int policy)  160
 | 
			
		||||
int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161
 | 
			
		||||
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241
 | 
			
		||||
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242
 | 
			
		||||
int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318,318
 | 
			
		||||
 | 
			
		||||
# io priorities
 | 
			
		||||
int ioprio_set(int which, int who, int ioprio) 314,289,288
 | 
			
		||||
int ioprio_get(int which, int who) 315,290,289
 | 
			
		||||
 | 
			
		||||
# 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 *)  122
 | 
			
		||||
pid_t   __wait4:wait4(pid_t pid, int *status, int options, struct rusage *rusage)   114
 | 
			
		||||
mode_t  umask(mode_t)  60
 | 
			
		||||
int      __reboot:reboot(int, int, int, void *)  88
 | 
			
		||||
int     __syslog:syslog(int, char *, int)  103
 | 
			
		||||
int     init_module(void *, unsigned long, const char *)  128
 | 
			
		||||
int     delete_module(const char*, unsigned int)   129
 | 
			
		||||
int     klogctl:syslog(int, char *, int)   103
 | 
			
		||||
int     sysinfo(struct sysinfo *)  116
 | 
			
		||||
int     personality(unsigned long)  136
 | 
			
		||||
 | 
			
		||||
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) 240
 | 
			
		||||
 | 
			
		||||
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)     250,254
 | 
			
		||||
int     epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)    251,255
 | 
			
		||||
int     epoll_wait(int epfd, struct epoll_event *events, int max, int timeout)   252,256
 | 
			
		||||
 | 
			
		||||
int eventfd:eventfd2(unsigned int, int)  all
 | 
			
		||||
int     inotify_init(void)      316,291,290
 | 
			
		||||
int     inotify_add_watch(int, const char *, unsigned int)  317,292,291
 | 
			
		||||
int     inotify_rm_watch(int, unsigned int)  318,293,292
 | 
			
		||||
 | 
			
		||||
void _exit|_Exit:exit_group(int)  all
 | 
			
		||||
void __exit:exit(int)  all
 | 
			
		||||
int     poll(struct pollfd *, unsigned int, long)  168
 | 
			
		||||
 | 
			
		||||
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)  356,328
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
# ARM-specific ARM_NR_BASE == 0x0f0000 == 983040
 | 
			
		||||
int     __set_tls:ARM_set_tls(void*)                                 983045,-1
 | 
			
		||||
int     cacheflush:ARM_cacheflush(long start, long end, long flags)  983042,-1
 | 
			
		||||
 
 | 
			
		||||
@@ -1,73 +0,0 @@
 | 
			
		||||
# 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 += \
 | 
			
		||||
    arch-arm/bionic/abort_arm.S \
 | 
			
		||||
    arch-arm/bionic/atomics_arm.c \
 | 
			
		||||
    arch-arm/bionic/__bionic_clone.S \
 | 
			
		||||
    arch-arm/bionic/_exit_with_stack_teardown.S \
 | 
			
		||||
    arch-arm/bionic/libgcc_compat.c \
 | 
			
		||||
    arch-arm/bionic/__restore.S \
 | 
			
		||||
    arch-arm/bionic/setjmp.S \
 | 
			
		||||
    arch-arm/bionic/syscall.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
 | 
			
		||||
 | 
			
		||||
## 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)
 | 
			
		||||
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
 | 
			
		||||
@@ -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_pc.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								libc/arch-arm/bionic/__get_pc.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.
 | 
			
		||||
 */
 | 
			
		||||
.global __get_pc
 | 
			
		||||
.type __get_pc, %function
 | 
			
		||||
 | 
			
		||||
__get_pc:
 | 
			
		||||
	mov r0, pc
 | 
			
		||||
	bx lr
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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.
 | 
			
		||||
 */
 | 
			
		||||
.global __get_sp
 | 
			
		||||
.type __get_sp, %function
 | 
			
		||||
 | 
			
		||||
__get_sp:
 | 
			
		||||
	mov r0, sp
 | 
			
		||||
	bx lr
 | 
			
		||||
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -25,17 +25,27 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <asm/unistd.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
@ void _exit_with_stack_teardown(void * stackBase, int stackSize, int retCode)
 | 
			
		||||
ENTRY(_exit_with_stack_teardown)
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
#if __ARM_EABI__
 | 
			
		||||
    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
 | 
			
		||||
#else
 | 
			
		||||
    mov     lr, r2
 | 
			
		||||
    swi     # __NR_munmap   @ the stack is destroyed by this call
 | 
			
		||||
    mov     r0, lr
 | 
			
		||||
    swi     # __NR_exit
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Coding the abort function in assembly so that registers are guaranteed to
 | 
			
		||||
 * be preserved properly regardless of GCC's assumption on the "noreturn"
 | 
			
		||||
 * attribute. When the registers are not properly preserved we won't be able
 | 
			
		||||
 * to unwind the stack all the way to the bottom to fully reveal the call
 | 
			
		||||
 * sequence when the crash happens.
 | 
			
		||||
 */
 | 
			
		||||
ENTRY(abort)
 | 
			
		||||
    stmfd   sp!, {r3, r14}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r3, 0
 | 
			
		||||
    .cfi_rel_offset r14, 4
 | 
			
		||||
    bl      __libc_android_abort
 | 
			
		||||
END(abort)
 | 
			
		||||
							
								
								
									
										62
									
								
								libc/arch-arm/bionic/atexit.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								libc/arch-arm/bionic/atexit.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2011 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef CRT_LEGACY_WORKAROUND
 | 
			
		||||
	.arch armv5te
 | 
			
		||||
	.fpu softvfp
 | 
			
		||||
	.eabi_attribute 20, 1
 | 
			
		||||
	.eabi_attribute 21, 1
 | 
			
		||||
	.eabi_attribute 23, 3
 | 
			
		||||
	.eabi_attribute 24, 1
 | 
			
		||||
	.eabi_attribute 25, 1
 | 
			
		||||
	.eabi_attribute 26, 2
 | 
			
		||||
	.eabi_attribute 30, 4
 | 
			
		||||
	.eabi_attribute 18, 4
 | 
			
		||||
	.hidden	atexit
 | 
			
		||||
	.code	16
 | 
			
		||||
	.thumb_func
 | 
			
		||||
ENTRY(atexit)
 | 
			
		||||
.LFB0:
 | 
			
		||||
	.save	{r4, lr}
 | 
			
		||||
	push	{r4, lr}
 | 
			
		||||
.LCFI0:
 | 
			
		||||
	ldr	r3, .L3
 | 
			
		||||
	mov	r1, #0
 | 
			
		||||
	@ sp needed for prologue
 | 
			
		||||
.LPIC0:
 | 
			
		||||
	add	r3, pc
 | 
			
		||||
	ldr	r2, [r3]
 | 
			
		||||
	bl	__cxa_atexit
 | 
			
		||||
	pop	{r4, pc}
 | 
			
		||||
.L4:
 | 
			
		||||
	.align	2
 | 
			
		||||
.L3:
 | 
			
		||||
	.word	__dso_handle-(.LPIC0+4)
 | 
			
		||||
.LFE0:
 | 
			
		||||
END(atexit)
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,60 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <sys/types.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
 | 
			
		||||
 * implementation of atexit().
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Register a function to be performed at exit.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
atexit(void (*func)(void))
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * Exit functions queued by this version of atexit will not be called
 | 
			
		||||
     * on dlclose(), and when they are called (at program exit), the
 | 
			
		||||
     * calling library may have been dlclose()'d, causing the program to
 | 
			
		||||
     * crash.
 | 
			
		||||
     */
 | 
			
		||||
    static char const warning[] = "WARNING: generic atexit() called from legacy shared library\n";
 | 
			
		||||
 | 
			
		||||
    __libc_format_log(ANDROID_LOG_WARN, "libc", warning);
 | 
			
		||||
    fprintf(stderr, warning);
 | 
			
		||||
 | 
			
		||||
    return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										236
									
								
								libc/arch-arm/bionic/atomics_arm.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								libc/arch-arm/bionic/atomics_arm.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,236 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <sys/linux-syscalls.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
#define FUTEX_WAIT 0
 | 
			
		||||
#define FUTEX_WAKE 1
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_HAVE_LDREX_STREX)
 | 
			
		||||
/*
 | 
			
		||||
 * ===========================================================================
 | 
			
		||||
 *      ARMv6+ implementation
 | 
			
		||||
 * ===========================================================================
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* r0(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_dec)
 | 
			
		||||
    mov     r1, r0                      @ copy addr so we don't clobber it
 | 
			
		||||
1:  ldrex   r0, [r1]                    @ load current value into r0
 | 
			
		||||
    sub     r2, r0, #1                  @ generate new value into r2
 | 
			
		||||
    strex   r3, r2, [r1]                @ try to store new value; result in r3
 | 
			
		||||
    cmp     r3, #0                      @ success?
 | 
			
		||||
    bxeq    lr                          @ yes, return
 | 
			
		||||
    b       1b                          @ no, retry
 | 
			
		||||
END(__atomic_dec)
 | 
			
		||||
 | 
			
		||||
/* r0(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_inc)
 | 
			
		||||
    mov     r1, r0
 | 
			
		||||
1:  ldrex   r0, [r1]
 | 
			
		||||
    add     r2, r0, #1
 | 
			
		||||
    strex   r3, r2, [r1]
 | 
			
		||||
    cmp     r3, #0
 | 
			
		||||
    bxeq    lr
 | 
			
		||||
    b       1b
 | 
			
		||||
END(__atomic_inc)
 | 
			
		||||
 | 
			
		||||
/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
 | 
			
		||||
ENTRY(__atomic_cmpxchg)
 | 
			
		||||
1:  mov     ip, #2                      @ ip=2 means "new != old"
 | 
			
		||||
    ldrex   r3, [r2]                    @ load current value into r3
 | 
			
		||||
    teq     r0, r3                      @ new == old?
 | 
			
		||||
    strexeq ip, r1, [r2]                @ yes, try store, set ip to 0 or 1
 | 
			
		||||
    teq     ip, #1                      @ strex failure?
 | 
			
		||||
    beq     1b                          @ yes, retry
 | 
			
		||||
    mov     r0, ip                      @ return 0 on success, 2 on failure
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_cmpxchg)
 | 
			
		||||
 | 
			
		||||
/* r0(new) r1(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_swap)
 | 
			
		||||
1:  ldrex   r2, [r1]
 | 
			
		||||
    strex   r3, r0, [r1]
 | 
			
		||||
    teq     r3, #0
 | 
			
		||||
    bne     1b
 | 
			
		||||
    mov     r0, r2
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_swap)
 | 
			
		||||
 | 
			
		||||
#else /*not defined __ARM_HAVE_LDREX_STREX*/
 | 
			
		||||
/*
 | 
			
		||||
 * ===========================================================================
 | 
			
		||||
 *      Pre-ARMv6 implementation
 | 
			
		||||
 * ===========================================================================
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    /* int __kernel_cmpxchg(int oldval, int newval, int* ptr) */
 | 
			
		||||
    .equ    kernel_cmpxchg, 0xFFFF0FC0
 | 
			
		||||
    .equ    kernel_atomic_base, 0xFFFF0FFF
 | 
			
		||||
 | 
			
		||||
/* r0(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_dec)
 | 
			
		||||
    .save {r4, lr}
 | 
			
		||||
    stmdb   sp!, {r4, lr}
 | 
			
		||||
    mov     r2, r0
 | 
			
		||||
1: @ atomic_dec
 | 
			
		||||
    ldr     r0, [r2]
 | 
			
		||||
    mov     r3, #kernel_atomic_base
 | 
			
		||||
    add     lr, pc, #4
 | 
			
		||||
    sub     r1, r0, #1
 | 
			
		||||
    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
 | 
			
		||||
    bcc     1b
 | 
			
		||||
    add     r0, r1, #1
 | 
			
		||||
    ldmia   sp!, {r4, lr}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_dec)
 | 
			
		||||
 | 
			
		||||
/* r0(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_inc)
 | 
			
		||||
    .save {r4, lr}
 | 
			
		||||
    stmdb   sp!, {r4, lr}
 | 
			
		||||
    mov     r2, r0
 | 
			
		||||
1: @ atomic_inc
 | 
			
		||||
    ldr     r0, [r2]
 | 
			
		||||
    mov     r3, #kernel_atomic_base
 | 
			
		||||
    add     lr, pc, #4
 | 
			
		||||
    add     r1, r0, #1
 | 
			
		||||
    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
 | 
			
		||||
    bcc     1b
 | 
			
		||||
    sub     r0, r1, #1
 | 
			
		||||
    ldmia   sp!, {r4, lr}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_inc)
 | 
			
		||||
 | 
			
		||||
/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
 | 
			
		||||
ENTRY(__atomic_cmpxchg)
 | 
			
		||||
    .save {r4, lr}
 | 
			
		||||
    stmdb   sp!, {r4, lr}
 | 
			
		||||
    mov     r4, r0          /* r4 = save oldvalue */
 | 
			
		||||
1: @ atomic_cmpxchg
 | 
			
		||||
    mov     r3, #kernel_atomic_base
 | 
			
		||||
    add     lr, pc, #4
 | 
			
		||||
    mov     r0, r4          /* r0 = oldvalue */
 | 
			
		||||
    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
 | 
			
		||||
    bcs     2f              /* swap was made. we're good, return. */
 | 
			
		||||
    ldr     r3, [r2]        /* swap not made, see if it's because *ptr!=oldvalue */
 | 
			
		||||
    cmp     r3, r4
 | 
			
		||||
    beq     1b
 | 
			
		||||
2: @ atomic_cmpxchg
 | 
			
		||||
    ldmia   sp!, {r4, lr}
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_cmpxchg)
 | 
			
		||||
 | 
			
		||||
/* r0(new) r1(addr) -> r0(old) */
 | 
			
		||||
ENTRY(__atomic_swap)
 | 
			
		||||
    swp     r0, r0, [r1]
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__atomic_swap)
 | 
			
		||||
 | 
			
		||||
#endif /*not defined __ARM_HAVE_LDREX_STREX*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* __futex_wait(*ftx, val, *timespec) */
 | 
			
		||||
/* __futex_wake(*ftx, counter) */
 | 
			
		||||
/* __futex_syscall3(*ftx, op, val) */
 | 
			
		||||
/* __futex_syscall4(*ftx, op, val, *timespec) */
 | 
			
		||||
 | 
			
		||||
.global __futex_wait
 | 
			
		||||
.type __futex_wait, %function
 | 
			
		||||
 | 
			
		||||
.global __futex_wake
 | 
			
		||||
.type __futex_wake, %function
 | 
			
		||||
 | 
			
		||||
.global __futex_syscall3
 | 
			
		||||
.type __futex_syscall3, %function
 | 
			
		||||
 | 
			
		||||
.global __futex_syscall4
 | 
			
		||||
.type __futex_syscall4, %function
 | 
			
		||||
 | 
			
		||||
#if __ARM_EABI__
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
ENTRY(__futex_syscall3)
 | 
			
		||||
    swi     #__NR_futex
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_syscall3)
 | 
			
		||||
 | 
			
		||||
ENTRY(__futex_wait)
 | 
			
		||||
    mov     r3, r2
 | 
			
		||||
    mov     r2, r1
 | 
			
		||||
    mov     r1, #FUTEX_WAIT
 | 
			
		||||
    swi     #__NR_futex
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_wait)
 | 
			
		||||
 | 
			
		||||
ENTRY(__futex_wake)
 | 
			
		||||
    mov     r2, r1
 | 
			
		||||
    mov     r1, #FUTEX_WAKE
 | 
			
		||||
    swi     #__NR_futex
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(__futex_wake)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(__futex_syscall4)
 | 
			
		||||
    b __futex_syscall3
 | 
			
		||||
END(__futex_syscall4)
 | 
			
		||||
@@ -1,87 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2011 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* The purpose of this file is to export a small set of atomic-related
 | 
			
		||||
 * functions from the C library, to ensure binary ABI compatibility for
 | 
			
		||||
 * the NDK.
 | 
			
		||||
 *
 | 
			
		||||
 * These functions were initially exposed by the NDK through <sys/atomics.h>,
 | 
			
		||||
 * which was unfortunate because their implementation didn't provide any
 | 
			
		||||
 * memory barriers at all.
 | 
			
		||||
 *
 | 
			
		||||
 * This wasn't a problem for the platform code that used them, because it
 | 
			
		||||
 * used explicit barrier instructions around them. On the other hand, it means
 | 
			
		||||
 * that any NDK-generated machine code that linked against them would not
 | 
			
		||||
 * perform correctly when running on multi-core devices.
 | 
			
		||||
 *
 | 
			
		||||
 * To fix this, the platform code was first modified to not use any of these
 | 
			
		||||
 * functions (everything is now inlined through assembly statements, see
 | 
			
		||||
 * libc/private/bionic_arm_inline.h and the headers it includes.
 | 
			
		||||
 *
 | 
			
		||||
 * The functions here are thus only for the benefit of NDK applications,
 | 
			
		||||
 * and now includes full memory barriers to prevent any random memory ordering
 | 
			
		||||
 * issue from cropping.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that we also provide an updated <sys/atomics.h> header that defines
 | 
			
		||||
 * always_inlined versions of the functions that use the GCC builtin
 | 
			
		||||
 * intrinsics to perform the same thing.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: There is no need for a similar file for non-ARM platforms.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* DO NOT INCLUDE <sys/atomics.h> HERE ! */
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
__atomic_cmpxchg(int old, int _new, volatile int *ptr)
 | 
			
		||||
{
 | 
			
		||||
    /* We must return 0 on success */
 | 
			
		||||
    return __sync_val_compare_and_swap(ptr, old, _new) != old;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
__atomic_swap(int _new, volatile int *ptr)
 | 
			
		||||
{
 | 
			
		||||
    int prev;
 | 
			
		||||
    do {
 | 
			
		||||
        prev = *ptr;
 | 
			
		||||
    } while (__sync_val_compare_and_swap(ptr, prev, _new) != prev);
 | 
			
		||||
    return prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
__atomic_dec(volatile int *ptr)
 | 
			
		||||
{
 | 
			
		||||
  return __sync_fetch_and_sub (ptr, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
__atomic_inc(volatile int *ptr)
 | 
			
		||||
{
 | 
			
		||||
  return __sync_fetch_and_add (ptr, 1);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										118
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <sys/linux-syscalls.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(__pthread_clone)
 | 
			
		||||
    @ insert the args onto the new stack
 | 
			
		||||
    str     r0, [r1, #-4]
 | 
			
		||||
    str     r3, [r1, #-8]
 | 
			
		||||
 | 
			
		||||
    @ do the system call
 | 
			
		||||
    @ get flags
 | 
			
		||||
 | 
			
		||||
    mov     r0, r2
 | 
			
		||||
 | 
			
		||||
    @ new sp is already in r1
 | 
			
		||||
 | 
			
		||||
#if __ARM_EABI__
 | 
			
		||||
    stmfd   sp!, {r4, r7}
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
#else
 | 
			
		||||
    swi     #__NR_clone
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
#if __ARM_EABI__
 | 
			
		||||
    ldmnefd sp!, {r4, r7}
 | 
			
		||||
#endif
 | 
			
		||||
    blt     __error
 | 
			
		||||
    bxne    lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @ 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
 | 
			
		||||
 | 
			
		||||
    ldr     r0, [sp, #-4]
 | 
			
		||||
    ldr     r1, [sp, #-8]
 | 
			
		||||
    mov     r2, sp			@ __thread_entry needs the TLS pointer
 | 
			
		||||
    b       __thread_entry
 | 
			
		||||
 | 
			
		||||
__error:
 | 
			
		||||
    mov     r0, #-1
 | 
			
		||||
    bx      lr
 | 
			
		||||
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 than the GLibc
 | 
			
		||||
    #       __clone function here !! 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 parent, reload saved registers
 | 
			
		||||
    # then either exit or error
 | 
			
		||||
    #
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    bxne    lr
 | 
			
		||||
    b       __set_syscall_errno
 | 
			
		||||
 | 
			
		||||
1:  # in the child - pick arguments
 | 
			
		||||
    ldr    r0, [sp, #-4]
 | 
			
		||||
    ldr    r1, [sp, #-8]
 | 
			
		||||
    b      __bionic_clone_entry
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
							
								
								
									
										88
									
								
								libc/arch-arm/bionic/crtbegin_dynamic.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								libc/arch-arm/bionic/crtbegin_dynamic.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
	.text
 | 
			
		||||
	.align 4
 | 
			
		||||
	.type _start,#function
 | 
			
		||||
	.globl _start
 | 
			
		||||
 | 
			
		||||
# this is the small startup code that is first run when
 | 
			
		||||
# any executable that is dynamically-linked with Bionic
 | 
			
		||||
# runs.
 | 
			
		||||
#
 | 
			
		||||
# it's purpose is to call __libc_init with appropriate
 | 
			
		||||
# arguments, which are:
 | 
			
		||||
#
 | 
			
		||||
#    - the address of the raw data block setup by the Linux
 | 
			
		||||
#      kernel ELF loader
 | 
			
		||||
#
 | 
			
		||||
#    - address of an "onexit" function, not used on any
 | 
			
		||||
#      platform supported by Bionic
 | 
			
		||||
#
 | 
			
		||||
#    - address of the "main" function of the program. We
 | 
			
		||||
#      can't hard-code it in the adr pseudo instruction
 | 
			
		||||
#      so we use a tiny trampoline that will get relocated
 | 
			
		||||
#      by the dynamic linker before this code runs
 | 
			
		||||
#
 | 
			
		||||
#    - address of the constructor list
 | 
			
		||||
#
 | 
			
		||||
_start:	
 | 
			
		||||
	mov	r0, sp
 | 
			
		||||
	mov	r1, #0
 | 
			
		||||
	adr r2, 0f
 | 
			
		||||
	adr r3, 1f
 | 
			
		||||
	b	__libc_init
 | 
			
		||||
 | 
			
		||||
0:  b   main
 | 
			
		||||
 | 
			
		||||
1:  .long   __PREINIT_ARRAY__
 | 
			
		||||
    .long   __INIT_ARRAY__
 | 
			
		||||
    .long   __FINI_ARRAY__
 | 
			
		||||
    .long   __CTOR_LIST__
 | 
			
		||||
 | 
			
		||||
	.section .preinit_array, "aw"
 | 
			
		||||
	.globl __PREINIT_ARRAY__
 | 
			
		||||
__PREINIT_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.globl __INIT_ARRAY__
 | 
			
		||||
__INIT_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	.globl __FINI_ARRAY__
 | 
			
		||||
__FINI_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .ctors, "aw"
 | 
			
		||||
	.globl __CTOR_LIST__
 | 
			
		||||
__CTOR_LIST__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
#include "__dso_handle.S"
 | 
			
		||||
#include "atexit.S"
 | 
			
		||||
							
								
								
									
										61
									
								
								libc/arch-arm/bionic/crtbegin_so.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libc/arch-arm/bionic/crtbegin_so.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
# Implement static C++ destructors when the shared
 | 
			
		||||
# library is unloaded through dlclose().
 | 
			
		||||
#
 | 
			
		||||
# A call to this function must be the first entry
 | 
			
		||||
# in the .fini_array. See 3.3.5.3.C of C++ ABI
 | 
			
		||||
# standard.
 | 
			
		||||
#
 | 
			
		||||
__on_dlclose:
 | 
			
		||||
        adr     r0, 0f
 | 
			
		||||
        ldr     r0, [r0]
 | 
			
		||||
        b       __cxa_finalize
 | 
			
		||||
 | 
			
		||||
0:
 | 
			
		||||
        .long   __dso_handle
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.globl __INIT_ARRAY__
 | 
			
		||||
__INIT_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
        .section .fini_array, "aw"
 | 
			
		||||
        .globl __FINI_ARRAY__
 | 
			
		||||
__FINI_ARRAY__:
 | 
			
		||||
        .long -1
 | 
			
		||||
        .long __on_dlclose
 | 
			
		||||
 | 
			
		||||
#ifdef CRT_LEGACY_WORKAROUND
 | 
			
		||||
#include "__dso_handle.S"
 | 
			
		||||
#else
 | 
			
		||||
#include "__dso_handle_so.S"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "atexit.S"
 | 
			
		||||
							
								
								
									
										89
									
								
								libc/arch-arm/bionic/crtbegin_static.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								libc/arch-arm/bionic/crtbegin_static.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
	.text
 | 
			
		||||
	.align 4
 | 
			
		||||
	.type _start,#function
 | 
			
		||||
	.globl _start
 | 
			
		||||
 | 
			
		||||
# this is the small startup code that is first run when
 | 
			
		||||
# any executable that is statically-linked with Bionic
 | 
			
		||||
# runs.
 | 
			
		||||
#
 | 
			
		||||
# it's purpose is to call __libc_init with appropriate
 | 
			
		||||
# arguments, which are:
 | 
			
		||||
#
 | 
			
		||||
#    - the address of the raw data block setup by the Linux
 | 
			
		||||
#      kernel ELF loader
 | 
			
		||||
#
 | 
			
		||||
#    - address of an "onexit" function, not used on any
 | 
			
		||||
#      platform supported by Bionic
 | 
			
		||||
#
 | 
			
		||||
#    - address of the "main" function of the program. We
 | 
			
		||||
#      can't hard-code it in the adr pseudo instruction
 | 
			
		||||
#      so we use a tiny trampoline that will get relocated
 | 
			
		||||
#      by the dynamic linker before this code runs
 | 
			
		||||
#
 | 
			
		||||
#    - address of the constructor list
 | 
			
		||||
#
 | 
			
		||||
_start:	
 | 
			
		||||
	mov	r0, sp
 | 
			
		||||
	mov	r1, #0
 | 
			
		||||
	adr r2, 0f
 | 
			
		||||
	adr r3, 1f
 | 
			
		||||
	b	__libc_init
 | 
			
		||||
 | 
			
		||||
0:  b   main
 | 
			
		||||
 | 
			
		||||
1:  .long   __PREINIT_ARRAY__
 | 
			
		||||
    .long   __INIT_ARRAY__
 | 
			
		||||
    .long   __FINI_ARRAY__
 | 
			
		||||
    .long   __CTOR_LIST__
 | 
			
		||||
 | 
			
		||||
	.section .preinit_array, "aw"
 | 
			
		||||
	.globl __PREINIT_ARRAY__
 | 
			
		||||
__PREINIT_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.globl __INIT_ARRAY__
 | 
			
		||||
__INIT_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	.globl __FINI_ARRAY__
 | 
			
		||||
__FINI_ARRAY__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
	.section .ctors, "aw"
 | 
			
		||||
	.globl __CTOR_LIST__
 | 
			
		||||
__CTOR_LIST__:
 | 
			
		||||
	.long -1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "__dso_handle.S"
 | 
			
		||||
#include "atexit.S"
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
	.section .ctors, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This is the same than crtend.S except that a shared library
 | 
			
		||||
 * cannot have a .preinit_array
 | 
			
		||||
 */
 | 
			
		||||
	
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										119
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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* );
 | 
			
		||||
 | 
			
		||||
/* Temporary hack: this variable should not be part of the C library
 | 
			
		||||
 * itself, but placed in the .bss section of each executable or
 | 
			
		||||
 * shared library instead.
 | 
			
		||||
 *
 | 
			
		||||
 * We keep it here temporarily until the build system has been
 | 
			
		||||
 * modified properly to use crtbegin_so.S and crtend_so.S when
 | 
			
		||||
 * generating shared libraries.
 | 
			
		||||
 *
 | 
			
		||||
 * It must be a 'weak' symbol to avoid conflicts with the definitions
 | 
			
		||||
 * that have been moved to crtbegin_static.S and crtbegin_dynamic.S
 | 
			
		||||
 *
 | 
			
		||||
 * For the record, it is used for static C++ object construction
 | 
			
		||||
 * and destruction. See http://www.codesourcery.com/public/cxx-abi/abi.html#dso-dtor
 | 
			
		||||
 */
 | 
			
		||||
void* __attribute__((weak)) __dso_handle;
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
}
 | 
			
		||||
@@ -25,8 +25,12 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
typedef long unsigned int *_Unwind_Ptr;
 | 
			
		||||
 | 
			
		||||
#include <link.h>
 | 
			
		||||
/* Stubbed out in libdl and defined in the dynamic linker.
 | 
			
		||||
 * Same semantics as __gnu_Unwind_Find_exidx().
 | 
			
		||||
 */
 | 
			
		||||
extern _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
 | 
			
		||||
 | 
			
		||||
/* For a given PC, find the .so that it belongs to.
 | 
			
		||||
 * Returns the base address of the .ARM.exidx section
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,7 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <link.h>
 | 
			
		||||
typedef long unsigned int *_Unwind_Ptr;
 | 
			
		||||
 | 
			
		||||
/* Find the .ARM.exidx section (which in the case of a static executable
 | 
			
		||||
 * can be identified through its start and end symbols), and return its
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										85
									
								
								libc/arch-arm/bionic/ffs.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								libc/arch-arm/bionic/ffs.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
/*	$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>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ffs - find first set bit, this algorithm isolates the first set
 | 
			
		||||
 * bit, then multiplies the number by 0x0450fbaf which leaves the top
 | 
			
		||||
 * 6 bits as an index into the table.  This algorithm should be a win
 | 
			
		||||
 * over the checking each bit in turn as per the C compiled version.
 | 
			
		||||
 *
 | 
			
		||||
 * Some newer ARM architectures have an instruction named
 | 
			
		||||
 * CLZ (count leading Zero's) that is used
 | 
			
		||||
 *
 | 
			
		||||
 * This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on
 | 
			
		||||
 * 16 Feb 1994.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
#ifndef __ARM_HAVE_CLZ
 | 
			
		||||
	/*
 | 
			
		||||
	 * now r0 has at most one set bit, call this X
 | 
			
		||||
	 * if X = 0, all further instructions are skipped
 | 
			
		||||
	 */
 | 
			
		||||
	adrne   r2, .L_ffs_table
 | 
			
		||||
	orrne   r0, r0, r0, lsl #4  /* r0 = X * 0x11 */ 
 | 
			
		||||
	orrne   r0, r0, r0, lsl #6  /* r0 = X * 0x451 */
 | 
			
		||||
	rsbne   r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */
 | 
			
		||||
              
 | 
			
		||||
	/* now lookup in table indexed on top 6 bits of r0 */
 | 
			
		||||
	ldrneb  r0, [ r2, r0, lsr #26 ]
 | 
			
		||||
 | 
			
		||||
	bx		lr
 | 
			
		||||
END(ffs)
 | 
			
		||||
 | 
			
		||||
.text;
 | 
			
		||||
.type .L_ffs_table, _ASM_TYPE_OBJECT;
 | 
			
		||||
.L_ffs_table:
 | 
			
		||||
/*               0   1   2   3   4   5   6   7           */
 | 
			
		||||
	.byte	 0,  1,  2, 13,  3,  7,  0, 14  /*  0- 7 */
 | 
			
		||||
	.byte	 4,  0,  8,  0,  0,  0,  0, 15  /*  8-15 */
 | 
			
		||||
	.byte	11,  5,  0,  0,  9,  0,  0, 26  /* 16-23 */
 | 
			
		||||
	.byte	 0,  0,  0,  0,  0, 22, 28, 16  /* 24-31 */
 | 
			
		||||
	.byte	32, 12,  6,  0,  0,  0,  0,  0	/* 32-39 */
 | 
			
		||||
	.byte	10,  0,  0, 25,  0,  0, 21, 27  /* 40-47 */
 | 
			
		||||
	.byte	31,  0,  0,  0,  0, 24,  0, 20  /* 48-55 */
 | 
			
		||||
	.byte   30,  0, 23, 19, 29, 18, 17,  0  /* 56-63 */
 | 
			
		||||
#else /* !defined(__ARM_HAVE_CLZ) */
 | 
			
		||||
	clzne	r0, r0
 | 
			
		||||
	rsbne	r0, r0, #32
 | 
			
		||||
	bx		lr
 | 
			
		||||
END(ffs)
 | 
			
		||||
#endif /* !defined(__ARM_HAVE_CLZ) */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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.
 | 
			
		||||
 */
 | 
			
		||||
/* 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).
 | 
			
		||||
*/
 | 
			
		||||
#include <sys/linux-syscalls.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#ifndef __NR_kill
 | 
			
		||||
#define __NR_kill   37
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(kill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_kill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    bxpl    lr
 | 
			
		||||
    b       __set_syscall_errno
 | 
			
		||||
END(kill)
 | 
			
		||||
@@ -1,159 +1,158 @@
 | 
			
		||||
/* 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 libn.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_l2d)          \
 | 
			
		||||
    XX(__aeabi_l2f)          \
 | 
			
		||||
    XX(__aeabi_lmul)         \
 | 
			
		||||
    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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										282
									
								
								libc/arch-arm/bionic/memcmp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								libc/arch-arm/bionic/memcmp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,282 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 memcmp() 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(memcmp)
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
 | 
			
		||||
        /* take of the case where length is 0 or the buffers are the same */
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        cmpne       r2, #0
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
 | 
			
		||||
        .save {r4, lr}
 | 
			
		||||
        /* save registers */
 | 
			
		||||
        stmfd       sp!, {r4, lr}
 | 
			
		||||
        
 | 
			
		||||
        PLD         (r0, #32)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
        /* since r0 hold the result, move the first source
 | 
			
		||||
         * pointer somewhere else
 | 
			
		||||
         */
 | 
			
		||||
         
 | 
			
		||||
         mov        r4, r0
 | 
			
		||||
         
 | 
			
		||||
         /* 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        8f
 | 
			
		||||
        
 | 
			
		||||
        /* 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, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        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
 | 
			
		||||
END(memcmp)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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, #64)
 | 
			
		||||
        PLD         (r4, #64)
 | 
			
		||||
        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
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
							
								
								
									
										499
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										499
									
								
								libc/arch-arm/bionic/memcpy.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,499 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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__)
 | 
			
		||||
 | 
			
		||||
        .text
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
 | 
			
		||||
/* a prefetch distance of 4 cache-lines works best experimentally */
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#define PREFETCH_DISTANCE   (CACHE_LINE_SIZE*4)
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*0)]
 | 
			
		||||
        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 half 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 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, #(CACHE_LINE_SIZE*2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*3)]
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0  - d3},   [r1]!
 | 
			
		||||
        vld1.8      {d4  - d7},   [r1]!
 | 
			
		||||
        pld         [r1, #(PREFETCH_DISTANCE)]
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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 */
 | 
			
		||||
							
								
								
									
										109
									
								
								libc/arch-arm/bionic/memset.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								libc/arch-arm/bionic/memset.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
	
 | 
			
		||||
		/*
 | 
			
		||||
		 * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
		 */
 | 
			
		||||
	
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov     r2, r1
 | 
			
		||||
        mov     r1, #0
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
		/* 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
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly 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
 | 
			
		||||
 | 
			
		||||
		/* conditionnaly 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)
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
}
 | 
			
		||||
@@ -25,27 +25,47 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <sys/linux-syscalls.h>
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(syscall)
 | 
			
		||||
	.text
 | 
			
		||||
	.align 4
 | 
			
		||||
	.type syscall,#function
 | 
			
		||||
	.globl syscall
 | 
			
		||||
 
 | 
			
		||||
	.text
 | 
			
		||||
	.align
 | 
			
		||||
 | 
			
		||||
#if __ARM_EABI__
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
    stmfd	sp!, {r4, r5, r6, r7}
 | 
			
		||||
    mov     r7, r0
 | 
			
		||||
    mov     r0, r1
 | 
			
		||||
    mov     r1, r2
 | 
			
		||||
    mov     r2, r3
 | 
			
		||||
    ldmfd   ip, {r3, r4, r5, r6}
 | 
			
		||||
    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
 | 
			
		||||
END(syscall)
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    bxpl    lr
 | 
			
		||||
    b       __set_syscall_errno
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#ifndef __NR_syscall
 | 
			
		||||
#define __NR_syscall    113
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
syscall:
 | 
			
		||||
    stmfd   sp!, {r4, r5, lr}
 | 
			
		||||
    ldr     r4, [sp, #12]
 | 
			
		||||
    ldr     r5, [sp, #16]
 | 
			
		||||
    swi     __NR_syscall
 | 
			
		||||
    ldmfd   sp!, {r4, r5, lr}
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    bxpl    lr
 | 
			
		||||
    b       __set_syscall_errno
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								libc/arch-arm/bionic/tkill.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								libc/arch-arm/bionic/tkill.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
/* 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).
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <sys/linux-syscalls.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#ifndef __NR_tkill
 | 
			
		||||
#define __NR_tkill  238
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(tkill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_tkill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    bxpl    lr
 | 
			
		||||
    b       __set_syscall_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"
 | 
			
		||||
@@ -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,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,191 +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 <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * 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)
 | 
			
		||||
 | 
			
		||||
ENTRY(bzero)
 | 
			
		||||
        mov         r2, r1
 | 
			
		||||
        mov         r1, #0
 | 
			
		||||
.L_done:
 | 
			
		||||
        // Fall through to memset...
 | 
			
		||||
END(bzero)
 | 
			
		||||
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        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.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         .L_set_less_than_16_unknown_align
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
 | 
			
		||||
.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
 | 
			
		||||
 | 
			
		||||
.L_double_word_aligned:
 | 
			
		||||
        mov         r0, r1
 | 
			
		||||
 | 
			
		||||
        subs        r2, #64
 | 
			
		||||
        blo         .L_set_less_than_64
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
        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
 | 
			
		||||
        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)
 | 
			
		||||
@@ -1,376 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_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
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
      /* 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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
        .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
 | 
			
		||||
        .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 */
 | 
			
		||||
 | 
			
		||||
        .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.  */
 | 
			
		||||
        uadd8   ip, \w1, r6
 | 
			
		||||
        sel     ip, r7, r6
 | 
			
		||||
        .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 */
 | 
			
		||||
 | 
			
		||||
        pld [r0, #0]
 | 
			
		||||
        pld [r1, #0]
 | 
			
		||||
 | 
			
		||||
        /* Are both strings double-word aligned?  */
 | 
			
		||||
        orr     ip, r0, r1
 | 
			
		||||
        tst     ip, #7
 | 
			
		||||
        bne     .L_do_align
 | 
			
		||||
 | 
			
		||||
        /* Fast path.  */
 | 
			
		||||
        init
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned:
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are double-word aligned.  */
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
2:
 | 
			
		||||
        pld [r0, #16]
 | 
			
		||||
        pld [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=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
.L_do_align:
 | 
			
		||||
        /* Is the first string word-aligned?  */
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        beq     .L_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 boundary is 4-ip.  */
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        lsls    ip, ip, #31
 | 
			
		||||
        beq     .L_byte2
 | 
			
		||||
        bcs     .L_byte3
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_fast_return:
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
.L_word_aligned_r0:
 | 
			
		||||
        init
 | 
			
		||||
        /* The first string is word-aligned.  */
 | 
			
		||||
        /* Is the second string word-aligned?  */
 | 
			
		||||
        ands    ip, r1, #3
 | 
			
		||||
        bne     .L_strcmp_unaligned
 | 
			
		||||
 | 
			
		||||
.L_word_aligned:
 | 
			
		||||
        /* The strings are word-aligned. */
 | 
			
		||||
        /* Is the first string double-word aligned?  */
 | 
			
		||||
        tst     r0, #4
 | 
			
		||||
        beq     .L_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
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned_r0:
 | 
			
		||||
        /* Get here when r0 is double-word aligned.  */
 | 
			
		||||
        /* Is r1 doubleword_aligned?  */
 | 
			
		||||
        tst     r1, #4
 | 
			
		||||
        beq     .L_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:
 | 
			
		||||
        pld [r0, #16]
 | 
			
		||||
        pld [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=.L_return_25
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=.L_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     .L_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
 | 
			
		||||
        b       7b
 | 
			
		||||
        .endm /* miscmp_word */
 | 
			
		||||
 | 
			
		||||
.L_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.  */
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.L_return_32:
 | 
			
		||||
        setup_return w1=r3, w2=r2
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_34:
 | 
			
		||||
        setup_return w1=r3, w2=r4
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_25:
 | 
			
		||||
        setup_return w1=r2, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_35:
 | 
			
		||||
        setup_return w1=r3, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_24:
 | 
			
		||||
        setup_return w1=r2, w2=r4
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
        .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
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
END(strcmp)
 | 
			
		||||
@@ -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 +0,0 @@
 | 
			
		||||
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 \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
@@ -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 +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"
 | 
			
		||||
@@ -1,82 +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>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
        .syntax unified
 | 
			
		||||
        .fpu    neon
 | 
			
		||||
        .thumb
 | 
			
		||||
        .thumb_func
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
 | 
			
		||||
        // Fall through to memcpy...
 | 
			
		||||
END(__memcpy_chk)
 | 
			
		||||
 | 
			
		||||
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]
 | 
			
		||||
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)
 | 
			
		||||
@@ -1,189 +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>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This code assumes it is running on a processor that supports all arm v7
 | 
			
		||||
 * instructions and that supports neon instructions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .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.
 | 
			
		||||
        cmp         r2, #132
 | 
			
		||||
        bhi         __memset_large_copy
 | 
			
		||||
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
        /* 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
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        // writes 16 bytes, 128-bits aligned
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
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
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        /* 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
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {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
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       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
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      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"
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -1,548 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_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
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
      /* 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.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
        .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
 | 
			
		||||
        .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 */
 | 
			
		||||
 | 
			
		||||
        .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.  */
 | 
			
		||||
        uadd8   ip, \w1, r6
 | 
			
		||||
        sel     ip, r7, r6
 | 
			
		||||
        .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 */
 | 
			
		||||
 | 
			
		||||
        pld [r0, #0]
 | 
			
		||||
        pld [r1, #0]
 | 
			
		||||
 | 
			
		||||
        /* Are both strings double-word aligned?  */
 | 
			
		||||
        orr     ip, r0, r1
 | 
			
		||||
        tst     ip, #7
 | 
			
		||||
        bne     .L_do_align
 | 
			
		||||
 | 
			
		||||
        /* Fast path.  */
 | 
			
		||||
        init
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned:
 | 
			
		||||
 | 
			
		||||
        /* Get here when the strings to compare are double-word aligned.  */
 | 
			
		||||
        /* Compare two words in every iteration.  */
 | 
			
		||||
        .p2align        2
 | 
			
		||||
2:
 | 
			
		||||
        pld [r0, #16]
 | 
			
		||||
        pld [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=.L_return_24
 | 
			
		||||
        magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
 | 
			
		||||
        b       2b
 | 
			
		||||
 | 
			
		||||
.L_do_align:
 | 
			
		||||
        /* Is the first string word-aligned?  */
 | 
			
		||||
        ands    ip, r0, #3
 | 
			
		||||
        beq     .L_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 boundary is 4-ip.  */
 | 
			
		||||
        bic     r0, r0, #3
 | 
			
		||||
        ldr     r2, [r0], #4
 | 
			
		||||
        lsls    ip, ip, #31
 | 
			
		||||
        beq     .L_byte2
 | 
			
		||||
        bcs     .L_byte3
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
.L_fast_return:
 | 
			
		||||
        mov     r0, ip
 | 
			
		||||
        bx      lr
 | 
			
		||||
 | 
			
		||||
.L_word_aligned_r0:
 | 
			
		||||
        init
 | 
			
		||||
        /* The first string is word-aligned.  */
 | 
			
		||||
        /* Is the second string word-aligned?  */
 | 
			
		||||
        ands    ip, r1, #3
 | 
			
		||||
        bne     .L_strcmp_unaligned
 | 
			
		||||
 | 
			
		||||
.L_word_aligned:
 | 
			
		||||
        /* The strings are word-aligned. */
 | 
			
		||||
        /* Is the first string double-word aligned?  */
 | 
			
		||||
        tst     r0, #4
 | 
			
		||||
        beq     .L_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
 | 
			
		||||
 | 
			
		||||
.L_doubleword_aligned_r0:
 | 
			
		||||
        /* Get here when r0 is double-word aligned.  */
 | 
			
		||||
        /* Is r1 doubleword_aligned?  */
 | 
			
		||||
        tst     r1, #4
 | 
			
		||||
        beq     .L_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:
 | 
			
		||||
        pld [r0, #16]
 | 
			
		||||
        pld [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=.L_return_25
 | 
			
		||||
        ldrd    r4, r5, [r1], #8
 | 
			
		||||
        magic_compare_and_branch w1=r3 w2=r4 label=.L_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     .L_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
 | 
			
		||||
        b       7b
 | 
			
		||||
        .endm /* miscmp_word */
 | 
			
		||||
 | 
			
		||||
.L_return_32:
 | 
			
		||||
        setup_return w1=r3, w2=r2
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_34:
 | 
			
		||||
        setup_return w1=r3, w2=r4
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_25:
 | 
			
		||||
        setup_return w1=r2, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_35:
 | 
			
		||||
        setup_return w1=r3, w2=r5
 | 
			
		||||
        b       .L_do_return
 | 
			
		||||
.L_return_24:
 | 
			
		||||
        setup_return w1=r2, w2=r4
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
        .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
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
.L_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
 | 
			
		||||
 | 
			
		||||
    /* The code from the previous version of strcmp.S handles all of the
 | 
			
		||||
     * cases where the first string and seconds string cannot both be
 | 
			
		||||
     * aligned to a word boundary faster than the new algorithm. See
 | 
			
		||||
     * bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
 | 
			
		||||
     * version of the code.
 | 
			
		||||
     */
 | 
			
		||||
.L_strcmp_unaligned:
 | 
			
		||||
	wp1 .req r0
 | 
			
		||||
	wp2 .req r1
 | 
			
		||||
	b1  .req r2
 | 
			
		||||
	w1  .req r4
 | 
			
		||||
	w2  .req r5
 | 
			
		||||
	t1  .req ip
 | 
			
		||||
	@ r3 is scratch
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
    /* Restore registers and stack. */
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
    /* Restore registers and stack. */
 | 
			
		||||
    ldrd    r6, r7, [sp]
 | 
			
		||||
    ldrd    r4, r5, [sp, #8]
 | 
			
		||||
    adds    sp, sp, #16
 | 
			
		||||
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(strcmp)
 | 
			
		||||
@@ -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 +0,0 @@
 | 
			
		||||
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 \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcmp.S \
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/denver/bionic/memmove.S \
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -1,412 +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>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memcpy() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * note that memcpy() always returns the destination pointer,
 | 
			
		||||
         * 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
 | 
			
		||||
         */
 | 
			
		||||
        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 */
 | 
			
		||||
        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]
 | 
			
		||||
 | 
			
		||||
        /* it simplifies things to take care of len<4 early */
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lcopy_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
 | 
			
		||||
 | 
			
		||||
        /* 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 */
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
 | 
			
		||||
        /* see if src and dst are aligned together (congruent) */
 | 
			
		||||
        eor         r12, r0, r1
 | 
			
		||||
        tst         r12, #3
 | 
			
		||||
        bne         .Lnon_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         .Lcongruent_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}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
.Lcongruent_aligned32:
 | 
			
		||||
        /*
 | 
			
		||||
         * here source is aligned to 32 bytes.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
.Lcached_aligned32:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         .Lless_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
 | 
			
		||||
 | 
			
		||||
.Lless_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
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
        ldmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
        /********************************************************************/
 | 
			
		||||
 | 
			
		||||
.Lnon_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         .Lcopy_last_3_and_return
 | 
			
		||||
 | 
			
		||||
        /* Use post-increment 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
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
        blo         .Lpartial_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         .Lpartial_word_tail
 | 
			
		||||
 | 
			
		||||
        /* copy 32 bytes at a time */
 | 
			
		||||
2:      subs        r2, r2, #32
 | 
			
		||||
        blo         .Lless_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         .Lloop24
 | 
			
		||||
        cmp         r12, #8
 | 
			
		||||
        beq         .Lloop8
 | 
			
		||||
 | 
			
		||||
.Lloop16:
 | 
			
		||||
        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           .Lless_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
.Lloop8:
 | 
			
		||||
        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           .Lless_than_thirtytwo
 | 
			
		||||
 | 
			
		||||
.Lloop24:
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.Lless_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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
.Lpartial_word_tail:
 | 
			
		||||
        /* we have a partial word in the input buffer */
 | 
			
		||||
        movs        r5, lr, lsl #(31-3)
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        /* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
        ldmfd       sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
.Lcopy_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]
 | 
			
		||||
 | 
			
		||||
        /* 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"
 | 
			
		||||
@@ -1,135 +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>
 | 
			
		||||
#include <private/libc_events.h>
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Optimized memset() for ARM.
 | 
			
		||||
         *
 | 
			
		||||
         * 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)
 | 
			
		||||
        /* 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
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {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
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       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
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
        .string     "memset: prevented write past end of buffer"
 | 
			
		||||
@@ -1,317 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <private/bionic_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)
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user