Compare commits
	
		
			2 Commits
		
	
	
		
			android-5.
			...
			jb-mr1-dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f7a9a681ab | ||
| 
						 | 
					1d69ab1de9 | 
							
								
								
									
										12
									
								
								ABI-bugs.txt
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								ABI-bugs.txt
									
									
									
									
									
								
							@@ -1,12 +0,0 @@
 | 
			
		||||
KNOWN ABI BUGS
 | 
			
		||||
--------------
 | 
			
		||||
 | 
			
		||||
  time_t is 32-bit. http://b/5819737
 | 
			
		||||
 | 
			
		||||
  off_t is 32-bit. There is off64_t, but no _FILE_OFFSET_BITS support.
 | 
			
		||||
 | 
			
		||||
  sigset_t is too small on ARM and x86 (but correct on MIPS), so support
 | 
			
		||||
  for real-time signals is broken. http://b/5828899
 | 
			
		||||
 | 
			
		||||
  atexit(3) handlers registered by a shared library aren't called on
 | 
			
		||||
  dlclose(3); this only affects ARM. http://b/4998315
 | 
			
		||||
@@ -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
 | 
			
		||||
# ************************************************
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										162
									
								
								HACKING.txt
									
									
									
									
									
								
							
							
						
						
									
										162
									
								
								HACKING.txt
									
									
									
									
									
								
							@@ -1,162 +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/?
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
@@ -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.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
ifneq ($(BUILD_TINY_ANDROID), true)
 | 
			
		||||
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Benchmarks.
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
benchmark_c_flags = \
 | 
			
		||||
    -O2 \
 | 
			
		||||
    -Wall -Wextra -Wunused \
 | 
			
		||||
    -Werror \
 | 
			
		||||
    -fno-builtin \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
benchmark_src_files = \
 | 
			
		||||
    benchmark_main.cpp \
 | 
			
		||||
    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-benchmarks
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE := bionic-benchmarks
 | 
			
		||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks32
 | 
			
		||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks64
 | 
			
		||||
LOCAL_MULTILIB := both
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_CFLAGS += $(benchmark_c_flags)
 | 
			
		||||
LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
 | 
			
		||||
LOCAL_SHARED_LIBRARIES += libstlport
 | 
			
		||||
LOCAL_SRC_FILES := $(benchmark_src_files)
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 | 
			
		||||
ifeq ($(TARGET_ARCH),x86)
 | 
			
		||||
LINKER = linker
 | 
			
		||||
NATIVE_SUFFIX=32
 | 
			
		||||
else
 | 
			
		||||
LINKER = linker64
 | 
			
		||||
NATIVE_SUFFIX=64
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
bionic-benchmarks-run-on-host: bionic-benchmarks $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
 | 
			
		||||
	if [ ! -d /system -o ! -d /system/bin ]; then \
 | 
			
		||||
	  echo "Attempting to create /system/bin"; \
 | 
			
		||||
	  sudo mkdir -p -m 0777 /system/bin; \
 | 
			
		||||
	fi
 | 
			
		||||
	mkdir -p $(TARGET_OUT_DATA)/local/tmp
 | 
			
		||||
	cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin
 | 
			
		||||
	cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
 | 
			
		||||
	ANDROID_DATA=$(TARGET_OUT_DATA) \
 | 
			
		||||
	ANDROID_ROOT=$(TARGET_OUT) \
 | 
			
		||||
	LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
 | 
			
		||||
		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks$(NATIVE_SUFFIX) $(BIONIC_BENCHMARKS_FLAGS)
 | 
			
		||||
endif # linux-x86
 | 
			
		||||
 | 
			
		||||
endif # !BUILD_TINY_ANDROID
 | 
			
		||||
@@ -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 <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
class Benchmark {
 | 
			
		||||
 public:
 | 
			
		||||
  Benchmark(const char* name, void (*fn)(int)) {
 | 
			
		||||
    Register(name, fn, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Benchmark(const char* name, void (*fn_range)(int, int)) {
 | 
			
		||||
    Register(name, NULL, fn_range);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Benchmark* Arg(int x);
 | 
			
		||||
 | 
			
		||||
  const char* Name();
 | 
			
		||||
 | 
			
		||||
  bool ShouldRun(int argc, char* argv[]);
 | 
			
		||||
  void Run();
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const char* name_;
 | 
			
		||||
 | 
			
		||||
  void (*fn_)(int);
 | 
			
		||||
  void (*fn_range_)(int, int);
 | 
			
		||||
 | 
			
		||||
  std::vector<int> args_;
 | 
			
		||||
 | 
			
		||||
  void Register(const char* name, void (*fn)(int), void (*fn_range)(int, int));
 | 
			
		||||
  void RunRepeatedlyWithArg(int iterations, int arg);
 | 
			
		||||
  void RunWithArg(int arg);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
void SetBenchmarkBytesProcessed(int64_t);
 | 
			
		||||
void StopBenchmarkTiming();
 | 
			
		||||
void StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
#define BENCHMARK(f) \
 | 
			
		||||
    static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
 | 
			
		||||
        (new ::testing::Benchmark(#f, f))
 | 
			
		||||
@@ -1,226 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
static int64_t g_bytes_processed;
 | 
			
		||||
static int64_t g_benchmark_total_time_ns;
 | 
			
		||||
static int64_t g_benchmark_start_time_ns;
 | 
			
		||||
 | 
			
		||||
typedef std::map<std::string, ::testing::Benchmark*> BenchmarkMap;
 | 
			
		||||
typedef BenchmarkMap::iterator BenchmarkMapIt;
 | 
			
		||||
static BenchmarkMap g_benchmarks;
 | 
			
		||||
static int g_name_column_width = 20;
 | 
			
		||||
 | 
			
		||||
static 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int64_t NanoTime() {
 | 
			
		||||
  struct timespec t;
 | 
			
		||||
  t.tv_sec = t.tv_nsec = 0;
 | 
			
		||||
  clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
Benchmark* Benchmark::Arg(int arg) {
 | 
			
		||||
  args_.push_back(arg);
 | 
			
		||||
  return this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* Benchmark::Name() {
 | 
			
		||||
  return name_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Benchmark::ShouldRun(int argc, char* argv[]) {
 | 
			
		||||
  if (argc == 1) {
 | 
			
		||||
    return true;  // With no arguments, we run all benchmarks.
 | 
			
		||||
  }
 | 
			
		||||
  // Otherwise, we interpret each argument as a regular expression and
 | 
			
		||||
  // see if any of our benchmarks match.
 | 
			
		||||
  for (int i = 1; i < argc; i++) {
 | 
			
		||||
    regex_t re;
 | 
			
		||||
    if (regcomp(&re, argv[i], 0) != 0) {
 | 
			
		||||
      fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]);
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    int match = regexec(&re, name_, 0, NULL, 0);
 | 
			
		||||
    regfree(&re);
 | 
			
		||||
    if (match != REG_NOMATCH) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int, int)) {
 | 
			
		||||
  name_ = name;
 | 
			
		||||
  fn_ = fn;
 | 
			
		||||
  fn_range_ = fn_range;
 | 
			
		||||
 | 
			
		||||
  if (fn_ == NULL && fn_range_ == NULL) {
 | 
			
		||||
    fprintf(stderr, "%s: missing function\n", name_);
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  g_benchmarks.insert(std::make_pair(name, this));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::Run() {
 | 
			
		||||
  if (fn_ != NULL) {
 | 
			
		||||
    RunWithArg(0);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (args_.empty()) {
 | 
			
		||||
      fprintf(stderr, "%s: no args!\n", name_);
 | 
			
		||||
      exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0; i < args_.size(); ++i) {
 | 
			
		||||
      RunWithArg(args_[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
 | 
			
		||||
  g_bytes_processed = 0;
 | 
			
		||||
  g_benchmark_total_time_ns = 0;
 | 
			
		||||
  g_benchmark_start_time_ns = NanoTime();
 | 
			
		||||
  if (fn_ != NULL) {
 | 
			
		||||
    fn_(iterations);
 | 
			
		||||
  } else {
 | 
			
		||||
    fn_range_(iterations, arg);
 | 
			
		||||
  }
 | 
			
		||||
  if (g_benchmark_start_time_ns != 0) {
 | 
			
		||||
    g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Benchmark::RunWithArg(int arg) {
 | 
			
		||||
  // run once in case it's expensive
 | 
			
		||||
  int iterations = 1;
 | 
			
		||||
  RunRepeatedlyWithArg(iterations, arg);
 | 
			
		||||
  while (g_benchmark_total_time_ns < 1e9 && iterations < 1e9) {
 | 
			
		||||
    int last = iterations;
 | 
			
		||||
    if (g_benchmark_total_time_ns/iterations == 0) {
 | 
			
		||||
      iterations = 1e9;
 | 
			
		||||
    } else {
 | 
			
		||||
      iterations = 1e9 / (g_benchmark_total_time_ns/iterations);
 | 
			
		||||
    }
 | 
			
		||||
    iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last));
 | 
			
		||||
    iterations = Round(iterations);
 | 
			
		||||
    RunRepeatedlyWithArg(iterations, arg);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char throughput[100];
 | 
			
		||||
  throughput[0] = '\0';
 | 
			
		||||
  if (g_benchmark_total_time_ns > 0 && g_bytes_processed > 0) {
 | 
			
		||||
    double mib_processed = static_cast<double>(g_bytes_processed)/1e6;
 | 
			
		||||
    double seconds = static_cast<double>(g_benchmark_total_time_ns)/1e9;
 | 
			
		||||
    snprintf(throughput, sizeof(throughput), " %8.2f MiB/s", mib_processed/seconds);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char full_name[100];
 | 
			
		||||
  if (fn_range_ != NULL) {
 | 
			
		||||
    if (arg >= (1<<20)) {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%dM", name_, arg/(1<<20));
 | 
			
		||||
    } else if (arg >= (1<<10)) {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%dK", name_, arg/(1<<10));
 | 
			
		||||
    } else {
 | 
			
		||||
      snprintf(full_name, sizeof(full_name), "%s/%d", name_, arg);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    snprintf(full_name, sizeof(full_name), "%s", name_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  printf("%-*s %10d %10" PRId64 "%s\n", g_name_column_width, full_name,
 | 
			
		||||
         iterations, g_benchmark_total_time_ns/iterations, throughput);
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
void SetBenchmarkBytesProcessed(int64_t x) {
 | 
			
		||||
  g_bytes_processed = x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StopBenchmarkTiming() {
 | 
			
		||||
  if (g_benchmark_start_time_ns != 0) {
 | 
			
		||||
    g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
 | 
			
		||||
  }
 | 
			
		||||
  g_benchmark_start_time_ns = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StartBenchmarkTiming() {
 | 
			
		||||
  if (g_benchmark_start_time_ns == 0) {
 | 
			
		||||
    g_benchmark_start_time_ns = NanoTime();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
  if (g_benchmarks.empty()) {
 | 
			
		||||
    fprintf(stderr, "No benchmarks registered!\n");
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
    int name_width = static_cast<int>(strlen(it->second->Name()));
 | 
			
		||||
    g_name_column_width = std::max(g_name_column_width, name_width);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool need_header = true;
 | 
			
		||||
  for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
    ::testing::Benchmark* b = it->second;
 | 
			
		||||
    if (b->ShouldRun(argc, argv)) {
 | 
			
		||||
      if (need_header) {
 | 
			
		||||
        printf("%-*s %10s %10s\n", g_name_column_width, "", "iterations", "ns/op");
 | 
			
		||||
        fflush(stdout);
 | 
			
		||||
        need_header = false;
 | 
			
		||||
      }
 | 
			
		||||
      b->Run();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (need_header) {
 | 
			
		||||
    fprintf(stderr, "No matching benchmarks!\n");
 | 
			
		||||
    fprintf(stderr, "Available benchmarks:\n");
 | 
			
		||||
    for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
 | 
			
		||||
      fprintf(stderr, "  %s\n", it->second->Name());
 | 
			
		||||
    }
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,211 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <fenv.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
// Avoid optimization.
 | 
			
		||||
double d;
 | 
			
		||||
double v;
 | 
			
		||||
 | 
			
		||||
static void BM_math_sqrt(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 2.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += sqrt(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sqrt);
 | 
			
		||||
 | 
			
		||||
static void BM_math_log10(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += log10(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_log10);
 | 
			
		||||
 | 
			
		||||
static void BM_math_logb(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += logb(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_logb);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_NORMAL(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0; // FP_NORMAL
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_NORMAL);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_NAN(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = nan(""); // FP_NAN
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_NAN);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_INFINITE(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = HUGE_VAL; // FP_INFINITE
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_INFINITE);
 | 
			
		||||
 | 
			
		||||
static void BM_math_isinf_ZERO(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 0.0; // FP_ZERO
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += (isinf)(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_isinf_ZERO);
 | 
			
		||||
 | 
			
		||||
static void BM_math_sin_fast(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 1.0;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += sin(d);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_sin_fast);
 | 
			
		||||
 | 
			
		||||
static void BM_math_sin_feupdateenv(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(BM_math_sin_feupdateenv);
 | 
			
		||||
 | 
			
		||||
static void BM_math_sin_fesetenv(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(BM_math_sin_fesetenv);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_NORMAL(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 1234.0; // FP_NORMAL
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_NORMAL);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_NAN(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = nan(""); // FP_NAN
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_NAN);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_INFINITE(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = HUGE_VAL; // FP_INFINITE
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_INFINITE);
 | 
			
		||||
 | 
			
		||||
static void BM_math_fpclassify_ZERO(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  d = 0.0;
 | 
			
		||||
  v = 0.0; // FP_ZERO
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    d += fpclassify(v);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_math_fpclassify_ZERO);
 | 
			
		||||
@@ -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 "benchmark.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 | 
			
		||||
#include <sys/_system_properties.h>
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void BM_property_get(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(BM_property_get)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
static void BM_property_find(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(BM_property_find)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
static void BM_property_read(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(BM_property_read)->TEST_NUM_PROPS;
 | 
			
		||||
 | 
			
		||||
static void BM_property_serial(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;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
 | 
			
		||||
@@ -1,107 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_self(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_self_fp();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_self);
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_getspecific(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(BM_pthread_getspecific);
 | 
			
		||||
 | 
			
		||||
static void DummyPthreadOnceInitFunction() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_once(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(BM_pthread_once);
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_mutex_lock(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(BM_pthread_mutex_lock);
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_mutex_lock_ERRORCHECK(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_mutex_lock(&mutex);
 | 
			
		||||
    pthread_mutex_unlock(&mutex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
 | 
			
		||||
 | 
			
		||||
static void BM_pthread_mutex_lock_RECURSIVE(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    pthread_mutex_lock(&mutex);
 | 
			
		||||
    pthread_mutex_unlock(&mutex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
 | 
			
		||||
@@ -1,49 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
static void BM_semaphore_sem_getvalue(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(BM_semaphore_sem_getvalue);
 | 
			
		||||
 | 
			
		||||
static void BM_semaphore_sem_wait_sem_post(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();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_semaphore_sem_wait_sem_post);
 | 
			
		||||
@@ -1,61 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.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)
 | 
			
		||||
 | 
			
		||||
static void BM_stdio_fread(int iters, int chunk_size) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  FILE* fp = fopen("/dev/zero", "rw");
 | 
			
		||||
  char* buf = new char[chunk_size];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    fread(buf, chunk_size, 1, fp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void BM_stdio_fwrite(int iters, int chunk_size) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  FILE* fp = fopen("/dev/zero", "rw");
 | 
			
		||||
  char* buf = new char[chunk_size];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
      fwrite(buf, chunk_size, 1, fp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
 | 
			
		||||
@@ -1,112 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <string.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.)
 | 
			
		||||
 | 
			
		||||
static void BM_string_memcmp(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(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
static void BM_string_memcpy(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(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
static void BM_string_memmove(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(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
static void BM_string_memset(int iters, int nbytes) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  char* dst = new char[nbytes];
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    memset(dst, 0, nbytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
  SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
 | 
			
		||||
 | 
			
		||||
static void BM_string_strlen(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(int64_t(iters) * int64_t(nbytes));
 | 
			
		||||
  delete[] s;
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
 | 
			
		||||
@@ -1,79 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
static void BM_time_clock_gettime(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    clock_gettime(CLOCK_MONOTONIC, &t);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_clock_gettime);
 | 
			
		||||
 | 
			
		||||
static void BM_time_clock_gettime_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timespec t;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_clock_gettime_syscall);
 | 
			
		||||
 | 
			
		||||
static void BM_time_gettimeofday(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    gettimeofday(&tv, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_gettimeofday);
 | 
			
		||||
 | 
			
		||||
static void BM_time_gettimeofday_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  timeval tv;
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_gettimeofday, &tv, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_gettimeofday_syscall);
 | 
			
		||||
 | 
			
		||||
static void BM_time_time(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    time(NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_time_time);
 | 
			
		||||
@@ -1,67 +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 "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
static void BM_unistd_getpid(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    getpid();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_getpid);
 | 
			
		||||
 | 
			
		||||
static void BM_unistd_getpid_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_getpid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_getpid_syscall);
 | 
			
		||||
 | 
			
		||||
// Stop GCC optimizing out our pure function.
 | 
			
		||||
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
 | 
			
		||||
 | 
			
		||||
static void BM_unistd_gettid(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    gettid_fp();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_gettid);
 | 
			
		||||
 | 
			
		||||
static void BM_unistd_gettid_syscall(int iters) {
 | 
			
		||||
  StartBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    syscall(__NR_gettid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_unistd_gettid_syscall);
 | 
			
		||||
							
								
								
									
										1736
									
								
								libc/Android.mk
									
									
									
									
									
								
							
							
						
						
									
										1736
									
								
								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
 | 
			
		||||
							
								
								
									
										1854
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										1854
									
								
								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,334 +1,315 @@
 | 
			
		||||
# 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/_unistd.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, and x86, MIPS use:
 | 
			
		||||
#        return_type funcname[:syscall_name](parameters) arm_number,x86_number,mips_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,246
 | 
			
		||||
void    _exit_thread:exit (int)     1
 | 
			
		||||
pid_t   __fork:fork (void)           2
 | 
			
		||||
pid_t   _waitpid:waitpid (pid_t, int*, int, struct rusage*)   -1,7,7
 | 
			
		||||
int     __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*)          280,284,278
 | 
			
		||||
 | 
			
		||||
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,213,-1
 | 
			
		||||
int     __setuid:setuid (uid_t)   -1,-1,23
 | 
			
		||||
uid_t   getuid:getuid32 ()         199,199,-1
 | 
			
		||||
uid_t   getuid:getuid ()           -1,-1,24
 | 
			
		||||
gid_t   getgid:getgid32 ()         200,200,-1
 | 
			
		||||
gid_t   getgid:getgid ()           -1,-1,47
 | 
			
		||||
uid_t   geteuid:geteuid32 ()       201,201,-1
 | 
			
		||||
uid_t   geteuid:geteuid ()         -1,-1,49
 | 
			
		||||
gid_t   getegid:getegid32 ()       202,202,-1
 | 
			
		||||
gid_t   getegid:getegid ()         -1,-1,50
 | 
			
		||||
uid_t   getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid)   209,209,-1
 | 
			
		||||
uid_t   getresuid:getresuid (uid_t *ruid, uid_t *euid, uid_t *suid)     -1,-1,186
 | 
			
		||||
gid_t   getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid)   211,211,-1
 | 
			
		||||
gid_t   getresgid:getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid)     -1,-1,191
 | 
			
		||||
pid_t   gettid()                   224,224,222
 | 
			
		||||
ssize_t readahead(int, off64_t, size_t)     225,225,223
 | 
			
		||||
int     getgroups:getgroups32(int, gid_t *)    205,205,-1
 | 
			
		||||
int     getgroups:getgroups(int, gid_t *)      -1,-1,80
 | 
			
		||||
pid_t   getpgid(pid_t)             132
 | 
			
		||||
pid_t   getppid()                  64
 | 
			
		||||
pid_t   getsid(pid_t)              147
 | 
			
		||||
pid_t   setsid()                   66
 | 
			
		||||
int     setgid:setgid32(gid_t)     214,214,-1
 | 
			
		||||
int     setgid:setgid(gid_t)       -1,-1,46
 | 
			
		||||
int     seteuid:seteuid32(uid_t)   stub
 | 
			
		||||
int     __setreuid:setreuid32(uid_t, uid_t)   203,203,-1
 | 
			
		||||
int     __setreuid:setreuid(uid_t, uid_t)     -1,-1,70
 | 
			
		||||
int     __setresuid:setresuid32(uid_t, uid_t, uid_t)   208,208,-1
 | 
			
		||||
int     __setresuid:setresuid(uid_t, uid_t, uid_t)     -1,-1,185
 | 
			
		||||
int     setresgid:setresgid32(gid_t, gid_t, gid_t)   210,210,-1
 | 
			
		||||
int     setresgid:setresgid(gid_t, gid_t, gid_t)     -1,-1,190
 | 
			
		||||
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,37
 | 
			
		||||
int     tkill(pid_t tid, int sig)  -1,238,236
 | 
			
		||||
int     tgkill(pid_t tgid, pid_t tid, int sig)  -1,270,266
 | 
			
		||||
int     __ptrace:ptrace(int request, int pid, void* addr, void* data)  26
 | 
			
		||||
int     __set_thread_area:set_thread_area(void*  user_desc)  -1,243,283
 | 
			
		||||
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,191,-1
 | 
			
		||||
int     getrlimit:getrlimit(int resource, struct rlimit *rlp)  -1,-1,76
 | 
			
		||||
int     getrusage(int who, struct rusage*  r_usage)  77
 | 
			
		||||
int     setgroups:setgroups32(int, const gid_t *)   206,206,-1
 | 
			
		||||
int     setgroups:setgroups(int, const gid_t *)     -1,-1,81
 | 
			
		||||
pid_t   getpgrp(void)  stub
 | 
			
		||||
int     setpgid(pid_t, pid_t)  57
 | 
			
		||||
pid_t   vfork(void)  190,-1,-1
 | 
			
		||||
int     setregid:setregid32(gid_t, gid_t)  204,204,-1
 | 
			
		||||
int     setregid:setregid(gid_t, gid_t)    -1,-1,71
 | 
			
		||||
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,172,192
 | 
			
		||||
int     capget(cap_user_header_t header, cap_user_data_t data) 184,184,204
 | 
			
		||||
int     capset(cap_user_header_t header, const cap_user_data_t data) 185,185,205
 | 
			
		||||
int     sigaltstack(const stack_t*, stack_t*) 186,186,206
 | 
			
		||||
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(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(const 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(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(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     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(int, const char*, int, int)  all
 | 
			
		||||
int fchmodat(int, const char*, mode_t, int)  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,mips64,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 ftruncate(int, off_t) arm,mips,x86
 | 
			
		||||
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 fstatfs64|fstatfs:fstatfs(int, struct statfs*)  arm64,mips64,x86_64
 | 
			
		||||
int __statfs64:statfs64(const char*, size_t, struct statfs*)  arm,mips,x86
 | 
			
		||||
int statfs64|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,mips64,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,180,200
 | 
			
		||||
ssize_t     pwrite64 (int, void *, size_t, off64_t) 181,181,201
 | 
			
		||||
int         __open:open (const char*, int, mode_t)  5
 | 
			
		||||
int         __openat:openat (int, const char*, int, mode_t)  322,295,288
 | 
			
		||||
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,192,210
 | 
			
		||||
int         munmap(void *, size_t)  91
 | 
			
		||||
void *      mremap(void *, size_t, size_t, unsigned long)  163,163,167
 | 
			
		||||
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,218
 | 
			
		||||
int         mlock(const void *addr, size_t len)    150,150,154
 | 
			
		||||
int         munlock(const void *addr, size_t len)   151,151,155
 | 
			
		||||
int         mlockall(int flags)   152,152,156
 | 
			
		||||
int         munlockall()   153,153,157
 | 
			
		||||
int         mincore(void*  start, size_t  length, unsigned char*  vec)   219,218,217
 | 
			
		||||
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,328
 | 
			
		||||
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,194,212
 | 
			
		||||
int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   217,220,219
 | 
			
		||||
int         fsync(int)  118
 | 
			
		||||
int         fdatasync(int) 148,148,152
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  207,207,-1
 | 
			
		||||
int         fchown:fchown(int, uid_t, gid_t)    -1,-1,95
 | 
			
		||||
void        sync(void)  36
 | 
			
		||||
int         __fcntl64:fcntl64(int, int, void *)  221,221,220
 | 
			
		||||
int         __fstatfs64:fstatfs64(int, size_t, struct statfs *)  267,269,256
 | 
			
		||||
ssize_t     sendfile(int out_fd, int in_fd, off_t *offset, size_t count)  187,187,207
 | 
			
		||||
int         fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags)   327,300,293
 | 
			
		||||
int         mkdirat(int dirfd, const char *pathname, mode_t mode)  323,296,289
 | 
			
		||||
int         fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags)  325,298,291
 | 
			
		||||
int         fchmodat(int dirfd, const char *path, mode_t mode, int flags)  333,306,299
 | 
			
		||||
int         renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)  329,302,295
 | 
			
		||||
int         fsetxattr(int, const char *, const void *, size_t, int) 228,228,226
 | 
			
		||||
ssize_t     fgetxattr(int, const char *, void *, size_t) 231,231,229
 | 
			
		||||
ssize_t     flistxattr(int, char *, size_t) 234,234,232
 | 
			
		||||
int         fremovexattr(int, const char *) 237,237,235
 | 
			
		||||
 | 
			
		||||
# 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,294
 | 
			
		||||
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,212,-1
 | 
			
		||||
int     chown:chown(const char *, uid_t, gid_t)    -1,-1,202
 | 
			
		||||
int     lchown:lchown32 (const char*, uid_t, gid_t)  198,198,-1
 | 
			
		||||
int     lchown:lchown (const char*, uid_t, gid_t)  -1,-1,16
 | 
			
		||||
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,197,215
 | 
			
		||||
int     stat:stat64(const char *, struct stat *)  195,195,213
 | 
			
		||||
int     lstat:lstat64(const char *, struct stat *)  196,196,214
 | 
			
		||||
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,183,203
 | 
			
		||||
int     access(const char *, int)  33
 | 
			
		||||
int     faccessat(int, const char *, int, int)  334,307,300
 | 
			
		||||
int     symlink(const char *, const char *)  83
 | 
			
		||||
int     fchdir(int)    133
 | 
			
		||||
int     truncate(const char*, off_t)    92
 | 
			
		||||
int     setxattr(const char *, const char *, const void *, size_t, int) 226,226,224
 | 
			
		||||
int     lsetxattr(const char *, const char *, const void *, size_t, int) 227,227,225
 | 
			
		||||
ssize_t getxattr(const char *, const char *, void *, size_t) 229,229,227
 | 
			
		||||
ssize_t lgetxattr(const char *, const char *, void *, size_t) 230,230,228
 | 
			
		||||
ssize_t listxattr(const char *, char *, size_t) 232,232,230
 | 
			
		||||
ssize_t llistxattr(const char *, char *, size_t) 233,233,231
 | 
			
		||||
int     removexattr(const char *, const char *) 235,235,233
 | 
			
		||||
int     lremovexattr(const char *, const char *) 236,236,234
 | 
			
		||||
int     __statfs64:statfs64(const char *, size_t, struct statfs *)  266,268,255
 | 
			
		||||
long    unshare(unsigned long)  337,310,303
 | 
			
		||||
 | 
			
		||||
# 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 clk_id, const struct timespec* tp)  all
 | 
			
		||||
int           clock_getres(clockid_t clk_id, struct timespec* res)   all
 | 
			
		||||
int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem)  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,162,166
 | 
			
		||||
int           clock_gettime(clockid_t clk_id, struct timespec *tp)    263,265,263
 | 
			
		||||
int           clock_settime(clockid_t clk_id, const struct timespec *tp)  262,264,262
 | 
			
		||||
int           clock_getres(clockid_t clk_id, struct timespec *res)   264,266,264
 | 
			
		||||
int           clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem)  265,267,265
 | 
			
		||||
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,257
 | 
			
		||||
int           __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 258,260,258
 | 
			
		||||
int           __timer_gettime:timer_gettime(timer_t, struct itimerspec*)                                259,261,259
 | 
			
		||||
int           __timer_getoverrun:timer_getoverrun(timer_t)                                              260,262,260
 | 
			
		||||
int           __timer_delete:timer_delete(timer_t)                                                      261,263,261
 | 
			
		||||
int           utimes(const char*, const struct timeval tvp[2])                          269,271,267
 | 
			
		||||
int           utimensat(int, const char *, const struct timespec times[2], int)         348,320,316
 | 
			
		||||
 | 
			
		||||
# 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     __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,72,-1
 | 
			
		||||
int     __sigsuspend:sigsuspend(const sigset_t *mask)  -1,-1,72
 | 
			
		||||
int     __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize)  174,174,194
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  175,175,195
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177,177,197
 | 
			
		||||
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,183
 | 
			
		||||
int           socketpair(int, int, int, int*)    288,-1,184
 | 
			
		||||
int           bind(int, struct sockaddr *, int)  282,-1,169
 | 
			
		||||
int           connect(int, struct sockaddr *, socklen_t)   283,-1,170
 | 
			
		||||
int           listen(int, int)                   284,-1,174
 | 
			
		||||
int           accept(int, struct sockaddr *, socklen_t *)  285,-1,168
 | 
			
		||||
int           getsockname(int, struct sockaddr *, socklen_t *)  286,-1,172
 | 
			
		||||
int           getpeername(int, struct sockaddr *, socklen_t *)  287,-1,171
 | 
			
		||||
int           sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t)  290,-1,180
 | 
			
		||||
int           recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *)  292,-1,176
 | 
			
		||||
int           shutdown(int, int)  293,-1,182
 | 
			
		||||
int           setsockopt(int, int, int, const void *, socklen_t)  294,-1,181
 | 
			
		||||
int           getsockopt(int, int, int, void *, socklen_t *)    295,-1,173
 | 
			
		||||
int           sendmsg(int, const struct msghdr *, unsigned int)  296,-1,179
 | 
			
		||||
int           recvmsg(int, struct msghdr *, unsigned int)   297,-1,177
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
# 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,156,160
 | 
			
		||||
int sched_getscheduler(pid_t pid)  157,157,161
 | 
			
		||||
int sched_yield(void)  158,158,162
 | 
			
		||||
int sched_setparam(pid_t pid, const struct sched_param *param)  154,154,158
 | 
			
		||||
int sched_getparam(pid_t pid, struct sched_param *param)  155,155,159
 | 
			
		||||
int sched_get_priority_max(int policy)  159,159,163
 | 
			
		||||
int sched_get_priority_min(int policy)  160,160,164
 | 
			
		||||
int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161,161,165
 | 
			
		||||
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241,241,239
 | 
			
		||||
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242,242,240
 | 
			
		||||
int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318,312
 | 
			
		||||
 | 
			
		||||
# io priorities
 | 
			
		||||
int ioprio_set(int which, int who, int ioprio) 314,289,314
 | 
			
		||||
int ioprio_get(int which, int who) 315,290,315
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
long    perf_event_open(struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) 364
 | 
			
		||||
 | 
			
		||||
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,240,238
 | 
			
		||||
 | 
			
		||||
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,248
 | 
			
		||||
int     epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)    251,255,249
 | 
			
		||||
int     epoll_wait(int epfd, struct epoll_event *events, int max, int timeout)   252,256,250
 | 
			
		||||
 | 
			
		||||
int eventfd:eventfd2(unsigned int, int)  all
 | 
			
		||||
int     inotify_init(void)      316,291,284
 | 
			
		||||
int     inotify_add_watch(int, const char *, unsigned int)  317,292,285
 | 
			
		||||
int     inotify_rm_watch(int, unsigned int)  318,293,286
 | 
			
		||||
 | 
			
		||||
void _exit|_Exit:exit_group(int)  all
 | 
			
		||||
void __exit:exit(int)  all
 | 
			
		||||
int     poll(struct pollfd *, unsigned int, long)  168,168,188
 | 
			
		||||
 | 
			
		||||
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,325
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
int __set_tid_address:set_tid_address(int*)  all
 | 
			
		||||
 | 
			
		||||
int setfsgid(gid_t)  all
 | 
			
		||||
int setfsuid(uid_t)  all
 | 
			
		||||
 | 
			
		||||
pid_t wait4(pid_t, int*, int, struct rusage*)  all
 | 
			
		||||
int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*)  all
 | 
			
		||||
 | 
			
		||||
# ARM-specific
 | 
			
		||||
int     __set_tls:__ARM_NR_set_tls(void*)                                 arm
 | 
			
		||||
int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  arm
 | 
			
		||||
# ARM-specific ARM_NR_BASE == 0x0f0000 == 983040
 | 
			
		||||
int     __set_tls:ARM_set_tls(void*)                                 983045,-1,-1
 | 
			
		||||
int     cacheflush:ARM_cacheflush(long start, long end, long flags)  983042,-1,-1
 | 
			
		||||
 | 
			
		||||
# MIPS-specific
 | 
			
		||||
int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
 | 
			
		||||
int     __set_tls:set_thread_area(void*) mips,mips64
 | 
			
		||||
 | 
			
		||||
# x86-specific
 | 
			
		||||
int     __set_thread_area:set_thread_area(void*) x86
 | 
			
		||||
 | 
			
		||||
# vdso stuff.
 | 
			
		||||
int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
 | 
			
		||||
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
 | 
			
		||||
int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
 | 
			
		||||
int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
 | 
			
		||||
int	_flush_cache:cacheflush(char *addr, const int nbytes, const int op)	-1,-1,147
 | 
			
		||||
int	syscall(int number,...) -1,-1,0
 | 
			
		||||
 
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
# 32-bit arm.
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Various kinds of LP32 cruft.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    bionic/mmap.cpp \
 | 
			
		||||
 | 
			
		||||
libc_common_src_files_arm += \
 | 
			
		||||
    bionic/legacy_32_bit_support.cpp \
 | 
			
		||||
    bionic/ndk_cruft.cpp \
 | 
			
		||||
    bionic/time64.c \
 | 
			
		||||
 | 
			
		||||
libc_netbsd_src_files_arm += \
 | 
			
		||||
    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
 | 
			
		||||
 | 
			
		||||
libc_openbsd_src_files_arm += \
 | 
			
		||||
    upstream-openbsd/lib/libc/stdio/putw.c \
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default implementations of functions that are commonly optimized.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    bionic/memchr.c \
 | 
			
		||||
    bionic/memrchr.c \
 | 
			
		||||
    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/bcopy.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/memcmp.S \
 | 
			
		||||
    arch-arm/bionic/__restore.S \
 | 
			
		||||
    arch-arm/bionic/_setjmp.S \
 | 
			
		||||
    arch-arm/bionic/setjmp.S \
 | 
			
		||||
    arch-arm/bionic/sigsetjmp.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,110 +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*);
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,69 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <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}
 | 
			
		||||
 | 
			
		||||
    # store 'fn' and 'arg' to the child stack
 | 
			
		||||
    str     r5, [r1, #-4]
 | 
			
		||||
    str     r6, [r1, #-8]
 | 
			
		||||
 | 
			
		||||
    # System call
 | 
			
		||||
    ldr     r7, =__NR_clone
 | 
			
		||||
    swi     #0
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    beq     1f
 | 
			
		||||
 | 
			
		||||
    # In the parent, reload saved registers then either return or set errno.
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
 | 
			
		||||
1:  # The child.
 | 
			
		||||
    # Setting lr to 0 will make the unwinder stop at __start_thread
 | 
			
		||||
    mov    lr, #0
 | 
			
		||||
    ldr    r0, [sp, #-4]
 | 
			
		||||
    ldr    r1, [sp, #-8]
 | 
			
		||||
    b      __start_thread
 | 
			
		||||
END(__bionic_clone)
 | 
			
		||||
.hidden __bionic_clone
 | 
			
		||||
							
								
								
									
										34
									
								
								libc/arch-arm/bionic/__get_sp.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								libc/arch-arm/bionic/__get_sp.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
.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)
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
@@ -107,7 +107,7 @@ ENTRY(_longjmp)
 | 
			
		||||
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(longjmperror, PLT)
 | 
			
		||||
	bl	PIC_SYM(abort, PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(abort), PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(_longjmp)
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Coding the abort function in assembly so that registers are guaranteed to
 | 
			
		||||
@@ -36,9 +36,7 @@
 | 
			
		||||
 * sequence when the crash happens.
 | 
			
		||||
 */
 | 
			
		||||
ENTRY(abort)
 | 
			
		||||
    .save   {r3, r14}
 | 
			
		||||
    stmfd   sp!, {r3, r14}
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset r3, 0
 | 
			
		||||
    .cfi_rel_offset r14, 4
 | 
			
		||||
    bl      PIC_SYM(__libc_android_abort, PLT)
 | 
			
		||||
    blx     PIC_SYM(_C_LABEL(__libc_android_abort), PLT)
 | 
			
		||||
END(abort)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2012 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -27,10 +27,9 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <private/logd.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
 | 
			
		||||
@@ -51,9 +50,10 @@ atexit(void (*func)(void))
 | 
			
		||||
     * 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";
 | 
			
		||||
    static char const warning[] =
 | 
			
		||||
        "WARNING: generic atexit() called from legacy shared library\n";
 | 
			
		||||
 | 
			
		||||
    __libc_format_log(ANDROID_LOG_WARN, "libc", warning);
 | 
			
		||||
    __libc_android_log_print(ANDROID_LOG_WARN, "libc", warning);
 | 
			
		||||
    fprintf(stderr, warning);
 | 
			
		||||
 | 
			
		||||
    return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								libc/arch-arm/bionic/clone.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
    stmdb r1!, {r0, r3}
 | 
			
		||||
 | 
			
		||||
    @ 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
 | 
			
		||||
 | 
			
		||||
    pop     {r0, r1}
 | 
			
		||||
    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)
 | 
			
		||||
							
								
								
									
										68
									
								
								libc/arch-arm/bionic/crtbegin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								libc/arch-arm/bionic/crtbegin.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    void (**preinit_array)(void);
 | 
			
		||||
    void (**init_array)(void);
 | 
			
		||||
    void (**fini_array)(void);
 | 
			
		||||
} structors_array_t;
 | 
			
		||||
 | 
			
		||||
extern int main(int argc, char **argv, char **env);
 | 
			
		||||
 | 
			
		||||
extern void __libc_init(
 | 
			
		||||
  unsigned int *elfdata,
 | 
			
		||||
  void (*onexit)(void),
 | 
			
		||||
  int (*slingshot)(int, char**, char**),
 | 
			
		||||
  structors_array_t const * const structors
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".preinit_array")))
 | 
			
		||||
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".init_array")))
 | 
			
		||||
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__attribute__ ((section (".fini_array")))
 | 
			
		||||
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
 | 
			
		||||
 | 
			
		||||
__attribute__((visibility("hidden")))
 | 
			
		||||
void _start() {
 | 
			
		||||
  structors_array_t array;
 | 
			
		||||
  void *elfdata;
 | 
			
		||||
 | 
			
		||||
  array.preinit_array = &__PREINIT_ARRAY__;
 | 
			
		||||
  array.init_array =    &__INIT_ARRAY__;
 | 
			
		||||
  array.fini_array =    &__FINI_ARRAY__;
 | 
			
		||||
 | 
			
		||||
  elfdata = __builtin_frame_address(0) + sizeof(void *);
 | 
			
		||||
  __libc_init(elfdata, (void *) 0, &main, &array);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "__dso_handle.h"
 | 
			
		||||
#include "atexit.h"
 | 
			
		||||
							
								
								
									
										58
									
								
								libc/arch-arm/bionic/crtbegin_so.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libc/arch-arm/bionic/crtbegin_so.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern void __cxa_finalize(void *);
 | 
			
		||||
extern void *__dso_handle;
 | 
			
		||||
 | 
			
		||||
__attribute__((visibility("hidden"),destructor))
 | 
			
		||||
void __on_dlclose() {
 | 
			
		||||
  __cxa_finalize(&__dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* CRT_LEGACY_WORKAROUND should only be defined when building
 | 
			
		||||
 * this file as part of the platform's C library.
 | 
			
		||||
 *
 | 
			
		||||
 * The C library already defines a function named 'atexit()'
 | 
			
		||||
 * for backwards compatibility with older NDK-generated binaries.
 | 
			
		||||
 *
 | 
			
		||||
 * For newer ones, 'atexit' is actually embedded in the C
 | 
			
		||||
 * runtime objects that are linked into the final ELF
 | 
			
		||||
 * binary (shared library or executable), and will call
 | 
			
		||||
 * __cxa_atexit() in order to un-register any atexit()
 | 
			
		||||
 * handler when a library is unloaded.
 | 
			
		||||
 *
 | 
			
		||||
 * This function must be global *and* hidden. Only the
 | 
			
		||||
 * code inside the same ELF binary should be able to access it.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef CRT_LEGACY_WORKAROUND
 | 
			
		||||
#include "__dso_handle.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "__dso_handle_so.h"
 | 
			
		||||
#include "atexit.h"
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										40
									
								
								libc/arch-arm/bionic/crtend.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libc/arch-arm/bionic/crtend.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
	
 | 
			
		||||
	.section .preinit_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	.long 0
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) && defined(__ELF__)
 | 
			
		||||
	.section .note.GNU-stack,"",%progbits
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										31
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								libc/arch-arm/bionic/crtend_so.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) && defined(__ELF__)
 | 
			
		||||
	.section .note.GNU-stack,"",%progbits
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										103
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								libc/arch-arm/bionic/eabi.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
extern int  __cxa_atexit(void (*)(void*), void*, void* );
 | 
			
		||||
 | 
			
		||||
/* The "C++ ABI for ARM" document states that static C++ constructors,
 | 
			
		||||
 * which are called from the .init_array, should manually call
 | 
			
		||||
 * __aeabi_atexit() to register static destructors explicitely.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that 'dso_handle' is the address of a magic linker-generate
 | 
			
		||||
 * variable from the shared object that contains the constructor/destructor
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Make this a weak symbol to avoid a multiple definition error when linking
 | 
			
		||||
 * with libstdc++-v3.  */
 | 
			
		||||
int __attribute__((weak))
 | 
			
		||||
__aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle)
 | 
			
		||||
{
 | 
			
		||||
    return __cxa_atexit(destructor, object, dso_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memcpy(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memcpy(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove8(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove4(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memmove(void *dest, const void *src, size_t n) {
 | 
			
		||||
    memmove(dest, src, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * __aeabi_memset has the order of its second and third arguments reversed. 
 | 
			
		||||
 *  This allows __aeabi_memclr to tail-call __aeabi_memset
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
void __aeabi_memset8(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memset4(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memset(void *dest, size_t n, int c) {
 | 
			
		||||
    memset(dest, c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr8(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset8(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr4(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset4(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __aeabi_memclr(void *dest, size_t n) {
 | 
			
		||||
    __aeabi_memset(dest, n, 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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) */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										112
									
								
								libc/arch-arm/bionic/futex_arm.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								libc/arch-arm/bionic/futex_arm.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
 | 
			
		||||
/* __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)
 | 
			
		||||
							
								
								
									
										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,160 @@
 | 
			
		||||
/* Generated by genlibgcc_compat.py */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern char __adddf3;
 | 
			
		||||
extern char __addsf3;
 | 
			
		||||
extern char __aeabi_cdcmpeq;
 | 
			
		||||
extern char __aeabi_cdcmple;
 | 
			
		||||
extern char __aeabi_cdrcmple;
 | 
			
		||||
extern char __aeabi_d2f;
 | 
			
		||||
extern char __aeabi_d2iz;
 | 
			
		||||
extern char __aeabi_dadd;
 | 
			
		||||
extern char __aeabi_dcmpeq;
 | 
			
		||||
extern char __aeabi_dcmpge;
 | 
			
		||||
extern char __aeabi_dcmpgt;
 | 
			
		||||
extern char __aeabi_dcmple;
 | 
			
		||||
extern char __aeabi_dcmplt;
 | 
			
		||||
extern char __aeabi_dcmpun;
 | 
			
		||||
extern char __aeabi_ddiv;
 | 
			
		||||
extern char __aeabi_dmul;
 | 
			
		||||
extern char __aeabi_drsub;
 | 
			
		||||
extern char __aeabi_dsub;
 | 
			
		||||
extern char __aeabi_f2d;
 | 
			
		||||
extern char __aeabi_f2iz;
 | 
			
		||||
extern char __aeabi_f2uiz;
 | 
			
		||||
extern char __aeabi_fadd;
 | 
			
		||||
extern char __aeabi_fcmpun;
 | 
			
		||||
extern char __aeabi_fdiv;
 | 
			
		||||
extern char __aeabi_fmul;
 | 
			
		||||
extern char __aeabi_frsub;
 | 
			
		||||
extern char __aeabi_fsub;
 | 
			
		||||
extern char __aeabi_i2d;
 | 
			
		||||
extern char __aeabi_i2f;
 | 
			
		||||
extern char __aeabi_idiv;
 | 
			
		||||
extern char __aeabi_idivmod;
 | 
			
		||||
extern char __aeabi_l2d;
 | 
			
		||||
extern char __aeabi_l2f;
 | 
			
		||||
extern char __aeabi_lasr;
 | 
			
		||||
extern char __aeabi_ldivmod;
 | 
			
		||||
extern char __aeabi_llsl;
 | 
			
		||||
extern char __aeabi_llsr;
 | 
			
		||||
extern char __aeabi_lmul;
 | 
			
		||||
extern char __aeabi_ui2d;
 | 
			
		||||
extern char __aeabi_ui2f;
 | 
			
		||||
extern char __aeabi_uidiv;
 | 
			
		||||
extern char __aeabi_uidivmod;
 | 
			
		||||
extern char __aeabi_ul2d;
 | 
			
		||||
extern char __aeabi_ul2f;
 | 
			
		||||
extern char __aeabi_uldivmod;
 | 
			
		||||
extern char __aeabi_unwind_cpp_pr0;
 | 
			
		||||
extern char __aeabi_unwind_cpp_pr1;
 | 
			
		||||
extern char __cmpdf2;
 | 
			
		||||
extern char __divdf3;
 | 
			
		||||
extern char __divsf3;
 | 
			
		||||
extern char __eqdf2;
 | 
			
		||||
extern char __extendsfdf2;
 | 
			
		||||
extern char __fixdfsi;
 | 
			
		||||
extern char __fixsfsi;
 | 
			
		||||
extern char __floatdidf;
 | 
			
		||||
extern char __floatdisf;
 | 
			
		||||
extern char __floatsidf;
 | 
			
		||||
extern char __floatsisf;
 | 
			
		||||
extern char __floatundidf;
 | 
			
		||||
extern char __floatundisf;
 | 
			
		||||
extern char __floatunsidf;
 | 
			
		||||
extern char __floatunsisf;
 | 
			
		||||
extern char __gedf2;
 | 
			
		||||
extern char __gtdf2;
 | 
			
		||||
extern char __ledf2;
 | 
			
		||||
extern char __ltdf2;
 | 
			
		||||
extern char __muldf3;
 | 
			
		||||
extern char __muldi3;
 | 
			
		||||
extern char __mulsf3;
 | 
			
		||||
extern char __nedf2;
 | 
			
		||||
extern char __popcount_tab;
 | 
			
		||||
extern char __popcountsi2;
 | 
			
		||||
extern char __subdf3;
 | 
			
		||||
extern char __subsf3;
 | 
			
		||||
extern char __truncdfsf2;
 | 
			
		||||
extern char __unorddf2;
 | 
			
		||||
extern char __unordsf2;
 | 
			
		||||
/* This file contains dummy references to libgcc.a functions to force the
 | 
			
		||||
 * dynamic linker to copy their definition into the final libc.so binary.
 | 
			
		||||
 *
 | 
			
		||||
 * They are required to ensure backwards binary compatibility with
 | 
			
		||||
 * Android 1.5, 1.6 and even 3.0  system images. Some applications built
 | 
			
		||||
 * using the NDK require them to be here.
 | 
			
		||||
 *
 | 
			
		||||
 * Now, for a more elaborate description of the issue:
 | 
			
		||||
 *
 | 
			
		||||
 * libgcc.a is a compiler-specific library containing various helper
 | 
			
		||||
 * functions used to implement certain operations that are not necessarily
 | 
			
		||||
 * supported by the target CPU. For example, integer division doesn't have a
 | 
			
		||||
 * corresponding CPU instruction on ARMv5, and is instead implemented in the
 | 
			
		||||
 * compiler-generated machine code as a call to an __idiv helper function.
 | 
			
		||||
 *
 | 
			
		||||
 * Normally, one has to place libgcc.a in the link command used to generate
 | 
			
		||||
 * target binaries (shared libraries and executables) after all objects and
 | 
			
		||||
 * static libraries, but before dependent shared libraries, i.e. something
 | 
			
		||||
 * like:
 | 
			
		||||
 *         gcc <options> -o libfoo.so  foo.a libgcc.a -lc -lm
 | 
			
		||||
 *
 | 
			
		||||
 * This ensures that any helper function needed by the code in foo.a is copied
 | 
			
		||||
 * into the final libfoo.so. Unfortunately, the Android build system has been
 | 
			
		||||
 * using this instead:
 | 
			
		||||
 *
 | 
			
		||||
 *         gcc <options> -o libfoo.so foo.a -lc -lm libgcc.a
 | 
			
		||||
 *
 | 
			
		||||
 * The problem with this is that if one helper function needed by foo.a has
 | 
			
		||||
 * already been copied into libc.so or libm.so, then nothing will be copied
 | 
			
		||||
 * into libfoo.so. Instead, a symbol import definition will be added to it
 | 
			
		||||
 * so libfoo.so can directly call the one in libc.so at runtime.
 | 
			
		||||
 *
 | 
			
		||||
 * When changing toolchains for 2.0, the set of helper functions copied to
 | 
			
		||||
 * libc.so changed, which resulted in some native shared libraries generated
 | 
			
		||||
 * with the NDK to fail to load properly.
 | 
			
		||||
 *
 | 
			
		||||
 * The NDK has been fixed after 1.6_r1 to use the correct link command, so
 | 
			
		||||
 * any native shared library generated with it should now be safe from that
 | 
			
		||||
 * problem. On the other hand, existing shared libraries distributed with
 | 
			
		||||
 * applications that were generated with a previous version of the NDK
 | 
			
		||||
 * still need all 1.5/1.6 helper functions in libc.so and libm.so
 | 
			
		||||
 *
 | 
			
		||||
 * After 3.2, the toolchain was updated again, adding __aeabi_f2uiz to the
 | 
			
		||||
 * list of requirements. Technically, this is due to mis-linked NDK libraries
 | 
			
		||||
 * but it is easier to add a single function here than asking several app
 | 
			
		||||
 * developers to fix their build.
 | 
			
		||||
 *
 | 
			
		||||
 * Final note: some of the functions below should really be in libm.so to
 | 
			
		||||
 *             completely reflect the state of 1.5/1.6 system images. However,
 | 
			
		||||
 *             since libm.so depends on libc.so, it's easier to put all of
 | 
			
		||||
 *             these in libc.so instead, since the dynamic linker will always
 | 
			
		||||
 *             search in libc.so before libm.so for dependencies.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void* __bionic_libgcc_compat_symbols[] = {
 | 
			
		||||
    &__adddf3,
 | 
			
		||||
    &__addsf3,
 | 
			
		||||
    &__aeabi_cdcmpeq,
 | 
			
		||||
    &__aeabi_cdcmple,
 | 
			
		||||
    &__aeabi_cdrcmple,
 | 
			
		||||
    &__aeabi_d2f,
 | 
			
		||||
    &__aeabi_d2iz,
 | 
			
		||||
    &__aeabi_dadd,
 | 
			
		||||
    &__aeabi_dcmpeq,
 | 
			
		||||
    &__aeabi_dcmpge,
 | 
			
		||||
    &__aeabi_dcmpgt,
 | 
			
		||||
    &__aeabi_dcmple,
 | 
			
		||||
    &__aeabi_dcmplt,
 | 
			
		||||
    &__aeabi_dcmpun,
 | 
			
		||||
    &__aeabi_ddiv,
 | 
			
		||||
    &__aeabi_dmul,
 | 
			
		||||
    &__aeabi_drsub,
 | 
			
		||||
    &__aeabi_dsub,
 | 
			
		||||
    &__aeabi_f2d,
 | 
			
		||||
    &__aeabi_f2iz,
 | 
			
		||||
    &__aeabi_f2uiz,
 | 
			
		||||
    &__aeabi_fadd,
 | 
			
		||||
    &__aeabi_fcmpun,
 | 
			
		||||
    &__aeabi_fdiv,
 | 
			
		||||
    &__aeabi_fmul,
 | 
			
		||||
    &__aeabi_frsub,
 | 
			
		||||
    &__aeabi_fsub,
 | 
			
		||||
    &__aeabi_i2d,
 | 
			
		||||
    &__aeabi_i2f,
 | 
			
		||||
    &__aeabi_idiv,
 | 
			
		||||
    &__aeabi_idivmod,
 | 
			
		||||
    &__aeabi_l2d,
 | 
			
		||||
    &__aeabi_l2f,
 | 
			
		||||
    &__aeabi_lasr,
 | 
			
		||||
    &__aeabi_ldivmod,
 | 
			
		||||
    &__aeabi_llsl,
 | 
			
		||||
    &__aeabi_llsr,
 | 
			
		||||
    &__aeabi_lmul,
 | 
			
		||||
    &__aeabi_ui2d,
 | 
			
		||||
    &__aeabi_ui2f,
 | 
			
		||||
    &__aeabi_uidiv,
 | 
			
		||||
    &__aeabi_uidivmod,
 | 
			
		||||
    &__aeabi_ul2d,
 | 
			
		||||
    &__aeabi_ul2f,
 | 
			
		||||
    &__aeabi_uldivmod,
 | 
			
		||||
    &__aeabi_unwind_cpp_pr0,
 | 
			
		||||
    &__aeabi_unwind_cpp_pr1,
 | 
			
		||||
    &__cmpdf2,
 | 
			
		||||
    &__divdf3,
 | 
			
		||||
    &__divsf3,
 | 
			
		||||
    &__eqdf2,
 | 
			
		||||
    &__extendsfdf2,
 | 
			
		||||
    &__fixdfsi,
 | 
			
		||||
    &__fixsfsi,
 | 
			
		||||
    &__floatdidf,
 | 
			
		||||
    &__floatdisf,
 | 
			
		||||
    &__floatsidf,
 | 
			
		||||
    &__floatsisf,
 | 
			
		||||
    &__floatundidf,
 | 
			
		||||
    &__floatundisf,
 | 
			
		||||
    &__floatunsidf,
 | 
			
		||||
    &__floatunsisf,
 | 
			
		||||
    &__gedf2,
 | 
			
		||||
    &__gtdf2,
 | 
			
		||||
    &__ledf2,
 | 
			
		||||
    &__ltdf2,
 | 
			
		||||
    &__muldf3,
 | 
			
		||||
    &__muldi3,
 | 
			
		||||
    &__mulsf3,
 | 
			
		||||
    &__nedf2,
 | 
			
		||||
    &__popcount_tab,
 | 
			
		||||
    &__popcountsi2,
 | 
			
		||||
    &__subdf3,
 | 
			
		||||
    &__subsf3,
 | 
			
		||||
    &__truncdfsf2,
 | 
			
		||||
    &__unorddf2,
 | 
			
		||||
    &__unordsf2,
 | 
			
		||||
};
 | 
			
		||||
#define   COMPAT_FUNCTIONS_LIST \
 | 
			
		||||
    XX(__adddf3)             \
 | 
			
		||||
    XX(__addsf3)             \
 | 
			
		||||
    XX(__aeabi_cdcmpeq)      \
 | 
			
		||||
    XX(__aeabi_cdcmple)      \
 | 
			
		||||
    XX(__aeabi_cdrcmple)     \
 | 
			
		||||
    XX(__aeabi_d2f)          \
 | 
			
		||||
    XX(__aeabi_d2iz)         \
 | 
			
		||||
    XX(__aeabi_dadd)         \
 | 
			
		||||
    XX(__aeabi_dcmpeq)       \
 | 
			
		||||
    XX(__aeabi_dcmpge)       \
 | 
			
		||||
    XX(__aeabi_dcmpgt)       \
 | 
			
		||||
    XX(__aeabi_dcmple)       \
 | 
			
		||||
    XX(__aeabi_dcmplt)       \
 | 
			
		||||
    XX(__aeabi_dcmpun)       \
 | 
			
		||||
    XX(__aeabi_ddiv)         \
 | 
			
		||||
    XX(__aeabi_dmul)         \
 | 
			
		||||
    XX(__aeabi_drsub)        \
 | 
			
		||||
    XX(__aeabi_dsub)         \
 | 
			
		||||
    XX(__aeabi_f2d)          \
 | 
			
		||||
    XX(__aeabi_f2iz)         \
 | 
			
		||||
    XX(__aeabi_f2uiz)        \
 | 
			
		||||
    XX(__aeabi_fadd)         \
 | 
			
		||||
    XX(__aeabi_fcmpun)       \
 | 
			
		||||
    XX(__aeabi_fdiv)         \
 | 
			
		||||
    XX(__aeabi_fmul)         \
 | 
			
		||||
    XX(__aeabi_frsub)        \
 | 
			
		||||
    XX(__aeabi_fsub)         \
 | 
			
		||||
    XX(__aeabi_i2d)          \
 | 
			
		||||
    XX(__aeabi_i2f)          \
 | 
			
		||||
    XX(__aeabi_l2d)          \
 | 
			
		||||
    XX(__aeabi_l2f)          \
 | 
			
		||||
    XX(__aeabi_lmul)         \
 | 
			
		||||
    XX(__aeabi_llsl)         \
 | 
			
		||||
    XX(__aeabi_llsr)         \
 | 
			
		||||
    XX(__aeabi_ui2d)         \
 | 
			
		||||
    XX(__aeabi_ui2f)         \
 | 
			
		||||
    XX(__aeabi_ul2d)         \
 | 
			
		||||
    XX(__aeabi_ul2f)         \
 | 
			
		||||
    XX(__cmpdf2)             \
 | 
			
		||||
    XX(__divdf3)             \
 | 
			
		||||
    XX(__divsf3)             \
 | 
			
		||||
    XX(__eqdf2)             \
 | 
			
		||||
    XX(__extendsfdf2)        \
 | 
			
		||||
    XX(__fixdfsi)            \
 | 
			
		||||
    XX(__fixsfsi)            \
 | 
			
		||||
    XX(__floatdidf)          \
 | 
			
		||||
    XX(__floatdisf)          \
 | 
			
		||||
    XX(__floatsidf)          \
 | 
			
		||||
    XX(__floatsisf)          \
 | 
			
		||||
    XX(__floatundidf)        \
 | 
			
		||||
    XX(__floatundisf)        \
 | 
			
		||||
    XX(__floatunsidf)        \
 | 
			
		||||
    XX(__floatunsisf)        \
 | 
			
		||||
    XX(__gedf2)              \
 | 
			
		||||
    XX(__gtdf2)              \
 | 
			
		||||
    XX(__ledf2)              \
 | 
			
		||||
    XX(__ltdf2)              \
 | 
			
		||||
    XX(__muldf3)             \
 | 
			
		||||
    XX(__muldi3)             \
 | 
			
		||||
    XX(__mulsf3)             \
 | 
			
		||||
    XX(__nedf2)              \
 | 
			
		||||
    XX(__subdf3)             \
 | 
			
		||||
    XX(__subsf3)             \
 | 
			
		||||
    XX(__truncdfsf2)         \
 | 
			
		||||
    XX(__unorddf2)           \
 | 
			
		||||
    XX(__unordsf2)           \
 | 
			
		||||
 | 
			
		||||
#define  XX(f)    extern void f(void);
 | 
			
		||||
COMPAT_FUNCTIONS_LIST
 | 
			
		||||
#undef XX
 | 
			
		||||
 | 
			
		||||
void  __bionic_libgcc_compat_hooks(void)
 | 
			
		||||
{
 | 
			
		||||
#define XX(f)    f();
 | 
			
		||||
COMPAT_FUNCTIONS_LIST
 | 
			
		||||
#undef XX
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,97 +27,46 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 * 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, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
        /* make sure we have at least 8+4 bytes, this simplify things below
 | 
			
		||||
         * and avoid some overhead for small blocks
 | 
			
		||||
         */
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
/*
 | 
			
		||||
 * Neon optimization
 | 
			
		||||
 * Comparing 32 bytes at a time
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__ARM_NEON__) && defined(NEON_UNALIGNED_ACCESS)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         3f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop compares 32 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Start subtracting the values and merge results */
 | 
			
		||||
        vsub.i8     q0, q2
 | 
			
		||||
        vsub.i8     q1, q3
 | 
			
		||||
        vorr        q2, q0, q1
 | 
			
		||||
        vorr        d4, d5
 | 
			
		||||
        vmov        r3, ip, d4
 | 
			
		||||
        /* Check if there are any differences among the 32 bytes */
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         1b
 | 
			
		||||
        b           3f
 | 
			
		||||
2:
 | 
			
		||||
        /* Check if the difference was in the first or last 16 bytes */
 | 
			
		||||
        sub         r0, #32
 | 
			
		||||
        vorr        d0, d1
 | 
			
		||||
        sub         r1, #32
 | 
			
		||||
        vmov        r3, ip, d0
 | 
			
		||||
        orrs        r3, ip
 | 
			
		||||
        /* if the first 16 bytes are equal, we only have to rewind 16 bytes */
 | 
			
		||||
        ittt        eq
 | 
			
		||||
        subeq       r2, #16
 | 
			
		||||
        addeq       r0, #16
 | 
			
		||||
        addeq       r1, #16
 | 
			
		||||
 | 
			
		||||
3:      /* fix-up the remaining count */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        cmp        r2, #(8+4)
 | 
			
		||||
        bmi        10f
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        .save {r4, lr}
 | 
			
		||||
        /* save registers */
 | 
			
		||||
        stmfd       sp!, {r4, lr}
 | 
			
		||||
        .cfi_def_cfa_offset 8
 | 
			
		||||
        .cfi_rel_offset r4, 0
 | 
			
		||||
        .cfi_rel_offset lr, 4
 | 
			
		||||
        
 | 
			
		||||
        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
 | 
			
		||||
         */
 | 
			
		||||
@@ -153,9 +102,9 @@ ENTRY(memcmp)
 | 
			
		||||
        ldr         ip, [r1]
 | 
			
		||||
        subs        r2, r2, #(32 + 4)
 | 
			
		||||
        bmi         1f
 | 
			
		||||
 | 
			
		||||
0:      pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        
 | 
			
		||||
0:      PLD         (r4, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
        ldr         lr, [r1, #4]!
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
@@ -180,14 +129,14 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        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
 | 
			
		||||
@@ -221,28 +170,19 @@ ENTRY(memcmp)
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memcmp)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
        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
 | 
			
		||||
@@ -252,8 +192,8 @@ ENTRY(memcmp)
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
 | 
			
		||||
6:      pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r4, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
6:      PLD         (r1, #64)
 | 
			
		||||
        PLD         (r4, #64)
 | 
			
		||||
        mov         ip, lr, lsr #16
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        ldr         r0, [r4], #4
 | 
			
		||||
@@ -340,4 +280,3 @@ ENTRY(memcmp)
 | 
			
		||||
        mov         r2, #4
 | 
			
		||||
		ldmfd		sp!, {r5, r6, r7}
 | 
			
		||||
        b           8b
 | 
			
		||||
END(memcmp)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										232
									
								
								libc/arch-arm/bionic/memcmp16.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								libc/arch-arm/bionic/memcmp16.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,232 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Optimized memcmp16() for ARM9.
 | 
			
		||||
 * This would not be optimal on XScale or ARM11, where more prefetching
 | 
			
		||||
 * and use of PLD will be needed.
 | 
			
		||||
 * The 2 major optimzations here are
 | 
			
		||||
 * (1) The main loop compares 16 bytes at a time
 | 
			
		||||
 * (2) The loads are scheduled in a way they won't stall
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcmp16)
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
 | 
			
		||||
        /* take of the case where length is nul or the buffers are the same */
 | 
			
		||||
        cmp         r0, r1
 | 
			
		||||
        cmpne       r2, #0
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        bxeq        lr
 | 
			
		||||
 | 
			
		||||
        /* since r0 hold the result, move the first source
 | 
			
		||||
         * pointer somewhere else
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
 | 
			
		||||
         /* make sure we have at least 12 words, this simplify things below
 | 
			
		||||
          * and avoid some overhead for small blocks
 | 
			
		||||
          */
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #12
 | 
			
		||||
        bpl         0f
 | 
			
		||||
 | 
			
		||||
        /* small blocks (less then 12 words) */
 | 
			
		||||
        PLD         (r0, #32)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
1:      ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bxne        lr        
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         1b
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        .save {r4, lr}
 | 
			
		||||
        /* save registers */
 | 
			
		||||
0:      stmfd       sp!, {r4, lr}
 | 
			
		||||
        
 | 
			
		||||
        /* align first pointer to word boundary */
 | 
			
		||||
        tst         r3, #2
 | 
			
		||||
        beq         0f
 | 
			
		||||
        
 | 
			
		||||
        ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        sub         r2, r2, #1
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        ldmnefd     sp!, {r4, lr}
 | 
			
		||||
        bxne        lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
0:      /* here the first pointer is aligned, and we have at least 3 words
 | 
			
		||||
         * to process.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* see if the pointers are congruent */
 | 
			
		||||
        eor         r0, r3, r1
 | 
			
		||||
        ands        r0, r0, #2
 | 
			
		||||
        bne         5f
 | 
			
		||||
 | 
			
		||||
        /* congruent case, 16 half-words per iteration
 | 
			
		||||
         * We need to make sure there are at least 16+2 words left
 | 
			
		||||
         * because we effectively read ahead one long word, and we could
 | 
			
		||||
         * read past the buffer (and segfault) if we're not careful.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        ldr         ip, [r1]
 | 
			
		||||
        subs        r2, r2, #(16 + 2)
 | 
			
		||||
        bmi         1f
 | 
			
		||||
        
 | 
			
		||||
0:
 | 
			
		||||
        PLD         (r3, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        ldr         r0, [r3], #4
 | 
			
		||||
        ldr         lr, [r1, #4]!
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f        
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         0b
 | 
			
		||||
 | 
			
		||||
        /* do we have at least 2 words left? */
 | 
			
		||||
1:      adds        r2, r2, #(16 - 2 + 2)
 | 
			
		||||
        bmi         4f
 | 
			
		||||
        
 | 
			
		||||
        /* finish off 2 words at a time */
 | 
			
		||||
3:      ldr         r0, [r3], #4
 | 
			
		||||
        ldr         ip, [r1], #4
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #2
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
4:      adds        r2, r2, #2
 | 
			
		||||
        bne         8f
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        mov         r0, #0
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
2:      /* the last 2 words are different, restart them */
 | 
			
		||||
        ldrh        r0, [r3, #-4]
 | 
			
		||||
        ldrh        ip, [r1, #-4]
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        ldreqh      r0, [r3, #-2]
 | 
			
		||||
        ldreqh      ip, [r1, #-2]
 | 
			
		||||
        subeqs      r0, r0, ip
 | 
			
		||||
        /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
        /* process the last few words */
 | 
			
		||||
8:      ldrh        r0, [r3], #2
 | 
			
		||||
        ldrh        ip, [r1], #2
 | 
			
		||||
        subs        r0, r0, ip
 | 
			
		||||
        bne         9f
 | 
			
		||||
        subs        r2, r2, #1
 | 
			
		||||
        bne         8b
 | 
			
		||||
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
5:      /*************** non-congruent case ***************/
 | 
			
		||||
 | 
			
		||||
        /* align the unaligned pointer */
 | 
			
		||||
        bic         r1, r1, #3
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        sub         r2, r2, #8
 | 
			
		||||
 | 
			
		||||
6:
 | 
			
		||||
        PLD         (r3, #64)
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        mov         ip, lr, lsr #16
 | 
			
		||||
        ldr         lr, [r1], #4
 | 
			
		||||
        ldr         r0, [r3], #4
 | 
			
		||||
        orr         ip, ip, lr, lsl #16
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r3], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        /* are we done? */
 | 
			
		||||
        adds        r2, r2, #8
 | 
			
		||||
        moveq       r0, #0
 | 
			
		||||
        beq         9b
 | 
			
		||||
        /* finish off the remaining bytes */
 | 
			
		||||
        b           8b
 | 
			
		||||
 | 
			
		||||
7:      /* fix up the 2 pointers and fallthrough... */
 | 
			
		||||
        sub         r1, r1, #2
 | 
			
		||||
        b           2b
 | 
			
		||||
END(__memcmp16)
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__ARM_NEON__) && !defined(ARCH_ARM_USE_NON_NEON_MEMCPY)
 | 
			
		||||
 | 
			
		||||
@@ -37,35 +37,28 @@
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
/* a prefetch distance of 2 cache-lines */
 | 
			
		||||
#define CACHE_LINE_SIZE     32
 | 
			
		||||
#define PREFETCH_DISTANCE   (CACHE_LINE_SIZE*2)
 | 
			
		||||
#else
 | 
			
		||||
/* a prefetch distance of 4 cache-lines works best experimentally */
 | 
			
		||||
#define CACHE_LINE_SIZE     64
 | 
			
		||||
#define PREFETCH_DISTANCE   (CACHE_LINE_SIZE*4)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
        .save       {r0, lr}
 | 
			
		||||
        /* start preloading as early as possible */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*0)]
 | 
			
		||||
        stmfd       sp!, {r0, lr}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*1)]
 | 
			
		||||
 | 
			
		||||
/* If Neon supports unaligned access then remove the align code,
 | 
			
		||||
 * unless a size limit has been specified.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NEON_UNALIGNED_ACCESS
 | 
			
		||||
        /* do we have at least 16-bytes to copy (needed for alignment below) */
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to cache-line for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         2f
 | 
			
		||||
        beq         0f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
@@ -86,9 +79,10 @@ ENTRY(memcpy)
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
 | 
			
		||||
0:      /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE*1)]
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        /* make sure we have at least 32 bytes to copy */
 | 
			
		||||
@@ -114,22 +108,23 @@ ENTRY(memcpy)
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need. */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
        /* 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]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        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]!
 | 
			
		||||
        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 */
 | 
			
		||||
@@ -138,9 +133,9 @@ ENTRY(memcpy)
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d0 - d3},  [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0, :128]!
 | 
			
		||||
        vst1.8      {d0 - d3},  [r0, :128]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
#endif
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
@@ -150,6 +145,7 @@ ENTRY(memcpy)
 | 
			
		||||
        // 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
 | 
			
		||||
@@ -168,164 +164,6 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
 | 
			
		||||
#else   /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
 | 
			
		||||
        // Check so divider is at least 16 bytes, needed for alignment code.
 | 
			
		||||
        cmp         r2, #16
 | 
			
		||||
        blo         5f
 | 
			
		||||
 | 
			
		||||
#ifdef NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
#if NEON_MEMCPY_ALIGNMENT_DIVIDER >= 16
 | 
			
		||||
        cmp         r2, #NEON_MEMCPY_ALIGNMENT_DIVIDER
 | 
			
		||||
        blo         3f
 | 
			
		||||
#endif
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         11f
 | 
			
		||||
 | 
			
		||||
        /* align destination to 16 bytes for the write-buffer */
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0xF
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        /* copy up to 15-bytes (count in r3) */
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
        movs        ip, r3, lsl #31
 | 
			
		||||
        ldrmib      lr, [r1], #1
 | 
			
		||||
        strmib      lr, [r0], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
        movs        ip, r3, lsl #29
 | 
			
		||||
        bge         1f
 | 
			
		||||
        // copies 4 bytes, destination 32-bits aligned
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0, :32]!
 | 
			
		||||
1:      bcc         2f
 | 
			
		||||
        // copies 8 bytes, destination 64-bits aligned
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0, :64]!
 | 
			
		||||
2:
 | 
			
		||||
        /* preload immediately the next cache line, which we may need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
3:
 | 
			
		||||
#endif
 | 
			
		||||
        /* make sure we have at least 64 bytes to copy */
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        blo         2f
 | 
			
		||||
 | 
			
		||||
        /* preload all the cache lines we need */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
 | 
			
		||||
1:      /* The main loop copies 64 bytes at a time */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        vld1.8      {d4 - d7}, [r1]!
 | 
			
		||||
#ifdef  HAVE_32_BYTE_CACHE_LINE
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#else
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
#endif
 | 
			
		||||
        subs        r2, r2, #64
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d4 - d7}, [r0]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
 | 
			
		||||
        add         r2, r2, #64
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        blo         4f
 | 
			
		||||
 | 
			
		||||
3:      /* 32 bytes at a time. These cache lines were already preloaded */
 | 
			
		||||
        vld1.8      {d0 - d3}, [r1]!
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        bhs         3b
 | 
			
		||||
 | 
			
		||||
4:      /* less than 32 left */
 | 
			
		||||
        add         r2, r2, #32
 | 
			
		||||
        tst         r2, #0x10
 | 
			
		||||
        beq         5f
 | 
			
		||||
        // copies 16 bytes, 128-bits aligned
 | 
			
		||||
        vld1.8      {d0, d1}, [r1]!
 | 
			
		||||
        vst1.8      {d0, d1}, [r0]!
 | 
			
		||||
5:      /* copy up to 15-bytes (count in r2) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vld1.8      {d0}, [r1]!
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vld1.32     {d0[0]}, [r1]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      ip, [r1], #1
 | 
			
		||||
        ldrcsb      lr, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      ip, [r0], #1
 | 
			
		||||
        strcsb      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
#endif  /* NEON_UNALIGNED_ACCESS */
 | 
			
		||||
11:
 | 
			
		||||
        /* Simple arm-only copy loop to handle aligned copy operations */
 | 
			
		||||
        stmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 2)]
 | 
			
		||||
 | 
			
		||||
        /* Check alignment */
 | 
			
		||||
        rsb         r3, r1, #0
 | 
			
		||||
        ands        r3, #3
 | 
			
		||||
        beq         2f
 | 
			
		||||
 | 
			
		||||
        /* align source to 32 bits. We need to insert 2 instructions between
 | 
			
		||||
         * a ldr[b|h] and str[b|h] because byte and half-word instructions
 | 
			
		||||
         * stall 2 cycles.
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r5, [r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r5, [r0], #1
 | 
			
		||||
2:
 | 
			
		||||
        subs        r2, #32
 | 
			
		||||
        blt         5f
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 3)]
 | 
			
		||||
3:      /* Main copy loop, copying 32 bytes at a time */
 | 
			
		||||
        pld         [r1, #(CACHE_LINE_SIZE * 4)]
 | 
			
		||||
        ldmia       r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        stmia       r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
 | 
			
		||||
        bge         3b
 | 
			
		||||
5:      /* Handle any remaining bytes */
 | 
			
		||||
        adds        r2, #32
 | 
			
		||||
        beq         6f
 | 
			
		||||
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r3, r4, r5, r6}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r7, r8}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r3, r4, r5, r6}
 | 
			
		||||
        stmmiia     r0!, {r7, r8}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
6:
 | 
			
		||||
        ldmfd       sp!, {r4, r5, r6, r7, r8}
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -352,9 +190,9 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        // preload the destination because we'll align it to a cache line
 | 
			
		||||
        // with small writes. Also start the source "pump".
 | 
			
		||||
        pld         [r0, #0]
 | 
			
		||||
        pld         [r1, #0]
 | 
			
		||||
        pld         [r1, #32]
 | 
			
		||||
        PLD         (r0, #0)
 | 
			
		||||
        PLD         (r1, #0)
 | 
			
		||||
        PLD         (r1, #32)
 | 
			
		||||
 | 
			
		||||
		/* it simplifies things to take care of len<4 early */
 | 
			
		||||
		cmp			r2, #4
 | 
			
		||||
@@ -442,7 +280,7 @@ cached_aligned32:
 | 
			
		||||
        add         r12, r12, #64
 | 
			
		||||
 | 
			
		||||
1:      ldmia       r1!, { r4-r11 }
 | 
			
		||||
        pld         [r12, #64]
 | 
			
		||||
        PLD         (r12, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
 | 
			
		||||
@@ -563,7 +401,7 @@ loop16:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #16
 | 
			
		||||
@@ -590,7 +428,7 @@ loop8:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #24
 | 
			
		||||
@@ -617,7 +455,7 @@ loop24:
 | 
			
		||||
        ldr         r12, [r1], #4
 | 
			
		||||
1:      mov         r4, r12
 | 
			
		||||
		ldmia		r1!, {   r5,r6,r7,  r8,r9,r10,r11}
 | 
			
		||||
        pld         [r1, #64]
 | 
			
		||||
        PLD         (r1, #64)
 | 
			
		||||
		subs		r2, r2, #32
 | 
			
		||||
        ldrhs       r12, [r1], #4
 | 
			
		||||
		orr			r3, r3, r4,		lsl #8
 | 
			
		||||
 
 | 
			
		||||
@@ -1,614 +0,0 @@
 | 
			
		||||
/* Copyright (c) 2013, Linaro Limited
 | 
			
		||||
   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.
 | 
			
		||||
 | 
			
		||||
      * Neither the name of Linaro Limited 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 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
 | 
			
		||||
   HOLDER 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 memcpy routine is optimised for Cortex-A15 cores and takes advantage
 | 
			
		||||
   of VFP or NEON when built with the appropriate flags.
 | 
			
		||||
 | 
			
		||||
   Assumptions:
 | 
			
		||||
 | 
			
		||||
    ARMv6 (ARMv7-a if using Neon)
 | 
			
		||||
    ARM state
 | 
			
		||||
    Unaligned accesses
 | 
			
		||||
    LDRD/STRD support unaligned word accesses
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
	.syntax unified
 | 
			
		||||
	/* This implementation requires ARM state.  */
 | 
			
		||||
	.arm
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_NEON__
 | 
			
		||||
 | 
			
		||||
	.fpu	neon
 | 
			
		||||
	.arch	armv7-a
 | 
			
		||||
# define FRAME_SIZE	4
 | 
			
		||||
# define USE_VFP
 | 
			
		||||
# define USE_NEON
 | 
			
		||||
 | 
			
		||||
#elif !defined (__SOFTFP__)
 | 
			
		||||
 | 
			
		||||
	.arch	armv6
 | 
			
		||||
	.fpu	vfpv2
 | 
			
		||||
# define FRAME_SIZE	32
 | 
			
		||||
# define USE_VFP
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	.arch	armv6
 | 
			
		||||
# define FRAME_SIZE    32
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Old versions of GAS incorrectly implement the NEON align semantics.  */
 | 
			
		||||
#ifdef BROKEN_ASM_NEON_ALIGN
 | 
			
		||||
#define ALIGN(addr, align) addr,:align
 | 
			
		||||
#else
 | 
			
		||||
#define ALIGN(addr, align) addr:align
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PC_OFFSET	8	/* PC pipeline compensation.  */
 | 
			
		||||
#define INSN_SIZE	4
 | 
			
		||||
 | 
			
		||||
/* Call parameters.  */
 | 
			
		||||
#define dstin	r0
 | 
			
		||||
#define src	r1
 | 
			
		||||
#define count	r2
 | 
			
		||||
 | 
			
		||||
/* Locals.  */
 | 
			
		||||
#define tmp1	r3
 | 
			
		||||
#define dst	ip
 | 
			
		||||
#define tmp2	r10
 | 
			
		||||
 | 
			
		||||
#ifndef USE_NEON
 | 
			
		||||
/* For bulk copies using GP registers.  */
 | 
			
		||||
#define	A_l	r2		/* Call-clobbered.  */
 | 
			
		||||
#define	A_h	r3		/* Call-clobbered.  */
 | 
			
		||||
#define	B_l	r4
 | 
			
		||||
#define	B_h	r5
 | 
			
		||||
#define	C_l	r6
 | 
			
		||||
#define	C_h	r7
 | 
			
		||||
#define	D_l	r8
 | 
			
		||||
#define	D_h	r9
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Number of lines ahead to pre-fetch data.  If you change this the code
 | 
			
		||||
   below will need adjustment to compensate.  */
 | 
			
		||||
 | 
			
		||||
#define prefetch_lines	5
 | 
			
		||||
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	.macro	cpy_line_vfp vreg, base
 | 
			
		||||
	vstr	\vreg, [dst, #\base]
 | 
			
		||||
	vldr	\vreg, [src, #\base]
 | 
			
		||||
	vstr	d0, [dst, #\base + 8]
 | 
			
		||||
	vldr	d0, [src, #\base + 8]
 | 
			
		||||
	vstr	d1, [dst, #\base + 16]
 | 
			
		||||
	vldr	d1, [src, #\base + 16]
 | 
			
		||||
	vstr	d2, [dst, #\base + 24]
 | 
			
		||||
	vldr	d2, [src, #\base + 24]
 | 
			
		||||
	vstr	\vreg, [dst, #\base + 32]
 | 
			
		||||
	vldr	\vreg, [src, #\base + prefetch_lines * 64 - 32]
 | 
			
		||||
	vstr	d0, [dst, #\base + 40]
 | 
			
		||||
	vldr	d0, [src, #\base + 40]
 | 
			
		||||
	vstr	d1, [dst, #\base + 48]
 | 
			
		||||
	vldr	d1, [src, #\base + 48]
 | 
			
		||||
	vstr	d2, [dst, #\base + 56]
 | 
			
		||||
	vldr	d2, [src, #\base + 56]
 | 
			
		||||
	.endm
 | 
			
		||||
 | 
			
		||||
	.macro	cpy_tail_vfp vreg, base
 | 
			
		||||
	vstr	\vreg, [dst, #\base]
 | 
			
		||||
	vldr	\vreg, [src, #\base]
 | 
			
		||||
	vstr	d0, [dst, #\base + 8]
 | 
			
		||||
	vldr	d0, [src, #\base + 8]
 | 
			
		||||
	vstr	d1, [dst, #\base + 16]
 | 
			
		||||
	vldr	d1, [src, #\base + 16]
 | 
			
		||||
	vstr	d2, [dst, #\base + 24]
 | 
			
		||||
	vldr	d2, [src, #\base + 24]
 | 
			
		||||
	vstr	\vreg, [dst, #\base + 32]
 | 
			
		||||
	vstr	d0, [dst, #\base + 40]
 | 
			
		||||
	vldr	d0, [src, #\base + 40]
 | 
			
		||||
	vstr	d1, [dst, #\base + 48]
 | 
			
		||||
	vldr	d1, [src, #\base + 48]
 | 
			
		||||
	vstr	d2, [dst, #\base + 56]
 | 
			
		||||
	vldr	d2, [src, #\base + 56]
 | 
			
		||||
	.endm
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	.p2align 6
 | 
			
		||||
ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
	mov	dst, dstin	/* Preserve dstin, we need to return it.  */
 | 
			
		||||
	cmp	count, #64
 | 
			
		||||
	bge	.Lcpy_not_short
 | 
			
		||||
	/* Deal with small copies quickly by dropping straight into the
 | 
			
		||||
	   exit block.  */
 | 
			
		||||
 | 
			
		||||
.Ltail63unaligned:
 | 
			
		||||
#ifdef USE_NEON
 | 
			
		||||
	and	tmp1, count, #0x38
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 14 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 12 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 10 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 8 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 6 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 4 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
	vld1.8	{d0}, [src]!	/* 2 words to go.  */
 | 
			
		||||
	vst1.8	{d0}, [dst]!
 | 
			
		||||
 | 
			
		||||
	tst	count, #4
 | 
			
		||||
	ldrne	tmp1, [src], #4
 | 
			
		||||
	strne	tmp1, [dst], #4
 | 
			
		||||
#else
 | 
			
		||||
	/* Copy up to 15 full words of data.  May not be aligned.  */
 | 
			
		||||
	/* Cannot use VFP for unaligned data.  */
 | 
			
		||||
	and	tmp1, count, #0x3c
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
 | 
			
		||||
	/* Jump directly into the sequence below at the correct offset.  */
 | 
			
		||||
	add	pc, pc, tmp1, lsl #1
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-60]	/* 15 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-60]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-56]
 | 
			
		||||
	ldr	tmp1, [src, #-52]
 | 
			
		||||
	str	tmp1, [dst, #-52]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-48]
 | 
			
		||||
	ldr	tmp1, [src, #-44]
 | 
			
		||||
	str	tmp1, [dst, #-44]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-40]
 | 
			
		||||
	ldr	tmp1, [src, #-36]
 | 
			
		||||
	str	tmp1, [dst, #-36]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-32]
 | 
			
		||||
	ldr	tmp1, [src, #-28]
 | 
			
		||||
	str	tmp1, [dst, #-28]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-24]
 | 
			
		||||
	ldr	tmp1, [src, #-20]
 | 
			
		||||
	str	tmp1, [dst, #-20]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-16]
 | 
			
		||||
	ldr	tmp1, [src, #-12]
 | 
			
		||||
	str	tmp1, [dst, #-12]
 | 
			
		||||
 | 
			
		||||
	ldr	tmp1, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	str	tmp1, [dst, #-8]
 | 
			
		||||
	ldr	tmp1, [src, #-4]
 | 
			
		||||
	str	tmp1, [dst, #-4]
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	lsls	count, count, #31
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	src, [src]		/* Src is dead, use as a scratch.  */
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	src, [dst]
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lcpy_not_short:
 | 
			
		||||
	/* At least 64 bytes to copy, but don't know the alignment yet.  */
 | 
			
		||||
	str	tmp2, [sp, #-FRAME_SIZE]!
 | 
			
		||||
	and	tmp2, src, #7
 | 
			
		||||
	and	tmp1, dst, #7
 | 
			
		||||
	cmp	tmp1, tmp2
 | 
			
		||||
	bne	.Lcpy_notaligned
 | 
			
		||||
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	/* Magic dust alert!  Force VFP on Cortex-A9.  Experiments show
 | 
			
		||||
	   that the FP pipeline is much better at streaming loads and
 | 
			
		||||
	   stores.  This is outside the critical loop.  */
 | 
			
		||||
	vmov.f32	s0, s0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* SRC and DST have the same mutual 32-bit alignment, but we may
 | 
			
		||||
	   still need to pre-copy some bytes to get to natural alignment.
 | 
			
		||||
	   We bring DST into full 64-bit alignment.  */
 | 
			
		||||
	lsls	tmp2, dst, #29
 | 
			
		||||
	beq	1f
 | 
			
		||||
	rsbs	tmp2, tmp2, #0
 | 
			
		||||
	sub	count, count, tmp2, lsr #29
 | 
			
		||||
	ldrmi	tmp1, [src], #4
 | 
			
		||||
	strmi	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #2
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	tmp2, [src], #1
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	tmp2, [dst], #1
 | 
			
		||||
 | 
			
		||||
1:
 | 
			
		||||
	subs	tmp2, count, #64	/* Use tmp2 for count.  */
 | 
			
		||||
	blt	.Ltail63aligned
 | 
			
		||||
 | 
			
		||||
	cmp	tmp2, #512
 | 
			
		||||
	bge	.Lcpy_body_long
 | 
			
		||||
 | 
			
		||||
.Lcpy_body_medium:			/* Count in tmp2.  */
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
1:
 | 
			
		||||
	vldr	d0, [src, #0]
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	vldr	d1, [src, #8]
 | 
			
		||||
	vstr	d0, [dst, #0]
 | 
			
		||||
	vldr	d0, [src, #16]
 | 
			
		||||
	vstr	d1, [dst, #8]
 | 
			
		||||
	vldr	d1, [src, #24]
 | 
			
		||||
	vstr	d0, [dst, #16]
 | 
			
		||||
	vldr	d0, [src, #32]
 | 
			
		||||
	vstr	d1, [dst, #24]
 | 
			
		||||
	vldr	d1, [src, #40]
 | 
			
		||||
	vstr	d0, [dst, #32]
 | 
			
		||||
	vldr	d0, [src, #48]
 | 
			
		||||
	vstr	d1, [dst, #40]
 | 
			
		||||
	vldr	d1, [src, #56]
 | 
			
		||||
	vstr	d0, [dst, #48]
 | 
			
		||||
	add	src, src, #64
 | 
			
		||||
	vstr	d1, [dst, #56]
 | 
			
		||||
	add	dst, dst, #64
 | 
			
		||||
	bge	1b
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	beq	.Ldone
 | 
			
		||||
 | 
			
		||||
.Ltail63aligned:			/* Count in tmp2.  */
 | 
			
		||||
	and	tmp1, tmp2, #0x38
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
 | 
			
		||||
	vldr	d0, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-56]
 | 
			
		||||
	vldr	d0, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-48]
 | 
			
		||||
	vldr	d0, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-40]
 | 
			
		||||
	vldr	d0, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-32]
 | 
			
		||||
	vldr	d0, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-24]
 | 
			
		||||
	vldr	d0, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-16]
 | 
			
		||||
	vldr	d0, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	vstr	d0, [dst, #-8]
 | 
			
		||||
#else
 | 
			
		||||
	sub	src, src, #8
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
1:
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #16]
 | 
			
		||||
	strd	A_l, A_h, [dst, #16]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #24]
 | 
			
		||||
	strd	A_l, A_h, [dst, #24]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #32]
 | 
			
		||||
	strd	A_l, A_h, [dst, #32]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #40]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #48]
 | 
			
		||||
	strd	A_l, A_h, [dst, #48]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #56]
 | 
			
		||||
	strd	A_l, A_h, [dst, #56]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #64]!
 | 
			
		||||
	strd	A_l, A_h, [dst, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	bge	1b
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	bne	1f
 | 
			
		||||
	ldr	tmp2,[sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
1:
 | 
			
		||||
	add	src, src, #8
 | 
			
		||||
	add	dst, dst, #8
 | 
			
		||||
 | 
			
		||||
.Ltail63aligned:			/* Count in tmp2.  */
 | 
			
		||||
	/* Copy up to 7 d-words of data.  Similar to Ltail63unaligned, but
 | 
			
		||||
	   we know that the src and dest are 32-bit aligned so we can use
 | 
			
		||||
	   LDRD/STRD to improve efficiency.  */
 | 
			
		||||
	/* TMP2 is now negative, but we don't care about that.  The bottom
 | 
			
		||||
	   six bits still tell us how many bytes are left to copy.  */
 | 
			
		||||
 | 
			
		||||
	and	tmp1, tmp2, #0x38
 | 
			
		||||
	add	dst, dst, tmp1
 | 
			
		||||
	add	src, src, tmp1
 | 
			
		||||
	rsb	tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
 | 
			
		||||
	add	pc, pc, tmp1
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-56]	/* 14 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-56]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-48]	/* 12 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-48]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-40]	/* 10 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-32]	/* 8 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-32]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-24]	/* 6 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-24]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-16]	/* 4 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-16]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #-8]	/* 2 words to go.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #-8]
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
	tst	tmp2, #4
 | 
			
		||||
	ldrne	tmp1, [src], #4
 | 
			
		||||
	strne	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #31		/* Count (tmp2) now dead. */
 | 
			
		||||
	ldrhcs	tmp1, [src], #2
 | 
			
		||||
	ldrbne	tmp2, [src]
 | 
			
		||||
	strhcs	tmp1, [dst], #2
 | 
			
		||||
	strbne	tmp2, [dst]
 | 
			
		||||
 | 
			
		||||
.Ldone:
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
 | 
			
		||||
.Lcpy_body_long:			/* Count in tmp2.  */
 | 
			
		||||
 | 
			
		||||
	/* Long copy.  We know that there's at least (prefetch_lines * 64)
 | 
			
		||||
	   bytes to go.  */
 | 
			
		||||
#ifdef USE_VFP
 | 
			
		||||
	/* Don't use PLD.  Instead, read some data in advance of the current
 | 
			
		||||
	   copy position into a register.  This should act like a PLD
 | 
			
		||||
	   operation but we won't have to repeat the transfer.  */
 | 
			
		||||
 | 
			
		||||
	vldr	d3, [src, #0]
 | 
			
		||||
	vldr	d4, [src, #64]
 | 
			
		||||
	vldr	d5, [src, #128]
 | 
			
		||||
	vldr	d6, [src, #192]
 | 
			
		||||
	vldr	d7, [src, #256]
 | 
			
		||||
 | 
			
		||||
	vldr	d0, [src, #8]
 | 
			
		||||
	vldr	d1, [src, #16]
 | 
			
		||||
	vldr	d2, [src, #24]
 | 
			
		||||
	add	src, src, #32
 | 
			
		||||
 | 
			
		||||
	subs	tmp2, tmp2, #prefetch_lines * 64 * 2
 | 
			
		||||
	blt	2f
 | 
			
		||||
1:
 | 
			
		||||
	cpy_line_vfp	d3, 0
 | 
			
		||||
	cpy_line_vfp	d4, 64
 | 
			
		||||
	cpy_line_vfp	d5, 128
 | 
			
		||||
	add	dst, dst, #3 * 64
 | 
			
		||||
	add	src, src, #3 * 64
 | 
			
		||||
	cpy_line_vfp	d6, 0
 | 
			
		||||
	cpy_line_vfp	d7, 64
 | 
			
		||||
	add	dst, dst, #2 * 64
 | 
			
		||||
	add	src, src, #2 * 64
 | 
			
		||||
	subs	tmp2, tmp2, #prefetch_lines * 64
 | 
			
		||||
	bge	1b
 | 
			
		||||
 | 
			
		||||
2:
 | 
			
		||||
	cpy_tail_vfp	d3, 0
 | 
			
		||||
	cpy_tail_vfp	d4, 64
 | 
			
		||||
	cpy_tail_vfp	d5, 128
 | 
			
		||||
	add	src, src, #3 * 64
 | 
			
		||||
	add	dst, dst, #3 * 64
 | 
			
		||||
	cpy_tail_vfp	d6, 0
 | 
			
		||||
	vstr	d7, [dst, #64]
 | 
			
		||||
	vldr	d7, [src, #64]
 | 
			
		||||
	vstr	d0, [dst, #64 + 8]
 | 
			
		||||
	vldr	d0, [src, #64 + 8]
 | 
			
		||||
	vstr	d1, [dst, #64 + 16]
 | 
			
		||||
	vldr	d1, [src, #64 + 16]
 | 
			
		||||
	vstr	d2, [dst, #64 + 24]
 | 
			
		||||
	vldr	d2, [src, #64 + 24]
 | 
			
		||||
	vstr	d7, [dst, #64 + 32]
 | 
			
		||||
	add	src, src, #96
 | 
			
		||||
	vstr	d0, [dst, #64 + 40]
 | 
			
		||||
	vstr	d1, [dst, #64 + 48]
 | 
			
		||||
	vstr	d2, [dst, #64 + 56]
 | 
			
		||||
	add	dst, dst, #128
 | 
			
		||||
	add	tmp2, tmp2, #prefetch_lines * 64
 | 
			
		||||
	b	.Lcpy_body_medium
 | 
			
		||||
#else
 | 
			
		||||
	/* Long copy.  Use an SMS style loop to maximize the I/O
 | 
			
		||||
	   bandwidth of the core.  We don't have enough spare registers
 | 
			
		||||
	   to synthesise prefetching, so use PLD operations.  */
 | 
			
		||||
	/* Pre-bias src and dst.  */
 | 
			
		||||
	sub	src, src, #8
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
	pld	[src, #8]
 | 
			
		||||
	pld	[src, #72]
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
	pld	[src, #136]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [sp, #8]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [sp, #16]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [sp, #24]
 | 
			
		||||
	pld	[src, #200]
 | 
			
		||||
	ldrd	D_l, D_h, [src, #32]!
 | 
			
		||||
	b	1f
 | 
			
		||||
	.p2align	6
 | 
			
		||||
2:
 | 
			
		||||
	pld	[src, #232]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #40]
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #48]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #56]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]!
 | 
			
		||||
	ldrd	D_l, D_h, [src, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
1:
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldrd	A_l, A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [dst, #16]
 | 
			
		||||
	ldrd	B_l, B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [dst, #24]
 | 
			
		||||
	ldrd	C_l, C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [dst, #32]
 | 
			
		||||
	ldrd	D_l, D_h, [src, #32]
 | 
			
		||||
	bcs	2b
 | 
			
		||||
	/* Save the remaining bytes and restore the callee-saved regs.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	add	src, src, #40
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [sp, #8]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [sp, #16]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]
 | 
			
		||||
	ldrd	D_l, D_h, [sp, #24]
 | 
			
		||||
	add	dst, dst, #72
 | 
			
		||||
	tst	tmp2, #0x3f
 | 
			
		||||
	bne	.Ltail63aligned
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bx	lr
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
.Lcpy_notaligned:
 | 
			
		||||
	pld	[src]
 | 
			
		||||
	pld	[src, #64]
 | 
			
		||||
	/* There's at least 64 bytes to copy, but there is no mutual
 | 
			
		||||
	   alignment.  */
 | 
			
		||||
	/* Bring DST to 64-bit alignment.  */
 | 
			
		||||
	lsls	tmp2, dst, #29
 | 
			
		||||
	pld	[src, #(2 * 64)]
 | 
			
		||||
	beq	1f
 | 
			
		||||
	rsbs	tmp2, tmp2, #0
 | 
			
		||||
	sub	count, count, tmp2, lsr #29
 | 
			
		||||
	ldrmi	tmp1, [src], #4
 | 
			
		||||
	strmi	tmp1, [dst], #4
 | 
			
		||||
	lsls	tmp2, tmp2, #2
 | 
			
		||||
	ldrbne	tmp1, [src], #1
 | 
			
		||||
	ldrhcs	tmp2, [src], #2
 | 
			
		||||
	strbne	tmp1, [dst], #1
 | 
			
		||||
	strhcs	tmp2, [dst], #2
 | 
			
		||||
1:
 | 
			
		||||
	pld	[src, #(3 * 64)]
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	ldrmi	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bmi	.Ltail63unaligned
 | 
			
		||||
	pld	[src, #(4 * 64)]
 | 
			
		||||
 | 
			
		||||
#ifdef USE_NEON
 | 
			
		||||
	vld1.8	{d0-d3}, [src]!
 | 
			
		||||
	vld1.8	{d4-d7}, [src]!
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	bmi	2f
 | 
			
		||||
1:
 | 
			
		||||
	pld	[src, #(4 * 64)]
 | 
			
		||||
	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vld1.8	{d0-d3}, [src]!
 | 
			
		||||
	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vld1.8	{d4-d7}, [src]!
 | 
			
		||||
	subs	count, count, #64
 | 
			
		||||
	bpl	1b
 | 
			
		||||
2:
 | 
			
		||||
	vst1.8	{d0-d3}, [ALIGN (dst, 64)]!
 | 
			
		||||
	vst1.8	{d4-d7}, [ALIGN (dst, 64)]!
 | 
			
		||||
	ands	count, count, #0x3f
 | 
			
		||||
#else
 | 
			
		||||
	/* Use an SMS style loop to maximize the I/O bandwidth.  */
 | 
			
		||||
	sub	src, src, #4
 | 
			
		||||
	sub	dst, dst, #8
 | 
			
		||||
	subs	tmp2, count, #64	/* Use tmp2 for count.  */
 | 
			
		||||
	ldr	A_l, [src, #4]
 | 
			
		||||
	ldr	A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [sp, #8]
 | 
			
		||||
	ldr	B_l, [src, #12]
 | 
			
		||||
	ldr	B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [sp, #16]
 | 
			
		||||
	ldr	C_l, [src, #20]
 | 
			
		||||
	ldr	C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [sp, #24]
 | 
			
		||||
	ldr	D_l, [src, #28]
 | 
			
		||||
	ldr	D_h, [src, #32]!
 | 
			
		||||
	b	1f
 | 
			
		||||
	.p2align	6
 | 
			
		||||
2:
 | 
			
		||||
	pld	[src, #(5 * 64) - (32 - 4)]
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	ldr	A_l, [src, #36]
 | 
			
		||||
	ldr	A_h, [src, #40]
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldr	B_l, [src, #44]
 | 
			
		||||
	ldr	B_h, [src, #48]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldr	C_l, [src, #52]
 | 
			
		||||
	ldr	C_h, [src, #56]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]!
 | 
			
		||||
	ldr	D_l, [src, #60]
 | 
			
		||||
	ldr	D_h, [src, #64]!
 | 
			
		||||
	subs	tmp2, tmp2, #64
 | 
			
		||||
1:
 | 
			
		||||
	strd	A_l, A_h, [dst, #8]
 | 
			
		||||
	ldr	A_l, [src, #4]
 | 
			
		||||
	ldr	A_h, [src, #8]
 | 
			
		||||
	strd	B_l, B_h, [dst, #16]
 | 
			
		||||
	ldr	B_l, [src, #12]
 | 
			
		||||
	ldr	B_h, [src, #16]
 | 
			
		||||
	strd	C_l, C_h, [dst, #24]
 | 
			
		||||
	ldr	C_l, [src, #20]
 | 
			
		||||
	ldr	C_h, [src, #24]
 | 
			
		||||
	strd	D_l, D_h, [dst, #32]
 | 
			
		||||
	ldr	D_l, [src, #28]
 | 
			
		||||
	ldr	D_h, [src, #32]
 | 
			
		||||
	bcs	2b
 | 
			
		||||
 | 
			
		||||
	/* Save the remaining bytes and restore the callee-saved regs.  */
 | 
			
		||||
	strd	A_l, A_h, [dst, #40]
 | 
			
		||||
	add	src, src, #36
 | 
			
		||||
	strd	B_l, B_h, [dst, #48]
 | 
			
		||||
	ldrd	B_l, B_h, [sp, #8]
 | 
			
		||||
	strd	C_l, C_h, [dst, #56]
 | 
			
		||||
	ldrd	C_l, C_h, [sp, #16]
 | 
			
		||||
	strd	D_l, D_h, [dst, #64]
 | 
			
		||||
	ldrd	D_l, D_h, [sp, #24]
 | 
			
		||||
	add	dst, dst, #72
 | 
			
		||||
	ands	count, tmp2, #0x3f
 | 
			
		||||
#endif
 | 
			
		||||
	ldr	tmp2, [sp], #FRAME_SIZE
 | 
			
		||||
	bne	.Ltail63unaligned
 | 
			
		||||
	bx	lr
 | 
			
		||||
END(memcpy)
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
@@ -51,16 +51,12 @@
 | 
			
		||||
ENTRY(setjmp)
 | 
			
		||||
	/* Block all signals and retrieve the old signal mask */
 | 
			
		||||
	stmfd	sp!, {r0, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 8
 | 
			
		||||
	.cfi_rel_offset r0, 0
 | 
			
		||||
	.cfi_rel_offset r14, 4
 | 
			
		||||
	mov	r0, #0x00000000
 | 
			
		||||
 | 
			
		||||
	bl	PIC_SYM(sigblock, PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(sigblock), PLT)
 | 
			
		||||
	mov	r1, r0
 | 
			
		||||
 | 
			
		||||
	ldmfd	sp!, {r0, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 0
 | 
			
		||||
 | 
			
		||||
	/* Store signal mask */
 | 
			
		||||
	str	r1, [r0, #(_JB_SIGMASK * 4)]
 | 
			
		||||
@@ -100,20 +96,13 @@ ENTRY(longjmp)
 | 
			
		||||
 | 
			
		||||
	/* Set 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
 | 
			
		||||
 | 
			
		||||
	mov	r0, r2
 | 
			
		||||
	bl	PIC_SYM(sigsetmask, PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(sigsetmask), PLT)
 | 
			
		||||
 | 
			
		||||
	add	sp, sp, #4	/* unalign the stack */
 | 
			
		||||
	.cfi_adjust_cfa_offset -4
 | 
			
		||||
	ldmfd	sp!, {r0, r1, r14}
 | 
			
		||||
	.cfi_def_cfa_offset 0
 | 
			
		||||
	ldmfd	sp!, {r0, r1, r14} 
 | 
			
		||||
 | 
			
		||||
#ifdef __ARM_HAVE_VFP
 | 
			
		||||
	/* Restore floating-point registers */
 | 
			
		||||
@@ -147,7 +136,7 @@ ENTRY(longjmp)
 | 
			
		||||
 | 
			
		||||
	/* validation failed, die die die. */
 | 
			
		||||
botch:
 | 
			
		||||
	bl	PIC_SYM(longjmperror, PLT)
 | 
			
		||||
	bl	PIC_SYM(abort, PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
 | 
			
		||||
	bl	PIC_SYM(_C_LABEL(abort), PLT)
 | 
			
		||||
	b	. - 8		/* Cannot get here */
 | 
			
		||||
END(longjmp)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@
 | 
			
		||||
 | 
			
		||||
#define _ALIGN_TEXT .align 0
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
#include <machine/setjmp.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -50,8 +50,8 @@
 | 
			
		||||
 | 
			
		||||
ENTRY(sigsetjmp)
 | 
			
		||||
	teq	r1, #0
 | 
			
		||||
	beq	PIC_SYM(_setjmp, PLT)
 | 
			
		||||
	b	PIC_SYM(setjmp, PLT)
 | 
			
		||||
	beq	PIC_SYM(_C_LABEL(_setjmp), PLT)
 | 
			
		||||
	b	PIC_SYM(_C_LABEL(setjmp), PLT)
 | 
			
		||||
END(sigsetjmp)
 | 
			
		||||
 | 
			
		||||
.L_setjmp_magic:
 | 
			
		||||
@@ -61,6 +61,6 @@ ENTRY(siglongjmp)
 | 
			
		||||
	ldr	r2, .L_setjmp_magic
 | 
			
		||||
	ldr	r3, [r0]
 | 
			
		||||
	teq	r2, r3
 | 
			
		||||
	beq	PIC_SYM(_longjmp, PLT)
 | 
			
		||||
	b	PIC_SYM(longjmp, PLT)
 | 
			
		||||
	beq	PIC_SYM(_C_LABEL(_longjmp), PLT)
 | 
			
		||||
	b	PIC_SYM(_C_LABEL(longjmp), PLT)
 | 
			
		||||
END(siglongjmp)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
#include <machine/asm.h>
 | 
			
		||||
 | 
			
		||||
	.text
 | 
			
		||||
 | 
			
		||||
@@ -52,8 +52,8 @@
 | 
			
		||||
#define magic2(REG) REG, lsl #7
 | 
			
		||||
 | 
			
		||||
ENTRY(strcmp)
 | 
			
		||||
	pld	[r0, #0]
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	PLD(r0, #0)
 | 
			
		||||
	PLD(r1, #0)
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
	tst	r2, #3
 | 
			
		||||
 | 
			
		||||
@@ -88,8 +88,8 @@ ENTRY(strcmp)
 | 
			
		||||
	orr	r4, r4, r4, lsl #16
 | 
			
		||||
	.p2align	2
 | 
			
		||||
4:
 | 
			
		||||
	pld	[r0, #8]
 | 
			
		||||
	pld	[r1, #8]
 | 
			
		||||
	PLD(r0, #8)
 | 
			
		||||
	PLD(r1, #8)
 | 
			
		||||
	sub	r2, ip, magic1(r4)
 | 
			
		||||
	cmp	ip, r3
 | 
			
		||||
	itttt	eq
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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/tgkill.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								libc/arch-arm/bionic/tgkill.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_tgkill
 | 
			
		||||
#define __NR_tgkill  268
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENTRY(tgkill)
 | 
			
		||||
    stmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    ldr     r7, =__NR_tgkill
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4-r7, ip, lr}
 | 
			
		||||
    movs    r0, r0
 | 
			
		||||
    bxpl    lr
 | 
			
		||||
    b       __set_syscall_errno
 | 
			
		||||
END(tgkill)
 | 
			
		||||
							
								
								
									
										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,11 +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 \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
@@ -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,188 +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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      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
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
        mov         r12, r1
 | 
			
		||||
        mov         lr, r1
 | 
			
		||||
        mov         r4, r1
 | 
			
		||||
        mov         r5, r1
 | 
			
		||||
        mov         r6, r1
 | 
			
		||||
        mov         r7, r1
 | 
			
		||||
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0x1C
 | 
			
		||||
        beq         3f
 | 
			
		||||
        cmp         r3, r2
 | 
			
		||||
        andhi       r3, r2, #0x1C
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
3:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        mov         r3, r1
 | 
			
		||||
        bmi         2f
 | 
			
		||||
1:      subs        r2, r2, #32
 | 
			
		||||
        stmia       r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
 | 
			
		||||
        bhs         1b
 | 
			
		||||
2:      add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_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,11 +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 \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
@@ -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,207 +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.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        .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,14 +0,0 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    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,410 +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.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
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 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
 | 
			
		||||
        /* 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
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
.Lcongruent_aligned32:
 | 
			
		||||
        /*
 | 
			
		||||
         * 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
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
        /********************************************************************/
 | 
			
		||||
 | 
			
		||||
.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
 | 
			
		||||
        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         .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)
 | 
			
		||||
        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}
 | 
			
		||||
 | 
			
		||||
.Lcopy_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)
 | 
			
		||||
 | 
			
		||||
        // 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,133 +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.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
        mov         r12, r1
 | 
			
		||||
        mov         lr, r1
 | 
			
		||||
        mov         r4, r1
 | 
			
		||||
        mov         r5, r1
 | 
			
		||||
        mov         r6, r1
 | 
			
		||||
        mov         r7, r1
 | 
			
		||||
 | 
			
		||||
        rsb         r3, r0, #0
 | 
			
		||||
        ands        r3, r3, #0x1C
 | 
			
		||||
        beq         3f
 | 
			
		||||
        cmp         r3, r2
 | 
			
		||||
        andhi       r3, r2, #0x1C
 | 
			
		||||
        sub         r2, r2, r3
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
3:
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        mov         r3, r1
 | 
			
		||||
        bmi         2f
 | 
			
		||||
1:      subs        r2, r2, #32
 | 
			
		||||
        stmia       r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
 | 
			
		||||
        bhs         1b
 | 
			
		||||
2:      add         r2, r2, #32
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .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)
 | 
			
		||||
@@ -1,133 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2010 The Android Open Source Project
 | 
			
		||||
 * Copyright (c) 2008 ARM Ltd
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. The name of the company may not be used to endorse or promote
 | 
			
		||||
 *    products derived from this software without specific prior written
 | 
			
		||||
 *    permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | 
			
		||||
 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 | 
			
		||||
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
			
		||||
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
@@ -1,136 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
 | 
			
		||||
size_t strlen(const char *s)
 | 
			
		||||
{
 | 
			
		||||
    __builtin_prefetch(s);
 | 
			
		||||
    __builtin_prefetch(s+32);
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        const char      *b;
 | 
			
		||||
        const uint32_t  *w;
 | 
			
		||||
        uintptr_t       i;
 | 
			
		||||
    } u;
 | 
			
		||||
 | 
			
		||||
    // these are some scratch variables for the asm code below
 | 
			
		||||
    uint32_t v, t;
 | 
			
		||||
 | 
			
		||||
    // initialize the string length to zero
 | 
			
		||||
    size_t l = 0;
 | 
			
		||||
 | 
			
		||||
    // align the pointer to a 32-bit word boundary
 | 
			
		||||
    u.b = s;
 | 
			
		||||
    while (u.i & 0x3)  {
 | 
			
		||||
        if (__builtin_expect(*u.b++ == 0, 0)) {
 | 
			
		||||
            goto done;
 | 
			
		||||
        }
 | 
			
		||||
        l++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // loop for each word, testing if it contains a zero byte
 | 
			
		||||
    // if so, exit the loop and update the length.
 | 
			
		||||
    // We need to process 32 bytes per loop to schedule PLD properly
 | 
			
		||||
    // and achieve the maximum bus speed.
 | 
			
		||||
    asm(
 | 
			
		||||
        "ldr     %[v], [%[s]], #4           \n"
 | 
			
		||||
        "sub     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "0:                                 \n"
 | 
			
		||||
        "pld     [%[s], #64]                \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
#if !defined(__OPTIMIZE_SIZE__)
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
        "bne     1f                         \n"
 | 
			
		||||
        "sub     %[t], %[v], %[mask], lsr #7\n"
 | 
			
		||||
        "and     %[t], %[t], %[mask]        \n"
 | 
			
		||||
        "bics    %[t], %[t], %[v]           \n"
 | 
			
		||||
        "it      eq                         \n"
 | 
			
		||||
        "ldreq   %[v], [%[s]], #4           \n"
 | 
			
		||||
#endif
 | 
			
		||||
        "beq     0b                         \n"
 | 
			
		||||
        "1:                                 \n"
 | 
			
		||||
        "add     %[l], %[l], %[s]           \n"
 | 
			
		||||
        "tst     %[v], #0xFF                \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF00              \n"
 | 
			
		||||
        "beq     2f                         \n"
 | 
			
		||||
        "add     %[l], %[l], #1             \n"
 | 
			
		||||
        "tst     %[v], #0xFF0000            \n"
 | 
			
		||||
        "it      ne                         \n"
 | 
			
		||||
        "addne   %[l], %[l], #1             \n"
 | 
			
		||||
        "2:                                 \n"
 | 
			
		||||
        : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
 | 
			
		||||
        : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
 | 
			
		||||
        : "cc"
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
    return l;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/generic/bionic/memcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/memset.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcmp.S \
 | 
			
		||||
    arch-arm/generic/bionic/strcpy.S \
 | 
			
		||||
    arch-arm/generic/bionic/strlen.c \
 | 
			
		||||
    bionic/memmove.c \
 | 
			
		||||
    bionic/__strcat_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
							
								
								
									
										89
									
								
								libc/arch-arm/include/endian.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								libc/arch-arm/include/endian.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
/*	$OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM_ENDIAN_H_
 | 
			
		||||
#define _ARM_ENDIAN_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * REV and REV16 weren't available on ARM5 or ARM4.
 | 
			
		||||
 * We don't include <machine/cpu-features.h> because it pollutes the
 | 
			
		||||
 * namespace with macros like PLD.
 | 
			
		||||
 */
 | 
			
		||||
#if !defined __ARM_ARCH_5__ && !defined __ARM_ARCH_5T__ && \
 | 
			
		||||
    !defined __ARM_ARCH_5TE__ && !defined __ARM_ARCH_5TEJ__ && \
 | 
			
		||||
    !defined __ARM_ARCH_4T__ && !defined __ARM_ARCH_4__
 | 
			
		||||
 | 
			
		||||
/* According to RealView Assembler User's Guide, REV and REV16 are available
 | 
			
		||||
 * in Thumb code and 16-bit instructions when used in Thumb-2 code.
 | 
			
		||||
 *
 | 
			
		||||
 * REV Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * REV16 Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * The +l constraint takes care of this without constraining us in ARM mode.
 | 
			
		||||
 */
 | 
			
		||||
#define __swap16md(x) ({                                        \
 | 
			
		||||
    register u_int16_t _x = (x);                                \
 | 
			
		||||
    __asm volatile ("rev16 %0, %0" : "+l" (_x));                \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap32md(x) ({                                        \
 | 
			
		||||
    register u_int32_t _x = (x);                                \
 | 
			
		||||
    __asm volatile ("rev %0, %0" : "+l" (_x));                  \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap64md(x) ({                                        \
 | 
			
		||||
    u_int64_t _swap64md_x = (x);                                \
 | 
			
		||||
    (u_int64_t) __swap32md(_swap64md_x >> 32) |                 \
 | 
			
		||||
        (u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/* Tell sys/endian.h we have MD variants of the swap macros.  */
 | 
			
		||||
#define MD_SWAP
 | 
			
		||||
 | 
			
		||||
#endif  /* __ARM_ARCH__ */
 | 
			
		||||
#endif  /* __GNUC__ */
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define _BYTE_ORDER _BIG_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
#define _BYTE_ORDER _LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
#define __STRICT_ALIGNMENT
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/endian.h>
 | 
			
		||||
 | 
			
		||||
#endif  /* !_ARM_ENDIAN_H_ */
 | 
			
		||||
							
								
								
									
										125
									
								
								libc/arch-arm/include/machine/_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								libc/arch-arm/include/machine/_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
/*	$OpenBSD: _types.h,v 1.3 2006/02/14 18:12:58 miod Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 1990, 1993
 | 
			
		||||
 *	The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of the University nor the names of its contributors
 | 
			
		||||
 *    may be used to endorse or promote products derived from this software
 | 
			
		||||
 *    without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 *	@(#)types.h	8.3 (Berkeley) 1/5/94
 | 
			
		||||
 *	@(#)ansi.h	8.2 (Berkeley) 1/4/94
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM__TYPES_H_
 | 
			
		||||
#define _ARM__TYPES_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if !defined(__ARM_EABI__)
 | 
			
		||||
/* the kernel defines size_t as unsigned int, but g++ wants it to be unsigned long */
 | 
			
		||||
#define _SIZE_T
 | 
			
		||||
#define _SSIZE_T
 | 
			
		||||
#define _PTRDIFF_T
 | 
			
		||||
typedef unsigned long  size_t;
 | 
			
		||||
typedef long           ssize_t;
 | 
			
		||||
typedef long           ptrdiff_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.1 Exact-width integer types */
 | 
			
		||||
typedef	__signed char		__int8_t;
 | 
			
		||||
typedef	unsigned char		__uint8_t;
 | 
			
		||||
typedef	short			__int16_t;
 | 
			
		||||
typedef	unsigned short		__uint16_t;
 | 
			
		||||
typedef	int			__int32_t;
 | 
			
		||||
typedef	unsigned int		__uint32_t;
 | 
			
		||||
/* LONGLONG */
 | 
			
		||||
typedef	long long		__int64_t;
 | 
			
		||||
/* LONGLONG */
 | 
			
		||||
typedef	unsigned long long	__uint64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.2 Minimum-width integer types */
 | 
			
		||||
typedef	__int8_t		__int_least8_t;
 | 
			
		||||
typedef	__uint8_t		__uint_least8_t;
 | 
			
		||||
typedef	__int16_t		__int_least16_t;
 | 
			
		||||
typedef	__uint16_t		__uint_least16_t;
 | 
			
		||||
typedef	__int32_t		__int_least32_t;
 | 
			
		||||
typedef	__uint32_t		__uint_least32_t;
 | 
			
		||||
typedef	__int64_t		__int_least64_t;
 | 
			
		||||
typedef	__uint64_t		__uint_least64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.3 Fastest minimum-width integer types */
 | 
			
		||||
typedef	__int32_t		__int_fast8_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast8_t;
 | 
			
		||||
typedef	__int32_t		__int_fast16_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast16_t;
 | 
			
		||||
typedef	__int32_t		__int_fast32_t;
 | 
			
		||||
typedef	__uint32_t		__uint_fast32_t;
 | 
			
		||||
typedef	__int64_t		__int_fast64_t;
 | 
			
		||||
typedef	__uint64_t		__uint_fast64_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.4 Integer types capable of holding object pointers */
 | 
			
		||||
typedef	int 			__intptr_t;
 | 
			
		||||
typedef	unsigned int 		__uintptr_t;
 | 
			
		||||
 | 
			
		||||
/* 7.18.1.5 Greatest-width integer types */
 | 
			
		||||
typedef	__int64_t		__intmax_t;
 | 
			
		||||
typedef	__uint64_t		__uintmax_t;
 | 
			
		||||
 | 
			
		||||
/* Register size */
 | 
			
		||||
typedef __int32_t		__register_t;
 | 
			
		||||
 | 
			
		||||
/* VM system types */
 | 
			
		||||
typedef unsigned long		__vaddr_t;
 | 
			
		||||
typedef unsigned long		__paddr_t;
 | 
			
		||||
typedef unsigned long		__vsize_t;
 | 
			
		||||
typedef unsigned long		__psize_t;
 | 
			
		||||
 | 
			
		||||
/* Standard system types */
 | 
			
		||||
typedef int			__clock_t;
 | 
			
		||||
typedef int			__clockid_t;
 | 
			
		||||
typedef long			__ptrdiff_t;
 | 
			
		||||
typedef	int			__time_t;
 | 
			
		||||
typedef int			__timer_t;
 | 
			
		||||
#if defined(__GNUC__) && __GNUC__ >= 3
 | 
			
		||||
typedef	__builtin_va_list	__va_list;
 | 
			
		||||
#else
 | 
			
		||||
typedef	char *			__va_list;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Wide character support types */
 | 
			
		||||
#ifndef __cplusplus
 | 
			
		||||
typedef	int			__wchar_t;
 | 
			
		||||
#endif
 | 
			
		||||
typedef int			__wint_t;
 | 
			
		||||
typedef	int			__rune_t;
 | 
			
		||||
typedef	void *			__wctrans_t;
 | 
			
		||||
typedef	void *			__wctype_t;
 | 
			
		||||
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
#define _BYTE_ORDER _BIG_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
#define _BYTE_ORDER _LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif	/* _ARM__TYPES_H_ */
 | 
			
		||||
@@ -38,22 +38,107 @@
 | 
			
		||||
#ifndef _ARM32_ASM_H_
 | 
			
		||||
#define _ARM32_ASM_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
# define _C_LABEL(x)	x
 | 
			
		||||
#else
 | 
			
		||||
# ifdef __STDC__
 | 
			
		||||
#  define _C_LABEL(x)	_ ## x
 | 
			
		||||
# else
 | 
			
		||||
#  define _C_LABEL(x)	_/**/x
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
#define	_ASM_LABEL(x)	x
 | 
			
		||||
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
# define __CONCAT(x,y)	x ## y
 | 
			
		||||
# define __STRING(x)	#x
 | 
			
		||||
#else
 | 
			
		||||
# define __CONCAT(x,y)	x/**/y
 | 
			
		||||
# define __STRING(x)	"x"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef _ALIGN_TEXT
 | 
			
		||||
# define _ALIGN_TEXT .align 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_custom_entry
 | 
			
		||||
#undef __bionic_asm_custom_end
 | 
			
		||||
#define __bionic_asm_custom_entry(f) .fnstart
 | 
			
		||||
#define __bionic_asm_custom_end(f) .fnend
 | 
			
		||||
/*
 | 
			
		||||
 * gas/arm uses @ as a single comment character and thus cannot be used here
 | 
			
		||||
 * Instead it recognised the # instead of an @ symbols in .type directives
 | 
			
		||||
 * We define a couple of macros so that assembly code will not be dependant
 | 
			
		||||
 * on one or the other.
 | 
			
		||||
 */
 | 
			
		||||
#define _ASM_TYPE_FUNCTION	#function
 | 
			
		||||
#define _ASM_TYPE_OBJECT	#object
 | 
			
		||||
#define _ENTRY(x) \
 | 
			
		||||
	.text; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; x: .fnstart
 | 
			
		||||
 | 
			
		||||
#undef __bionic_asm_function_type
 | 
			
		||||
#define __bionic_asm_function_type #function
 | 
			
		||||
#define _ASM_SIZE(x)	.size x, .-x;
 | 
			
		||||
 | 
			
		||||
#if defined(__ELF__) && defined(PIC)
 | 
			
		||||
#define PIC_SYM(x,y) x ## ( ## y ## )
 | 
			
		||||
#define _END(x) \
 | 
			
		||||
	.fnend; \
 | 
			
		||||
	_ASM_SIZE(x)
 | 
			
		||||
 | 
			
		||||
#ifdef GPROF
 | 
			
		||||
# ifdef __ELF__
 | 
			
		||||
#  define _PROF_PROLOGUE	\
 | 
			
		||||
	mov ip, lr; bl __mcount
 | 
			
		||||
# else
 | 
			
		||||
#  define _PROF_PROLOGUE	\
 | 
			
		||||
	mov ip,lr; bl mcount
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
#define PIC_SYM(x,y) x
 | 
			
		||||
# define _PROF_PROLOGUE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	ENTRY(y)	_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
 | 
			
		||||
#define	ENTRY_NP(y)	_ENTRY(_C_LABEL(y))
 | 
			
		||||
#define	END(y)		_END(_C_LABEL(y))
 | 
			
		||||
#define	ASENTRY(y)	_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
 | 
			
		||||
#define	ASENTRY_NP(y)	_ENTRY(_ASM_LABEL(y))
 | 
			
		||||
#define	ASEND(y)	_END(_ASM_LABEL(y))
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define ENTRY_PRIVATE(y)  ENTRY(y); .hidden _C_LABEL(y)
 | 
			
		||||
#else
 | 
			
		||||
#define ENTRY_PRIVATE(y)  ENTRY(y)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	ASMSTR		.asciz
 | 
			
		||||
 | 
			
		||||
#if defined(__ELF__) && defined(PIC)
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
#define	PIC_SYM(x,y)	x ## ( ## y ## )
 | 
			
		||||
#else
 | 
			
		||||
#define	PIC_SYM(x,y)	x/**/(/**/y/**/)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define	PIC_SYM(x,y)	x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define RCSID(x)	.section ".ident"; .asciz x
 | 
			
		||||
#else
 | 
			
		||||
#define RCSID(x)	.text; .asciz x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ELF__
 | 
			
		||||
#define	WEAK_ALIAS(alias,sym)						\
 | 
			
		||||
	.weak alias;							\
 | 
			
		||||
	alias = sym
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __STDC__
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg ## ,30,0,0,0 ;					\
 | 
			
		||||
	.stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0
 | 
			
		||||
#elif defined(__ELF__)
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg,30,0,0,0 ;						\
 | 
			
		||||
	.stabs __STRING(sym),1,0,0,0
 | 
			
		||||
#else
 | 
			
		||||
#define	WARN_REFERENCES(sym,msg)					\
 | 
			
		||||
	.stabs msg,30,0,0,0 ;						\
 | 
			
		||||
	.stabs __STRING(_/**/sym),1,0,0,0
 | 
			
		||||
#endif /* __STDC__ */
 | 
			
		||||
 | 
			
		||||
#endif /* !_ARM_ASM_H_ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								libc/arch-arm/include/machine/cdefs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								libc/arch-arm/include/machine/cdefs.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
/*	$OpenBSD: cdefs.h,v 1.2 2005/11/24 20:46:44 deraadt Exp $	*/
 | 
			
		||||
 | 
			
		||||
#ifndef	_MACHINE_CDEFS_H_
 | 
			
		||||
#define	_MACHINE_CDEFS_H_
 | 
			
		||||
 | 
			
		||||
#if defined(lint)
 | 
			
		||||
#define __indr_reference(sym,alias)	__lint_equal__(sym,alias)
 | 
			
		||||
#define __warn_references(sym,msg)
 | 
			
		||||
#define __weak_alias(alias,sym)		__lint_equal__(sym,alias)
 | 
			
		||||
#elif defined(__GNUC__) && defined(__STDC__)
 | 
			
		||||
#define __weak_alias(alias,sym)					\
 | 
			
		||||
	__asm__(".weak " __STRING(alias) " ; " __STRING(alias)	\
 | 
			
		||||
	    " = " __STRING(sym));
 | 
			
		||||
#define	__warn_references(sym,msg)				\
 | 
			
		||||
	__asm__(".section .gnu.warning." __STRING(sym)		\
 | 
			
		||||
	    " ; .ascii \"" msg "\" ; .text");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* !_MACHINE_CDEFS_H_ */
 | 
			
		||||
@@ -34,29 +34,133 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This is done to abstract us from the various ARM Architecture
 | 
			
		||||
 * quirks and alphabet soup.
 | 
			
		||||
 *
 | 
			
		||||
 * IMPORTANT: We have no intention to support anything below an ARMv4T !
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* __ARM_ARCH__ is a number corresponding to the ARM revision
 | 
			
		||||
 * we're going to support. Our toolchain doesn't define __ARM_ARCH__
 | 
			
		||||
 * we're going to support
 | 
			
		||||
 *
 | 
			
		||||
 * it looks like our toolchain doesn't define __ARM_ARCH__
 | 
			
		||||
 * so try to guess it.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __ARM_ARCH__
 | 
			
		||||
 | 
			
		||||
#  if defined __ARM_ARCH_7__   || defined __ARM_ARCH_7A__ || \
 | 
			
		||||
        defined __ARM_ARCH_7R__  || defined __ARM_ARCH_7M__
 | 
			
		||||
      defined __ARM_ARCH_7R__  || defined __ARM_ARCH_7M__
 | 
			
		||||
 | 
			
		||||
#    define __ARM_ARCH__ 7
 | 
			
		||||
 | 
			
		||||
#  elif defined __ARM_ARCH_6__   || defined __ARM_ARCH_6J__ || \
 | 
			
		||||
        defined __ARM_ARCH_6K__  || defined __ARM_ARCH_6Z__ || \
 | 
			
		||||
        defined __ARM_ARCH_6KZ__ || defined __ARM_ARCH_6T2__
 | 
			
		||||
      defined __ARM_ARCH_6K__  || defined __ARM_ARCH_6Z__ || \
 | 
			
		||||
      defined __ARM_ARCH_6KZ__ || defined __ARM_ARCH_6T2__
 | 
			
		||||
#
 | 
			
		||||
#    define __ARM_ARCH__ 6
 | 
			
		||||
#
 | 
			
		||||
#  elif defined __ARM_ARCH_5__ || defined __ARM_ARCH_5T__ || \
 | 
			
		||||
        defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__
 | 
			
		||||
#
 | 
			
		||||
#    define __ARM_ARCH__ 5
 | 
			
		||||
#
 | 
			
		||||
#  elif defined __ARM_ARCH_4T__
 | 
			
		||||
#
 | 
			
		||||
#    define __ARM_ARCH__ 4
 | 
			
		||||
#
 | 
			
		||||
#  elif defined __ARM_ARCH_4__
 | 
			
		||||
#    error ARMv4 is not supported, please use ARMv4T at a minimum
 | 
			
		||||
#  else
 | 
			
		||||
#    error Unknown or unsupported ARM architecture
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* experimental feature used to check that our ARMv4 workarounds
 | 
			
		||||
 * work correctly without a real ARMv4 machine */
 | 
			
		||||
#ifdef BIONIC_EXPERIMENTAL_FORCE_ARMV4
 | 
			
		||||
#  undef  __ARM_ARCH__
 | 
			
		||||
#  define __ARM_ARCH__  4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_5TE if we have the ARMv5TE instructions */
 | 
			
		||||
#if __ARM_ARCH__ > 5
 | 
			
		||||
#  define  __ARM_HAVE_5TE  1
 | 
			
		||||
#elif __ARM_ARCH__ == 5
 | 
			
		||||
#  if defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__
 | 
			
		||||
#    define __ARM_HAVE_5TE  1
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* instructions introduced in ARMv5 */
 | 
			
		||||
#if __ARM_ARCH__ >= 5
 | 
			
		||||
#  define  __ARM_HAVE_BLX  1
 | 
			
		||||
#  define  __ARM_HAVE_CLZ  1
 | 
			
		||||
#  define  __ARM_HAVE_LDC2 1
 | 
			
		||||
#  define  __ARM_HAVE_MCR2 1
 | 
			
		||||
#  define  __ARM_HAVE_MRC2 1
 | 
			
		||||
#  define  __ARM_HAVE_STC2 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ARMv5TE introduces a few instructions */
 | 
			
		||||
#if __ARM_HAVE_5TE
 | 
			
		||||
#  define  __ARM_HAVE_PLD   1
 | 
			
		||||
#  define  __ARM_HAVE_MCRR  1
 | 
			
		||||
#  define  __ARM_HAVE_MRRC  1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_HALFWORD_MULTIPLY when half-word multiply instructions
 | 
			
		||||
 * this means variants of: smul, smulw, smla, smlaw, smlal
 | 
			
		||||
 */
 | 
			
		||||
#define  __ARM_HAVE_HALFWORD_MULTIPLY  1
 | 
			
		||||
#if __ARM_HAVE_5TE
 | 
			
		||||
#  define  __ARM_HAVE_HALFWORD_MULTIPLY  1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_PAIR_LOAD_STORE when 64-bit memory loads and stored
 | 
			
		||||
 * into/from a pair of 32-bit registers is supported throuhg 'ldrd' and 'strd'
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_HAVE_5TE
 | 
			
		||||
#  define  __ARM_HAVE_PAIR_LOAD_STORE 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_SATURATED_ARITHMETIC is you have the saturated integer
 | 
			
		||||
 * arithmetic instructions: qdd, qdadd, qsub, qdsub
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_HAVE_5TE
 | 
			
		||||
#  define  __ARM_HAVE_SATURATED_ARITHMETIC 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_PC_INTERWORK when a direct assignment to the
 | 
			
		||||
 * pc register will switch into thumb/ARM mode depending on bit 0
 | 
			
		||||
 * of the new instruction address. Before ARMv5, this was not the
 | 
			
		||||
 * case, and you have to write:
 | 
			
		||||
 *
 | 
			
		||||
 *     mov  r0, [<some address>]
 | 
			
		||||
 *     bx   r0
 | 
			
		||||
 *
 | 
			
		||||
 * instead of:
 | 
			
		||||
 *
 | 
			
		||||
 *     ldr  pc, [<some address>]
 | 
			
		||||
 *
 | 
			
		||||
 * note that this affects any instruction that explicitly changes the
 | 
			
		||||
 * value of the pc register, including ldm { ...,pc } or 'add pc, #offset'
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 5
 | 
			
		||||
#  define __ARM_HAVE_PC_INTERWORK
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_LDREX_STREX for ARMv6 and ARMv7 architecture to be
 | 
			
		||||
 * used in replacement of deprecated swp instruction
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 6
 | 
			
		||||
#  define __ARM_HAVE_LDREX_STREX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_DMB for ARMv7 architecture
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_ARCH__ >= 7
 | 
			
		||||
#  define __ARM_HAVE_DMB
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* define __ARM_HAVE_LDREXD for ARMv7 architecture
 | 
			
		||||
 * (also present in ARMv6K, but not implemented in ARMv7-M, neither of which
 | 
			
		||||
@@ -80,4 +184,18 @@
 | 
			
		||||
#  define __ARM_HAVE_NEON
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Assembly-only macros */
 | 
			
		||||
#ifdef __ASSEMBLY__
 | 
			
		||||
 | 
			
		||||
/* define a handy PLD(address) macro since the cache preload
 | 
			
		||||
 * is an optional opcode
 | 
			
		||||
 */
 | 
			
		||||
#if __ARM_HAVE_PLD
 | 
			
		||||
#  define  PLD(reg,offset)    pld    [reg, offset]
 | 
			
		||||
#else
 | 
			
		||||
#  define  PLD(reg,offset)    /* nothing */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* ! __ASSEMBLY__ */
 | 
			
		||||
 | 
			
		||||
#endif /* _ARM_MACHINE_CPU_FEATURES_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,138 +0,0 @@
 | 
			
		||||
/*	$NetBSD: elf_machdep.h,v 1.10 2012/08/05 04:12:46 matt Exp $	*/
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM_ELF_MACHDEP_H_
 | 
			
		||||
#define _ARM_ELF_MACHDEP_H_
 | 
			
		||||
 | 
			
		||||
#if defined(__ARMEB__)
 | 
			
		||||
#define ELF32_MACHDEP_ENDIANNESS	ELFDATA2MSB
 | 
			
		||||
#else
 | 
			
		||||
#define ELF32_MACHDEP_ENDIANNESS	ELFDATA2LSB
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ELF64_MACHDEP_ENDIANNESS	XXX	/* break compilation */
 | 
			
		||||
#define ELF64_MACHDEP_ID_CASES                                          \
 | 
			
		||||
		/* no 64-bit ELF machine types supported */
 | 
			
		||||
 | 
			
		||||
/* Processor specific flags for the ELF header e_flags field.  */
 | 
			
		||||
#define EF_ARM_RELEXEC		0x00000001
 | 
			
		||||
#define EF_ARM_HASENTRY		0x00000002
 | 
			
		||||
#define EF_ARM_INTERWORK	0x00000004 /* GNU binutils 000413 */
 | 
			
		||||
#define EF_ARM_SYMSARESORTED	0x00000004 /* ARM ELF A08 */
 | 
			
		||||
#define EF_ARM_APCS_26		0x00000008 /* GNU binutils 000413 */
 | 
			
		||||
#define EF_ARM_DYNSYMSUSESEGIDX	0x00000008 /* ARM ELF B01 */
 | 
			
		||||
#define EF_ARM_APCS_FLOAT	0x00000010 /* GNU binutils 000413 */
 | 
			
		||||
#define EF_ARM_MAPSYMSFIRST	0x00000010 /* ARM ELF B01 */
 | 
			
		||||
#define EF_ARM_PIC		0x00000020
 | 
			
		||||
#define EF_ARM_ALIGN8		0x00000040 /* 8-bit structure alignment.  */
 | 
			
		||||
#define EF_ARM_NEW_ABI		0x00000080
 | 
			
		||||
#define EF_ARM_OLD_ABI		0x00000100
 | 
			
		||||
#define EF_ARM_SOFT_FLOAT	0x00000200
 | 
			
		||||
#define EF_ARM_EABIMASK		0xff000000
 | 
			
		||||
#define	EF_ARM_EABI_VER1	0x01000000
 | 
			
		||||
#define	EF_ARM_EABI_VER2	0x02000000
 | 
			
		||||
#define	EF_ARM_EABI_VER3	0x03000000
 | 
			
		||||
#define	EF_ARM_EABI_VER4	0x04000000
 | 
			
		||||
#define	EF_ARM_EABI_VER5	0x05000000
 | 
			
		||||
 | 
			
		||||
#define	ELF32_MACHDEP_ID_CASES						\
 | 
			
		||||
		case EM_ARM:						\
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
#define	ELF32_MACHDEP_ID	EM_ARM
 | 
			
		||||
 | 
			
		||||
#define ARCH_ELFSIZE		32	/* MD native binary size */
 | 
			
		||||
 | 
			
		||||
/* Processor specific relocation types */
 | 
			
		||||
 | 
			
		||||
#define R_ARM_NONE		0
 | 
			
		||||
#define R_ARM_PC24		1
 | 
			
		||||
#define R_ARM_ABS32		2
 | 
			
		||||
#define R_ARM_REL32		3
 | 
			
		||||
#define R_ARM_PC13		4
 | 
			
		||||
#define R_ARM_ABS16		5
 | 
			
		||||
#define R_ARM_ABS12		6
 | 
			
		||||
#define R_ARM_THM_ABS5		7
 | 
			
		||||
#define R_ARM_ABS8		8
 | 
			
		||||
#define R_ARM_SBREL32		9
 | 
			
		||||
#define R_ARM_THM_PC22		10
 | 
			
		||||
#define R_ARM_THM_PC8		11
 | 
			
		||||
#define R_ARM_AMP_VCALL9	12
 | 
			
		||||
#define R_ARM_SWI24		13
 | 
			
		||||
#define R_ARM_THM_SWI8		14
 | 
			
		||||
#define R_ARM_XPC25		15
 | 
			
		||||
#define R_ARM_THM_XPC22		16
 | 
			
		||||
 | 
			
		||||
/* TLS relocations */
 | 
			
		||||
#define R_ARM_TLS_DTPMOD32	17	/* ID of module containing symbol */
 | 
			
		||||
#define R_ARM_TLS_DTPOFF32	18	/* Offset in TLS block */
 | 
			
		||||
#define R_ARM_TLS_TPOFF32	19	/* Offset in static TLS block */
 | 
			
		||||
 | 
			
		||||
/* 20-31 are reserved for ARM Linux. */
 | 
			
		||||
#define R_ARM_COPY		20
 | 
			
		||||
#define R_ARM_GLOB_DAT		21
 | 
			
		||||
#define	R_ARM_JUMP_SLOT		22
 | 
			
		||||
#define R_ARM_RELATIVE		23
 | 
			
		||||
#define	R_ARM_GOTOFF		24
 | 
			
		||||
#define R_ARM_GOTPC		25
 | 
			
		||||
#define R_ARM_GOT32		26
 | 
			
		||||
#define R_ARM_PLT32		27
 | 
			
		||||
 | 
			
		||||
#define R_ARM_ALU_PCREL_7_0	32
 | 
			
		||||
#define R_ARM_ALU_PCREL_15_8	33
 | 
			
		||||
#define R_ARM_ALU_PCREL_23_15	34
 | 
			
		||||
#define R_ARM_ALU_SBREL_11_0	35
 | 
			
		||||
#define R_ARM_ALU_SBREL_19_12	36
 | 
			
		||||
#define R_ARM_ALU_SBREL_27_20	37
 | 
			
		||||
 | 
			
		||||
/* 96-111 are reserved to G++. */
 | 
			
		||||
#define R_ARM_GNU_VTENTRY	100
 | 
			
		||||
#define R_ARM_GNU_VTINHERIT	101
 | 
			
		||||
#define R_ARM_THM_PC11		102
 | 
			
		||||
#define R_ARM_THM_PC9		103
 | 
			
		||||
 | 
			
		||||
/* More TLS relocations */
 | 
			
		||||
#define R_ARM_TLS_GD32		104	/* PC-rel 32 bit for global dynamic */
 | 
			
		||||
#define R_ARM_TLS_LDM32		105	/* PC-rel 32 bit for local dynamic */
 | 
			
		||||
#define R_ARM_TLS_LDO32		106	/* 32 bit offset relative to TLS */
 | 
			
		||||
#define R_ARM_TLS_IE32		107	/* PC-rel 32 bit for GOT entry of */
 | 
			
		||||
#define R_ARM_TLS_LE32		108
 | 
			
		||||
#define R_ARM_TLS_LDO12		109
 | 
			
		||||
#define R_ARM_TLS_LE12		110
 | 
			
		||||
#define R_ARM_TLS_IE12GP	111
 | 
			
		||||
 | 
			
		||||
/* 112-127 are reserved for private experiments. */
 | 
			
		||||
 | 
			
		||||
#define R_ARM_RXPC25		249
 | 
			
		||||
#define R_ARM_RSBREL32		250
 | 
			
		||||
#define R_ARM_THM_RPC22		251
 | 
			
		||||
#define R_ARM_RREL32		252
 | 
			
		||||
#define R_ARM_RABS32		253
 | 
			
		||||
#define R_ARM_RPC24		254
 | 
			
		||||
#define R_ARM_RBASE		255
 | 
			
		||||
 | 
			
		||||
#define R_TYPE(name)		__CONCAT(R_ARM_,name)
 | 
			
		||||
 | 
			
		||||
/* Processor specific program header flags */
 | 
			
		||||
#define PF_ARM_SB		0x10000000
 | 
			
		||||
#define PF_ARM_PI		0x20000000
 | 
			
		||||
#define PF_ARM_ENTRY		0x80000000
 | 
			
		||||
 | 
			
		||||
/* Processor specific section header flags */
 | 
			
		||||
#define SHF_ENTRYSECT		0x10000000
 | 
			
		||||
#define SHF_COMDEF		0x80000000
 | 
			
		||||
 | 
			
		||||
/* Processor specific symbol types */
 | 
			
		||||
#define STT_ARM_TFUNC		STT_LOPROC
 | 
			
		||||
 | 
			
		||||
#ifdef _KERNEL
 | 
			
		||||
#ifdef ELFSIZE
 | 
			
		||||
#define	ELF_MD_PROBE_FUNC	ELFNAME2(arm_netbsd,probe)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct exec_package;
 | 
			
		||||
 | 
			
		||||
int arm_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *, char *,
 | 
			
		||||
	vaddr_t *);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _ARM_ELF_MACHDEP_H_ */
 | 
			
		||||
@@ -1,79 +0,0 @@
 | 
			
		||||
/*	$OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ARM_ENDIAN_H_
 | 
			
		||||
#define _ARM_ENDIAN_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
 | 
			
		||||
/* According to RealView Assembler User's Guide, REV and REV16 are available
 | 
			
		||||
 * in Thumb code and 16-bit instructions when used in Thumb-2 code.
 | 
			
		||||
 *
 | 
			
		||||
 * REV Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * REV16 Rd, Rm
 | 
			
		||||
 *   Rd and Rm must both be Lo registers.
 | 
			
		||||
 *
 | 
			
		||||
 * The +l constraint takes care of this without constraining us in ARM mode.
 | 
			
		||||
 */
 | 
			
		||||
#define __swap16md(x) ({                                        \
 | 
			
		||||
    register u_int16_t _x = (x);                                \
 | 
			
		||||
    __asm__ __volatile__("rev16 %0, %0" : "+l" (_x));           \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap32md(x) ({                                        \
 | 
			
		||||
    register u_int32_t _x = (x);                                \
 | 
			
		||||
    __asm__ __volatile__("rev %0, %0" : "+l" (_x));             \
 | 
			
		||||
    _x;                                                         \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define __swap64md(x) ({                                        \
 | 
			
		||||
    u_int64_t _swap64md_x = (x);                                \
 | 
			
		||||
    (u_int64_t) __swap32md(_swap64md_x >> 32) |                 \
 | 
			
		||||
        (u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/* Tell sys/endian.h we have MD variants of the swap macros.  */
 | 
			
		||||
#define MD_SWAP
 | 
			
		||||
 | 
			
		||||
#endif  /* __GNUC__ */
 | 
			
		||||
 | 
			
		||||
#if defined(__ARMEB__)
 | 
			
		||||
#define _BYTE_ORDER _BIG_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
#define _BYTE_ORDER _LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
#define __STRICT_ALIGNMENT
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/endian.h>
 | 
			
		||||
 | 
			
		||||
#endif  /* !_ARM_ENDIAN_H_ */
 | 
			
		||||
							
								
								
									
										191
									
								
								libc/arch-arm/include/machine/ieee.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								libc/arch-arm/include/machine/ieee.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
/*	$OpenBSD: ieee.h,v 1.1 2004/02/01 05:09:49 drahn Exp $	*/
 | 
			
		||||
/*	$NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 1992, 1993
 | 
			
		||||
 *	The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This software was developed by the Computer Systems Engineering group
 | 
			
		||||
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 | 
			
		||||
 * contributed to Berkeley.
 | 
			
		||||
 *
 | 
			
		||||
 * All advertising materials mentioning features or use of this software
 | 
			
		||||
 * must display the following acknowledgement:
 | 
			
		||||
 *	This product includes software developed by the University of
 | 
			
		||||
 *	California, Lawrence Berkeley Laboratory.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 the University of
 | 
			
		||||
 *	California, Berkeley and its contributors.
 | 
			
		||||
 * 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 REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 *	@(#)ieee.h	8.1 (Berkeley) 6/11/93
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ieee.h defines the machine-dependent layout of the machine's IEEE
 | 
			
		||||
 * floating point.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Define the number of bits in each fraction and exponent.
 | 
			
		||||
 *
 | 
			
		||||
 *		     k	         k+1
 | 
			
		||||
 * Note that  1.0 x 2  == 0.1 x 2      and that denorms are represented
 | 
			
		||||
 *
 | 
			
		||||
 *					  (-exp_bias+1)
 | 
			
		||||
 * as fractions that look like 0.fffff x 2             .  This means that
 | 
			
		||||
 *
 | 
			
		||||
 *			 -126
 | 
			
		||||
 * the number 0.10000 x 2    , for instance, is the same as the normalized
 | 
			
		||||
 *
 | 
			
		||||
 *		-127			   -128
 | 
			
		||||
 * float 1.0 x 2    .  Thus, to represent 2    , we need one leading zero
 | 
			
		||||
 *
 | 
			
		||||
 *				  -129
 | 
			
		||||
 * in the fraction; to represent 2    , we need two, and so on.  This
 | 
			
		||||
 *
 | 
			
		||||
 *						     (-exp_bias-fracbits+1)
 | 
			
		||||
 * implies that the smallest denormalized number is 2
 | 
			
		||||
 *
 | 
			
		||||
 * for whichever format we are talking about: for single precision, for
 | 
			
		||||
 *
 | 
			
		||||
 *						-126		-149
 | 
			
		||||
 * instance, we get .00000000000000000000001 x 2    , or 1.0 x 2    , and
 | 
			
		||||
 *
 | 
			
		||||
 * -149 == -127 - 23 + 1.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The ARM has two sets of FP data formats.  The FPA supports 32-bit, 64-bit
 | 
			
		||||
 * and 96-bit IEEE formats, with the words in big-endian order.  VFP supports
 | 
			
		||||
 * 32-bin and 64-bit IEEE formats with the words in the CPU's native byte
 | 
			
		||||
 * order.
 | 
			
		||||
 *
 | 
			
		||||
 * The FPA also has two packed decimal formats, but we ignore them here.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define	SNG_EXPBITS	8
 | 
			
		||||
#define	SNG_FRACBITS	23
 | 
			
		||||
 | 
			
		||||
#define	DBL_EXPBITS	11
 | 
			
		||||
#define	DBL_FRACBITS	52
 | 
			
		||||
 | 
			
		||||
#ifndef __VFP_FP__
 | 
			
		||||
#define	E80_EXPBITS	15
 | 
			
		||||
#define	E80_FRACBITS	64
 | 
			
		||||
 | 
			
		||||
#define	EXT_EXPBITS	15
 | 
			
		||||
#define	EXT_FRACBITS	112
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct ieee_single {
 | 
			
		||||
	u_int	sng_frac:23;
 | 
			
		||||
	u_int	sng_exponent:8;
 | 
			
		||||
	u_int	sng_sign:1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __VFP_FP__
 | 
			
		||||
struct ieee_double {
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	u_int	dbl_sign:1;
 | 
			
		||||
	u_int	dbl_exp:11;
 | 
			
		||||
	u_int	dbl_frach:20;
 | 
			
		||||
	u_int	dbl_fracl;
 | 
			
		||||
#else /* !__ARMEB__ */
 | 
			
		||||
	u_int	dbl_fracl;
 | 
			
		||||
	u_int	dbl_frach:20;
 | 
			
		||||
	u_int	dbl_exp:11;
 | 
			
		||||
	u_int	dbl_sign:1;
 | 
			
		||||
#endif /* !__ARMEB__ */
 | 
			
		||||
};
 | 
			
		||||
#else /* !__VFP_FP__ */
 | 
			
		||||
struct ieee_double {
 | 
			
		||||
	u_int	dbl_frach:20;
 | 
			
		||||
	u_int	dbl_exp:11;
 | 
			
		||||
	u_int	dbl_sign:1;
 | 
			
		||||
	u_int	dbl_fracl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
union ieee_double_u {
 | 
			
		||||
	double                  dblu_d;
 | 
			
		||||
	struct ieee_double      dblu_dbl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct ieee_e80 {
 | 
			
		||||
	u_int	e80_exp:15;
 | 
			
		||||
	u_int	e80_zero:16;
 | 
			
		||||
	u_int	e80_sign:1;
 | 
			
		||||
	u_int	e80_frach:31;
 | 
			
		||||
	u_int	e80_j:1;
 | 
			
		||||
	u_int	e80_fracl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ieee_ext {
 | 
			
		||||
	u_int	ext_frach:16;
 | 
			
		||||
	u_int	ext_exp:15;
 | 
			
		||||
	u_int	ext_sign:1;
 | 
			
		||||
	u_int	ext_frachm;
 | 
			
		||||
	u_int	ext_fraclm;
 | 
			
		||||
	u_int	ext_fracl;
 | 
			
		||||
};
 | 
			
		||||
#endif /* !__VFP_FP__ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Floats whose exponent is in [1..INFNAN) (of whatever type) are
 | 
			
		||||
 * `normal'.  Floats whose exponent is INFNAN are either Inf or NaN.
 | 
			
		||||
 * Floats whose exponent is zero are either zero (iff all fraction
 | 
			
		||||
 * bits are zero) or subnormal values.
 | 
			
		||||
 *
 | 
			
		||||
 * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
 | 
			
		||||
 * high fraction; if the bit is set, it is a `quiet NaN'.
 | 
			
		||||
 */
 | 
			
		||||
#define	SNG_EXP_INFNAN	255
 | 
			
		||||
#define	DBL_EXP_INFNAN	2047
 | 
			
		||||
#ifndef __VFP_FP__
 | 
			
		||||
#define	E80_EXP_INFNAN	32767
 | 
			
		||||
#define	EXT_EXP_INFNAN	32767
 | 
			
		||||
#endif /* !__VFP_FP__ */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#define	SNG_QUIETNAN	(1 << 22)
 | 
			
		||||
#define	DBL_QUIETNAN	(1 << 19)
 | 
			
		||||
#ifndef __VFP_FP__
 | 
			
		||||
#define	E80_QUIETNAN	(1 << 15)
 | 
			
		||||
#define	EXT_QUIETNAN	(1 << 15)
 | 
			
		||||
#endif /* !__VFP_FP__ */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Exponent biases.
 | 
			
		||||
 */
 | 
			
		||||
#define	SNG_EXP_BIAS	127
 | 
			
		||||
#define	DBL_EXP_BIAS	1023
 | 
			
		||||
#ifndef __VFP_FP__
 | 
			
		||||
#define	E80_EXP_BIAS	16383
 | 
			
		||||
#define	EXT_EXP_BIAS	16383
 | 
			
		||||
#endif /* !__VFP_FP__ */
 | 
			
		||||
							
								
								
									
										10
									
								
								libc/arch-arm/include/machine/internal_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								libc/arch-arm/include/machine/internal_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* $OpenBSD: internal_types.h,v 1.2 2004/05/06 15:53:39 drahn Exp $ */
 | 
			
		||||
/* Public domain */
 | 
			
		||||
#ifndef _ARM_INTERNAL_TYPES_H_
 | 
			
		||||
#define _ARM_INTERNAL_TYPES_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __CHAR_UNSIGNED__
 | 
			
		||||
#define __machine_has_unsigned_chars
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user