Compare commits

..

2 Commits

Author SHA1 Message Date
Baligh Uddin
e4dda1f1e9 Merge "resolved conflicts for merge of 5d0ad38c to jb-mr2-dev" into jb-mr2-dev 2013-09-25 02:31:37 +00:00
Elliott Hughes
5a6f55a3c4 resolved conflicts for merge of 5d0ad38c to jb-mr2-dev
Change-Id: I606f6d86aad46c5eda0dc0d907fe691ca0eea826
2013-09-24 15:53:34 -07:00
4280 changed files with 132532 additions and 264923 deletions

View File

@@ -8,5 +8,8 @@ KNOWN ABI BUGS
sigset_t is too small on ARM and x86 (but correct on MIPS), so support
for real-time signals is broken. http://b/5828899
Too few TLS slots mean we can't allocate 128 pthread_key_t instances,
which POSIX says should be the minimum.
atexit(3) handlers registered by a shared library aren't called on
dlclose(3); this only affects ARM. http://b/4998315

View File

@@ -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
# ************************************************

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

File diff suppressed because it is too large Load Diff

26
libc/CAVEATS Normal file
View 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

File diff suppressed because it is too large Load Diff

View File

@@ -1,334 +1,321 @@
# This file is used to automatically generate bionic's system call stubs.
# This file is used to automatically generate bionic's the system calls stubs.
#
# Each non-blank, non-comment line has the following format:
# Each non comment line has the following format:
#
# return_type func_name[|alias_list][:syscall_name[:socketcall_id]]([parameter_list]) arch_list
# return_type func_name[:syscall_name[:call_id]]([parameter_list]) (1|-1|"stub")
#
# where:
# arch_list ::= "all" | arch+
# arch ::= "arm" | "arm64" | "mips" | "mips64" | "x86" | "x86_64"
#
# Note:
# Note that:
# - syscall_name corresponds to the name of the syscall, which may differ from
# the exported function name (example: the exit syscall is implemented by the _exit()
# function, which is not the same as the standard C exit() function which calls it)
#
# - alias_list is optional comma separated list of function aliases.
#
# - The call_id parameter, given that func_name and syscall_name have
# The call_id parameter, given that func_name and syscall_name have
# been provided, allows the user to specify dispatch style syscalls.
# For example, socket() syscall on i386 actually becomes:
# socketcall(__NR_socket, 1, *(rest of args on stack)).
#
# - Each parameter type is assumed to be stored in 32 bits.
# - each parameter type is assumed to be stored on 32 bits, there is no plan to support
# 64-bit architectures at the moment
#
# - the final field can be "1", meaning: generate a stub for each architecture,
# taking the constants from the kernel header files.
#
# - the final field can be "stub" meaning: do not generate any stubs ---
# in this case, a hand-written custom stub must be provided.
# TODO: replace this with something like "custom" or "none", or remove
# it entirely.
#
# - the final field can be a three-element list of 1s and -1 meaning:
# this system call is only available on some of the architectures (1),
# and no stub should be generated for those architectures marked with -1.
# the order is arm,x86,mips.
# TODO: replace this with something more readable like "-arm,-mips" (meaning x86 only).
#
# This file is processed by a python script named gensyscalls.py.
#
int execve(const char*, char* const*, char* const*) all
# process management
void _exit:exit_group (int) 1
void _exit_thread:exit (int) 1
pid_t __fork:fork (void) 1
pid_t _waitpid:waitpid (pid_t, int*, int, struct rusage*) -1,1,1
int __waitid:waitid(int, pid_t, struct siginfo_t*, int,void*) 1
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1
uid_t getuid:getuid32() arm,x86
uid_t getuid:getuid() arm64,mips,mips64,x86_64
gid_t getgid:getgid32() arm,x86
gid_t getgid:getgid() arm64,mips,mips64,x86_64
uid_t geteuid:geteuid32() arm,x86
uid_t geteuid:geteuid() arm64,mips,mips64,x86_64
gid_t getegid:getegid32() arm,x86
gid_t getegid:getegid() arm64,mips,mips64,x86_64
uid_t getresuid:getresuid32(uid_t* ruid, uid_t* euid, uid_t* suid) arm,x86
uid_t getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) arm64,mips,mips64,x86_64
gid_t getresgid:getresgid32(gid_t* rgid, gid_t* egid, gid_t* sgid) arm,x86
gid_t getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) arm64,mips,mips64,x86_64
ssize_t readahead(int, off64_t, size_t) all
int getgroups:getgroups32(int, gid_t*) arm,x86
int getgroups:getgroups(int, gid_t*) arm64,mips,mips64,x86_64
pid_t getpgid(pid_t) all
pid_t getppid() all
pid_t getsid(pid_t) all
pid_t setsid() all
int setgid:setgid32(gid_t) arm,x86
int setgid:setgid(gid_t) arm64,mips,mips64,x86_64
int setuid:setuid32(uid_t) arm,x86
int setuid:setuid(uid_t) arm64,mips,mips64,x86_64
int setreuid:setreuid32(uid_t, uid_t) arm,x86
int setreuid:setreuid(uid_t, uid_t) arm64,mips,mips64,x86_64
int setresuid:setresuid32(uid_t, uid_t, uid_t) arm,x86
int setresuid:setresuid(uid_t, uid_t, uid_t) arm64,mips,mips64,x86_64
int setresgid:setresgid32(gid_t, gid_t, gid_t) arm,x86
int setresgid:setresgid(gid_t, gid_t, gid_t) arm64,mips,mips64,x86_64
void* __brk:brk(void*) all
int kill(pid_t, int) all
int tgkill(pid_t tgid, pid_t tid, int sig) all
int __ptrace:ptrace(int request, int pid, void* addr, void* data) all
# NOTE: this system call is never called directly, but we list it there
# to have __NR_clone properly defined.
#
pid_t __sys_clone:clone (int, void*, int*, void*, int*) 1
# <sys/resource.h>
int getrusage(int, struct rusage*) all
int __getpriority:getpriority(int, int) all
int setpriority(int, int, int) all
# On LP64, rlimit and rlimit64 are the same.
# On 32-bit systems we use prlimit64 to implement the rlimit64 functions.
int getrlimit:ugetrlimit(int, struct rlimit*) arm,x86
int getrlimit(int, struct rlimit*) mips
int getrlimit|getrlimit64(int, struct rlimit*) arm64,mips64,x86_64
int setrlimit(int, const struct rlimit*) arm,mips,x86
int setrlimit|setrlimit64(int, const struct rlimit*) arm64,mips64,x86_64
int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*) arm64,mips64,x86_64
int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x86
int execve (const char*, char* const*, char* const*) 1
int setgroups:setgroups32(int, const gid_t*) arm,x86
int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64
int setpgid(pid_t, pid_t) all
pid_t vfork(void) arm
int setregid:setregid32(gid_t, gid_t) arm,x86
int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64
int chroot(const char*) all
int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long) all
long __arch_prctl:arch_prctl(int, unsigned long) x86_64
int capget(cap_user_header_t header, cap_user_data_t data) all
int capset(cap_user_header_t header, const cap_user_data_t data) all
int sigaltstack(const stack_t*, stack_t*) all
int acct(const char* filepath) all
int __setuid:setuid32 (uid_t) 1,1,-1
int __setuid:setuid (uid_t) -1,-1,1
uid_t getuid:getuid32 () 1,1,-1
uid_t getuid:getuid () -1,-1,1
gid_t getgid:getgid32 () 1,1,-1
gid_t getgid:getgid () -1,-1,1
uid_t geteuid:geteuid32 () 1,1,-1
uid_t geteuid:geteuid () -1,-1,1
gid_t getegid:getegid32 () 1,1,-1
gid_t getegid:getegid () -1,-1,1
uid_t getresuid:getresuid32 (uid_t *ruid, uid_t *euid, uid_t *suid) 1,1,-1
uid_t getresuid:getresuid (uid_t *ruid, uid_t *euid, uid_t *suid) -1,-1,1
gid_t getresgid:getresgid32 (gid_t *rgid, gid_t *egid, gid_t *sgid) 1,1,-1
gid_t getresgid:getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid) -1,-1,1
pid_t gettid() 1
ssize_t readahead(int, off64_t, size_t) 1
int getgroups:getgroups32(int, gid_t *) 1,1,-1
int getgroups:getgroups(int, gid_t *) -1,-1,1
pid_t getpgid(pid_t) 1
pid_t getppid() 1
pid_t getsid(pid_t) 1
pid_t setsid() 1
int setgid:setgid32(gid_t) 1,1,-1
int setgid:setgid(gid_t) -1,-1,1
int seteuid:seteuid32(uid_t) stub
int __setreuid:setreuid32(uid_t, uid_t) 1,1,-1
int __setreuid:setreuid(uid_t, uid_t) -1,-1,1
int __setresuid:setresuid32(uid_t, uid_t, uid_t) 1,1,-1
int __setresuid:setresuid(uid_t, uid_t, uid_t) -1,-1,1
int setresgid:setresgid32(gid_t, gid_t, gid_t) 1,1,-1
int setresgid:setresgid(gid_t, gid_t, gid_t) -1,-1,1
void* __brk:brk(void*) 1
# see comments in arch-arm/bionic/kill.S to understand why we don't generate an ARM stub for kill/tkill
int kill(pid_t, int) -1,1,1
int tkill(pid_t tid, int sig) -1,1,1
int tgkill(pid_t tgid, pid_t tid, int sig) -1,1,1
int __ptrace:ptrace(int request, int pid, void* addr, void* data) 1
int __set_thread_area:set_thread_area(void* user_desc) -1,1,1
int __getpriority:getpriority(int, int) 1
int setpriority(int, int, int) 1
int setrlimit(int resource, const struct rlimit *rlp) 1
int getrlimit:ugetrlimit(int resource, struct rlimit *rlp) 1,1,-1
int getrlimit:getrlimit(int resource, struct rlimit *rlp) -1,-1,1
int getrusage(int who, struct rusage* r_usage) 1
int setgroups:setgroups32(int, const gid_t *) 1,1,-1
int setgroups:setgroups(int, const gid_t *) -1,-1,1
pid_t getpgrp(void) stub
int setpgid(pid_t, pid_t) 1
pid_t vfork(void) 1,-1,-1
int setregid:setregid32(gid_t, gid_t) 1,1,-1
int setregid:setregid(gid_t, gid_t) -1,-1,1
int chroot(const char *) 1
# IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
# to match the kernel implementation.
int prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5) 1
int capget(cap_user_header_t header, cap_user_data_t data) 1
int capset(cap_user_header_t header, const cap_user_data_t data) 1
int sigaltstack(const stack_t*, stack_t*) 1
int acct(const char* filepath) 1
# file descriptors
ssize_t read(int, void*, size_t) all
ssize_t write(int, const void*, size_t) all
ssize_t pread64(int, void*, size_t, off64_t) arm,mips,x86
ssize_t pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
ssize_t pwrite64(int, void*, size_t, off64_t) arm,mips,x86
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
int close(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) 1
ssize_t write (int, const void*, size_t) 1
ssize_t pread64 (int, void *, size_t, off64_t) 1
ssize_t pwrite64 (int, void *, size_t, off64_t) 1
int __open:open (const char*, int, mode_t) 1
int __openat:openat (int, const char*, int, mode_t) 1
int close (int) 1
int creat(const char*, mode_t) stub
off_t lseek(int, off_t, int) 1
int __llseek:_llseek (int, unsigned long, unsigned long, loff_t*, int) 1
pid_t getpid () 1
void * mmap(void *, size_t, int, int, int, long) stub
void * __mmap2:mmap2(void*, size_t, int, int, int, long) 1
int munmap(void *, size_t) 1
void * mremap(void *, size_t, size_t, unsigned long) 1
int msync(const void *, size_t, int) 1
int mprotect(const void *, size_t, int) 1
int madvise(const void *, size_t, int) 1
int mlock(const void *addr, size_t len) 1
int munlock(const void *addr, size_t len) 1
int mlockall(int flags) 1
int munlockall() 1
int mincore(void* start, size_t length, unsigned char* vec) 1
int __ioctl:ioctl(int, int, void *) 1
int readv(int, const struct iovec *, int) 1
int writev(int, const struct iovec *, int) 1
int __fcntl:fcntl(int, int, void*) 1
int flock(int, int) 1
int fchmod(int, mode_t) 1
int dup(int) 1
int pipe(int *) 1,1,-1
int pipe2(int *, int) 1
int dup2(int, int) 1
int select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *) 1
int ftruncate(int, off_t) 1
int ftruncate64(int, off64_t) 1
int getdents:getdents64(unsigned int, struct dirent *, unsigned int) 1
int fsync(int) 1
int fdatasync(int) 1
int fchown:fchown32(int, uid_t, gid_t) 1,1,-1
int fchown:fchown(int, uid_t, gid_t) -1,-1,1
void sync(void) 1
int __fcntl64:fcntl64(int, int, void *) 1
int __fstatfs64:fstatfs64(int, size_t, struct statfs *) 1
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) 1
int fstatat:fstatat64(int dirfd, const char *path, struct stat *buf, int flags) 1
int mkdirat(int dirfd, const char *pathname, mode_t mode) 1
int fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags) 1
int fchmodat(int dirfd, const char *path, mode_t mode, int flags) 1
int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) 1
int fsetxattr(int, const char *, const void *, size_t, int) 1
ssize_t fgetxattr(int, const char *, void *, size_t) 1
ssize_t flistxattr(int, char *, size_t) 1
int fremovexattr(int, const char *) 1
# file system
int chdir(const char*) all
int mount(const char*, const char*, const char*, unsigned long, const void*) all
int umount2(const char*, int) all
int __getcwd:getcwd(char* buf, size_t size) all
int fchdir(int) all
int setxattr(const char*, const char*, const void*, size_t, int) all
int lsetxattr(const char*, const char*, const void*, size_t, int) all
ssize_t getxattr(const char*, const char*, void*, size_t) all
ssize_t lgetxattr(const char*, const char*, void*, size_t) all
ssize_t listxattr(const char*, char*, size_t) all
ssize_t llistxattr(const char*, char*, size_t) all
int removexattr(const char*, const char*) all
int lremovexattr(const char*, const char*) all
int swapon(const char*, int) all
int swapoff(const char*) all
int link (const char*, const char*) 1
int unlink (const char*) 1
int unlinkat (int, const char *, int) 1
int chdir (const char*) 1
int mknod (const char*, mode_t, dev_t) 1
int chmod (const char*,mode_t) 1
int chown:chown32(const char *, uid_t, gid_t) 1,1,-1
int chown:chown(const char *, uid_t, gid_t) -1,-1,1
int lchown:lchown32 (const char*, uid_t, gid_t) 1,1,-1
int lchown:lchown (const char*, uid_t, gid_t) -1,-1,1
int mount (const char*, const char*, const char*, unsigned long, const void*) 1
int umount(const char*) stub
int umount2 (const char*, int) 1
int fstat:fstat64(int, struct stat*) 1
int stat:stat64(const char *, struct stat *) 1
int lstat:lstat64(const char *, struct stat *) 1
int mkdir(const char *, mode_t) 1
int readlink(const char *, char *, size_t) 1
int rmdir(const char *) 1
int rename(const char *, const char *) 1
int __getcwd:getcwd(char * buf, size_t size) 1
int access(const char *, int) 1
int faccessat(int, const char *, int, int) 1
int symlink(const char *, const char *) 1
int fchdir(int) 1
int truncate(const char*, off_t) 1
int setxattr(const char *, const char *, const void *, size_t, int) 1
int lsetxattr(const char *, const char *, const void *, size_t, int) 1
ssize_t getxattr(const char *, const char *, void *, size_t) 1
ssize_t lgetxattr(const char *, const char *, void *, size_t) 1
ssize_t listxattr(const char *, char *, size_t) 1
ssize_t llistxattr(const char *, char *, size_t) 1
int removexattr(const char *, const char *) 1
int lremovexattr(const char *, const char *) 1
int __statfs64:statfs64(const char *, size_t, struct statfs *) 1
long unshare(unsigned long) 1
# time
int settimeofday(const struct timeval*, const struct timezone*) all
clock_t times(struct tms*) all
int nanosleep(const struct timespec*, struct timespec*) all
int clock_settime(clockid_t 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 () 1
int gettimeofday(struct timeval*, struct timezone*) 1
int settimeofday(const struct timeval*, const struct timezone*) 1
clock_t times(struct tms *) 1
int nanosleep(const struct timespec *, struct timespec *) 1
int clock_gettime(clockid_t clk_id, struct timespec *tp) 1
int clock_settime(clockid_t clk_id, const struct timespec *tp) 1
int clock_getres(clockid_t clk_id, struct timespec *res) 1
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *req, struct timespec *rem) 1
int getitimer(int, const struct itimerval *) 1
int setitimer(int, const struct itimerval *, struct itimerval *) 1
int __timer_create:timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) 1
int __timer_settime:timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) 1
int __timer_gettime:timer_gettime(timer_t, struct itimerspec*) 1
int __timer_getoverrun:timer_getoverrun(timer_t) 1
int __timer_delete:timer_delete(timer_t) 1
int utimes(const char*, const struct timeval tvp[2]) 1
int utimensat(int, const char *, const struct timespec times[2], int) 1
# signals
int __sigaction:sigaction(int, const struct sigaction*, struct sigaction*) arm,mips,x86
int __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t) all
int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all
int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all
int sigaction(int, const struct sigaction *, struct sigaction *) 1
int sigprocmask(int, const sigset_t *, sigset_t *) 1
int __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask) 1,1,-1
int __sigsuspend:sigsuspend(const sigset_t *mask) -1,-1,1
int __rt_sigaction:rt_sigaction (int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize) 1
int __rt_sigprocmask:rt_sigprocmask (int how, const sigset_t *set, sigset_t *oset, size_t sigsetsize) 1
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t *info, struct timespec_t *timeout, size_t sigset_size) 1
int sigpending(sigset_t *) 1
int signalfd4(int fd, const sigset_t *mask, size_t sizemask, int flags) 1
# sockets
int __socket:socket(int, int, int) arm,arm64,mips,mips64,x86_64
int socketpair(int, int, int, int*) arm,arm64,mips,mips64,x86_64
int bind(int, struct sockaddr*, int) arm,arm64,mips,mips64,x86_64
int __connect:connect(int, struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
int listen(int, int) arm,arm64,mips,mips64,x86_64
int __accept4:accept4(int, struct sockaddr*, socklen_t*, int) arm,arm64,mips,mips64,x86_64
int getsockname(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int getpeername(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int shutdown(int, int) arm,arm64,mips,mips64,x86_64
int setsockopt(int, int, int, const void*, socklen_t) arm,arm64,mips,mips64,x86_64
int getsockopt(int, int, int, void*, socklen_t*) arm,arm64,mips,mips64,x86_64
int sendmsg(int, const struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64
int recvmsg(int, struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64
int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*) arm,arm64,mips,mips64,x86_64
int sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips,mips64,x86_64
int socket(int, int, int) 1,-1,1
int socketpair(int, int, int, int*) 1,-1,1
int bind(int, struct sockaddr *, int) 1,-1,1
int connect(int, struct sockaddr *, socklen_t) 1,-1,1
int listen(int, int) 1,-1,1
int accept(int, struct sockaddr *, socklen_t *) 1,-1,1
int getsockname(int, struct sockaddr *, socklen_t *) 1,-1,1
int getpeername(int, struct sockaddr *, socklen_t *) 1,-1,1
int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t) 1,-1,1
int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *) 1,-1,1
int shutdown(int, int) 1,-1,1
int setsockopt(int, int, int, const void *, socklen_t) 1,-1,1
int getsockopt(int, int, int, void *, socklen_t *) 1,-1,1
int sendmsg(int, const struct msghdr *, unsigned int) 1,-1,1
int recvmsg(int, struct msghdr *, unsigned int) 1,-1,1
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
int __socket:socketcall:1(int, int, int) x86
int bind:socketcall:2(int, struct sockaddr*, int) x86
int __connect:socketcall:3(int, struct sockaddr*, socklen_t) x86
int listen:socketcall:4(int, int) x86
int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
int getpeername:socketcall:7(int, struct sockaddr*, socklen_t*) x86
int socketpair:socketcall:8(int, int, int, int*) x86
int sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
int recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
int shutdown:socketcall:13(int, int) x86
int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x86
int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86
int sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86
int recvmsg:socketcall:17(int, struct msghdr*, unsigned int) x86
int __accept4:socketcall:18(int, struct sockaddr*, socklen_t*, int) x86
int recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*) x86
int sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int) x86
int socket:socketcall:1 (int, int, int) -1,1,-1
int bind:socketcall:2 (int, struct sockaddr *, int) -1,1,-1
int connect:socketcall:3(int, struct sockaddr *, socklen_t) -1,1,-1
int listen:socketcall:4(int, int) -1,1,-1
int accept:socketcall:5(int, struct sockaddr *, socklen_t *) -1,1,-1
int getsockname:socketcall:6(int, struct sockaddr *, socklen_t *) -1,1,-1
int getpeername:socketcall:7(int, struct sockaddr *, socklen_t *) -1,1,-1
int socketpair:socketcall:8(int, int, int, int*) -1,1,-1
int sendto:socketcall:11(int, const void *, size_t, int, const struct sockaddr *, socklen_t) -1,1,-1
int recvfrom:socketcall:12(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *) -1,1,-1
int shutdown:socketcall:13(int, int) -1,1,-1
int setsockopt:socketcall:14(int, int, int, const void *, socklen_t) -1,1,-1
int getsockopt:socketcall:15(int, int, int, void *, socklen_t *) -1,1,-1
int sendmsg:socketcall:16(int, const struct msghdr *, unsigned int) -1,1,-1
int recvmsg:socketcall:17(int, struct msghdr *, unsigned int) -1,1,-1
# scheduler & real-time
int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param) all
int sched_getscheduler(pid_t pid) all
int sched_yield(void) all
int sched_setparam(pid_t pid, const struct sched_param* param) all
int sched_getparam(pid_t pid, struct sched_param* param) all
int sched_get_priority_max(int policy) all
int sched_get_priority_min(int policy) all
int sched_rr_get_interval(pid_t pid, struct timespec* interval) all
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) all
int setns(int, int) all
int unshare(int) all
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) all
int __getcpu:getcpu(unsigned*, unsigned*, void*) all
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param) 1
int sched_getscheduler(pid_t pid) 1
int sched_yield(void) 1
int sched_setparam(pid_t pid, const struct sched_param *param) 1
int sched_getparam(pid_t pid, struct sched_param *param) 1
int sched_get_priority_max(int policy) 1
int sched_get_priority_min(int policy) 1
int sched_rr_get_interval(pid_t pid, struct timespec *interval) 1
int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 1
int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) 1
int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 1
# io priorities
int ioprio_set(int which, int who, int ioprio) 1
int ioprio_get(int which, int who) 1
# other
int uname(struct utsname*) all
mode_t umask(mode_t) all
int __reboot:reboot(int, int, int, void*) all
int init_module(void*, unsigned long, const char*) all
int delete_module(const char*, unsigned int) all
int klogctl:syslog(int, char*, int) all
int sysinfo(struct sysinfo*) all
int personality(unsigned long) all
int uname(struct utsname *) 1
mode_t umask(mode_t) 1
int __reboot:reboot(int, int, int, void *) 1
int __syslog:syslog(int, char *, int) 1
int init_module(void *, unsigned long, const char *) 1
int delete_module(const char*, unsigned int) 1
int klogctl:syslog(int, char *, int) 1
int sysinfo(struct sysinfo *) 1
int personality(unsigned long) 1
long perf_event_open(struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags) 1
ssize_t tee(int, int, size_t, unsigned int) all
ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int) all
ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int) all
# futex
int futex(void *, int, int, void *, void *, int) 1
int epoll_create1(int) all
int epoll_ctl(int, int op, int, struct epoll_event*) all
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t) all
# epoll
int epoll_create(int size) 1
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 1
int epoll_wait(int epfd, struct epoll_event *events, int max, int timeout) 1
int eventfd:eventfd2(unsigned int, int) all
int inotify_init(void) 1
int inotify_add_watch(int, const char *, unsigned int) 1
int inotify_rm_watch(int, unsigned int) 1
void _exit|_Exit:exit_group(int) all
void __exit:exit(int) all
int poll(struct pollfd *, unsigned int, long) 1
int inotify_init1(int) all
int inotify_add_watch(int, const char*, unsigned int) all
int inotify_rm_watch(int, unsigned int) all
int eventfd:eventfd2(unsigned int, int) 1
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*) all
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t) all
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_NR_set_tls(void*) 1,-1,-1
int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) 1,-1,-1
# MIPS-specific
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,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,1
int syscall(int number,...) -1,-1,1

View File

@@ -1,93 +1,35 @@
# arm specific configs
# These are used by the 32-bit targets, but not the 64-bit ones.
libc_common_src_files_arm := \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
bionic/time64.c \
upstream-openbsd/lib/libc/stdio/putw.c \
# These are shared by all the 32-bit targets, but not the 64-bit ones.
libc_bionic_src_files_arm := \
bionic/mmap.cpp
libc_common_src_files_arm += \
bionic/memchr.c \
bionic/memrchr.c \
bionic/strchr.cpp \
bionic/strnlen.c \
bionic/strrchr.cpp \
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 \
upstream-openbsd/lib/libc/string/bcopy.c \
upstream-openbsd/lib/libc/string/stpcpy.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 \
# The C++ fortify function implementations for which there is an
# arm assembler version.
#
# Fortify implementations of libc functions.
# libc_common_src_files_arm +=
# bionic/__memcpy_chk.cpp \
# bionic/__memset_chk.cpp \
# bionic/__strcpy_chk.cpp \
# bionic/__strcat_chk.cpp \
libc_common_cflags_arm := -DSOFTFLOAT
##########################################
### CPU specific source files
libc_bionic_src_files_arm += \
_LIBC_ARCH_COMMON_SRC_FILES := \
arch-arm/bionic/abort_arm.S \
arch-arm/bionic/atomics_arm.c \
arch-arm/bionic/__bionic_clone.S \
arch-arm/bionic/clone.S \
arch-arm/bionic/eabi.c \
arch-arm/bionic/_exit_with_stack_teardown.S \
arch-arm/bionic/ffs.S \
arch-arm/bionic/futex_arm.S \
arch-arm/bionic/__get_sp.S \
arch-arm/bionic/kill.S \
arch-arm/bionic/libgcc_compat.c \
arch-arm/bionic/memcmp16.S \
arch-arm/bionic/memcmp.S \
arch-arm/bionic/_setjmp.S \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/sigsetjmp.S \
arch-arm/bionic/strcpy.S \
arch-arm/bionic/strlen.c.arm \
arch-arm/bionic/syscall.S \
arch-arm/bionic/tgkill.S \
arch-arm/bionic/tkill.S \
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
# These are used by the static and dynamic versions of the libc
# respectively.
_LIBC_ARCH_STATIC_SRC_FILES := \
arch-arm/bionic/exidx_static.c
libc_netbsd_src_files_arm := \
upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
_LIBC_ARCH_DYNAMIC_SRC_FILES := \
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)
ifeq ($(strip $(wildcard bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk)),)
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
include $(cpu_variant_mk)
libc_common_additional_dependencies += $(cpu_variant_mk)
cpu_variant_mk :=
libc_crt_target_cflags_arm := \
-I$(LOCAL_PATH)/arch-arm/include \
-mthumb-interwork
libc_crt_target_so_cflags_arm :=
libc_crt_target_crtbegin_file_arm := \
$(LOCAL_PATH)/arch-common/bionic/crtbegin.c
libc_crt_target_crtbegin_so_file_arm := \
$(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c
include bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk

View File

@@ -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);
}

View File

@@ -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

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
ENTRY(__get_sp)
mov r0, sp
bx lr
END(__get_sp)

View File

@@ -26,16 +26,19 @@
* SUCH DAMAGE.
*/
#include <private/bionic_asm.h>
#include <machine/asm.h>
#include <asm/unistd.h>
// void _exit_with_stack_teardown(void* stackBase, size_t stackSize)
ENTRY_PRIVATE(_exit_with_stack_teardown)
ldr r7, =__NR_munmap
swi #0
// If munmap failed, we ignore the failure and exit anyway.
// void _exit_with_stack_teardown(void* stackBase, int stackSize, int retCode)
ENTRY(_exit_with_stack_teardown)
mov lr, r2
ldr r7, =__NR_munmap
swi #0 // the stack is destroyed by this call
mov r0, lr
ldr r7, =__NR_exit
swi #0
mov r0, #0
ldr r7, =__NR_exit
swi #0
// The exit syscall does not return.
// exit() should never return, cause a crash if it does
mov r0, #0
ldr r0, [r0]
END(_exit_with_stack_teardown)

View File

@@ -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)

View File

@@ -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)

View File

@@ -0,0 +1,35 @@
/*
* 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 *__dso_handle;
__attribute__ ((visibility ("hidden")))
int atexit(void (*func)(void))
{
return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 The Android Open Source Project
* Copyright (c) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +27,9 @@
*/
#include <sys/types.h>
#include <private/libc_logging.h>
#include <stdio.h>
#include "private/libc_logging.h"
/*
* This source file should only be included by libc.so, its purpose is
* to support legacy ARM binaries by exporting a publicly visible

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2008-2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <linux/err.h>
#include <machine/asm.h>
#include <asm/unistd.h>
// int __pthread_clone(void* (*fn)(void*), void* child_stack, int flags, void* arg);
ENTRY(__pthread_clone)
# Copy the args onto the new stack.
stmdb r1!, {r0, r3}
# The sys_clone system call only takes two arguments: 'flags' and 'child_stack'.
# 'child_stack' is already in r1, but we need to move 'flags' into position.
mov r0, r2
stmfd sp!, {r4, r7}
# System call.
ldr r7, =__NR_clone
swi #0
movs r0, r0
beq 1f
# In parent, reload saved registers then either return or set errno.
ldmfd sp!, {r4, r7}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
1: # The child.
# pick the function arg and call address off the stack and jump
# to the C __thread_entry function which does some setup and then
# calls the thread's start function
pop {r0, r1}
# __thread_entry needs the TLS pointer
mov r2, sp
b __thread_entry
END(__pthread_clone)
#
# This function is defined as:
#
# pid_t __bionic_clone( int flags, void *child_stack,
# pid_t *pid, void *tls, pid_t *ctid,
# int (*fn)(void *), void* arg );
#
# NOTE: This is not the same signature as the glibc
# __clone function. Placing 'fn' and 'arg'
# at the end of the parameter list makes the
# implementation much simpler.
#
ENTRY(__bionic_clone)
mov ip, sp
.save {r4, r5, r6, r7}
# save registers to parent stack
stmfd sp!, {r4, r5, r6, r7}
# load extra parameters
ldmfd ip, {r4, r5, r6}
# store 'fn' and 'arg' to the child stack
str r5, [r1, #-4]
str r6, [r1, #-8]
# System call
ldr r7, =__NR_clone
swi #0
movs r0, r0
beq 1f
# In the parent, reload saved registers then either return or set errno.
ldmfd sp!, {r4, r5, r6, r7}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
1: # The child.
ldr r0, [sp, #-4]
ldr r1, [sp, #-8]
b __bionic_clone_entry
END(__bionic_clone)

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2012 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "../../bionic/libc_init_common.h"
#include <stddef.h>
#include <stdint.h>
__attribute__ ((section (".preinit_array")))
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".init_array")))
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;
__attribute__ ((section (".fini_array")))
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;
__LIBC_HIDDEN__ void _start() {
structors_array_t array;
array.preinit_array = &__PREINIT_ARRAY__;
array.init_array = &__INIT_ARRAY__;
array.fini_array = &__FINI_ARRAY__;
void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*));
__libc_init(raw_args, NULL, &main, &array);
}
#include "__dso_handle.h"
#include "atexit.h"

View 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

View 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

View 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
View 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);
}

View File

@@ -0,0 +1,41 @@
/* $NetBSD: ffs.S,v 1.5 2003/04/05 23:08:52 bjh21 Exp $ */
/*
* Copyright (c) 2001 Christopher Gilbert
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
#include <machine/cpu-features.h>
ENTRY(ffs)
/* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */
rsb r1, r0, #0
ands r0, r0, r1
clzne r0, r0
rsbne r0, r0, #32
bx lr
END(ffs)

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <asm/unistd.h>
#include <machine/asm.h>
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
// __futex_syscall3(*ftx, op, val)
ENTRY(__futex_syscall3)
stmdb sp!, {r4, r7}
.save {r4, r7}
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
bx lr
END(__futex_syscall3)
// __futex_syscall4(*ftx, op, val, *timespec)
ENTRY(__futex_syscall4)
b __futex_syscall3
END(__futex_syscall4)
// __futex_wait(*ftx, val, *timespec)
ENTRY(__futex_wait)
stmdb sp!, {r4, r7}
.save {r4, r7}
mov r3, r2
mov r2, r1
mov r1, #FUTEX_WAIT
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
bx lr
END(__futex_wait)
// __futex_wake(*ftx, counter)
ENTRY(__futex_wake)
.save {r4, r7}
stmdb sp!, {r4, r7}
mov r2, r1
mov r1, #FUTEX_WAKE
ldr r7, =__NR_futex
swi #0
ldmia sp!, {r4, r7}
bx lr
END(__futex_wake)

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <linux/err.h>
#include <asm/unistd.h>
#include <machine/asm.h>
/* unlike our auto-generated syscall stubs, this code saves lr
on the stack, as well as a few other registers. this makes
our stack unwinder happy, when we generate debug stack
traces after the C library or other parts of the system
abort due to a fatal runtime error (e.g. detection
of a corrupted malloc heap).
*/
ENTRY(kill)
stmfd sp!, {r4-r7, ip, lr}
ldr r7, =__NR_kill
swi #0
ldmfd sp!, {r4-r7, ip, lr}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(kill)

View File

@@ -1,159 +1,161 @@
/* Generated by genlibgcc_compat.py */
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
extern char __adddf3;
extern char __addsf3;
extern char __aeabi_cdcmpeq;
extern char __aeabi_cdcmple;
extern char __aeabi_cdrcmple;
extern char __aeabi_d2f;
extern char __aeabi_d2iz;
extern char __aeabi_dadd;
extern char __aeabi_dcmpeq;
extern char __aeabi_dcmpge;
extern char __aeabi_dcmpgt;
extern char __aeabi_dcmple;
extern char __aeabi_dcmplt;
extern char __aeabi_dcmpun;
extern char __aeabi_ddiv;
extern char __aeabi_dmul;
extern char __aeabi_drsub;
extern char __aeabi_dsub;
extern char __aeabi_f2d;
extern char __aeabi_f2iz;
extern char __aeabi_f2uiz;
extern char __aeabi_fadd;
extern char __aeabi_fcmpun;
extern char __aeabi_fdiv;
extern char __aeabi_fmul;
extern char __aeabi_frsub;
extern char __aeabi_fsub;
extern char __aeabi_i2d;
extern char __aeabi_i2f;
extern char __aeabi_idiv;
extern char __aeabi_idivmod;
extern char __aeabi_l2d;
extern char __aeabi_l2f;
extern char __aeabi_lasr;
extern char __aeabi_ldivmod;
extern char __aeabi_llsl;
extern char __aeabi_llsr;
extern char __aeabi_lmul;
extern char __aeabi_ui2d;
extern char __aeabi_ui2f;
extern char __aeabi_uidiv;
extern char __aeabi_uidivmod;
extern char __aeabi_ul2d;
extern char __aeabi_ul2f;
extern char __aeabi_uldivmod;
extern char __aeabi_unwind_cpp_pr0;
extern char __aeabi_unwind_cpp_pr1;
extern char __cmpdf2;
extern char __divdf3;
extern char __divsf3;
extern char __eqdf2;
extern char __extendsfdf2;
extern char __fixdfsi;
extern char __fixsfsi;
extern char __floatdidf;
extern char __floatdisf;
extern char __floatsidf;
extern char __floatsisf;
extern char __floatundidf;
extern char __floatundisf;
extern char __floatunsidf;
extern char __floatunsisf;
extern char __gedf2;
extern char __gtdf2;
extern char __ledf2;
extern char __ltdf2;
extern char __muldf3;
extern char __muldi3;
extern char __mulsf3;
extern char __nedf2;
extern char __popcount_tab;
extern char __popcountsi2;
extern char __subdf3;
extern char __subsf3;
extern char __truncdfsf2;
extern char __unorddf2;
extern char __unordsf2;
/* This file contains dummy references to libgcc.a functions to force the
* dynamic linker to copy their definition into the final libc.so binary.
*
* They are required to ensure backwards binary compatibility with
* Android 1.5, 1.6 and even 3.0 system images. Some applications built
* using the NDK require them to be here.
*
* Now, for a more elaborate description of the issue:
*
* libgcc.a is a compiler-specific library containing various helper
* functions used to implement certain operations that are not necessarily
* supported by the target CPU. For example, integer division doesn't have a
* corresponding CPU instruction on ARMv5, and is instead implemented in the
* compiler-generated machine code as a call to an __idiv helper function.
*
* Normally, one has to place libgcc.a in the link command used to generate
* target binaries (shared libraries and executables) after all objects and
* static libraries, but before dependent shared libraries, i.e. something
* like:
* gcc <options> -o libfoo.so foo.a libgcc.a -lc -lm
*
* This ensures that any helper function needed by the code in foo.a is copied
* into the final libfoo.so. Unfortunately, the Android build system has been
* using this instead:
*
* gcc <options> -o libfoo.so foo.a -lc -lm libgcc.a
*
* The problem with this is that if one helper function needed by foo.a has
* already been copied into libc.so or libm.so, then nothing will be copied
* into libfoo.so. Instead, a symbol import definition will be added to it
* so libfoo.so can directly call the one in libc.so at runtime.
*
* When changing toolchains for 2.0, the set of helper functions copied to
* libc.so changed, which resulted in some native shared libraries generated
* with the NDK to fail to load properly.
*
* The NDK has been fixed after 1.6_r1 to use the correct link command, so
* any native shared library generated with it should now be safe from that
* problem. On the other hand, existing shared libraries distributed with
* applications that were generated with a previous version of the NDK
* still need all 1.5/1.6 helper functions in libc.so and libm.so
*
* After 3.2, the toolchain was updated again, adding __aeabi_f2uiz to the
* list of requirements. Technically, this is due to mis-linked NDK libraries
* but it is easier to add a single function here than asking several app
* developers to fix their build.
*
* Final note: some of the functions below should really be in libm.so to
* completely reflect the state of 1.5/1.6 system images. However,
* since libm.so depends on libc.so, it's easier to put all of
* these in libc.so instead, since the dynamic linker will always
* search in libc.so before libm.so for dependencies.
*/
void* __bionic_libgcc_compat_symbols[] = {
&__adddf3,
&__addsf3,
&__aeabi_cdcmpeq,
&__aeabi_cdcmple,
&__aeabi_cdrcmple,
&__aeabi_d2f,
&__aeabi_d2iz,
&__aeabi_dadd,
&__aeabi_dcmpeq,
&__aeabi_dcmpge,
&__aeabi_dcmpgt,
&__aeabi_dcmple,
&__aeabi_dcmplt,
&__aeabi_dcmpun,
&__aeabi_ddiv,
&__aeabi_dmul,
&__aeabi_drsub,
&__aeabi_dsub,
&__aeabi_f2d,
&__aeabi_f2iz,
&__aeabi_f2uiz,
&__aeabi_fadd,
&__aeabi_fcmpun,
&__aeabi_fdiv,
&__aeabi_fmul,
&__aeabi_frsub,
&__aeabi_fsub,
&__aeabi_i2d,
&__aeabi_i2f,
&__aeabi_idiv,
&__aeabi_idivmod,
&__aeabi_l2d,
&__aeabi_l2f,
&__aeabi_lasr,
&__aeabi_ldivmod,
&__aeabi_llsl,
&__aeabi_llsr,
&__aeabi_lmul,
&__aeabi_ui2d,
&__aeabi_ui2f,
&__aeabi_uidiv,
&__aeabi_uidivmod,
&__aeabi_ul2d,
&__aeabi_ul2f,
&__aeabi_uldivmod,
&__aeabi_unwind_cpp_pr0,
&__aeabi_unwind_cpp_pr1,
&__cmpdf2,
&__divdf3,
&__divsf3,
&__eqdf2,
&__extendsfdf2,
&__fixdfsi,
&__fixsfsi,
&__floatdidf,
&__floatdisf,
&__floatsidf,
&__floatsisf,
&__floatundidf,
&__floatundisf,
&__floatunsidf,
&__floatunsisf,
&__gedf2,
&__gtdf2,
&__ledf2,
&__ltdf2,
&__muldf3,
&__muldi3,
&__mulsf3,
&__nedf2,
&__popcount_tab,
&__popcountsi2,
&__subdf3,
&__subsf3,
&__truncdfsf2,
&__unorddf2,
&__unordsf2,
};
#define COMPAT_FUNCTIONS_LIST \
XX(__adddf3) \
XX(__addsf3) \
XX(__aeabi_cdcmpeq) \
XX(__aeabi_cdcmple) \
XX(__aeabi_cdrcmple) \
XX(__aeabi_d2f) \
XX(__aeabi_d2iz) \
XX(__aeabi_dadd) \
XX(__aeabi_dcmpeq) \
XX(__aeabi_dcmpge) \
XX(__aeabi_dcmpgt) \
XX(__aeabi_dcmple) \
XX(__aeabi_dcmplt) \
XX(__aeabi_dcmpun) \
XX(__aeabi_ddiv) \
XX(__aeabi_dmul) \
XX(__aeabi_drsub) \
XX(__aeabi_dsub) \
XX(__aeabi_f2d) \
XX(__aeabi_f2iz) \
XX(__aeabi_f2uiz) \
XX(__aeabi_fadd) \
XX(__aeabi_fcmpun) \
XX(__aeabi_fdiv) \
XX(__aeabi_fmul) \
XX(__aeabi_frsub) \
XX(__aeabi_fsub) \
XX(__aeabi_i2d) \
XX(__aeabi_i2f) \
XX(__aeabi_idiv) \
XX(__aeabi_l2d) \
XX(__aeabi_l2f) \
XX(__aeabi_lmul) \
XX(__aeabi_llsl) \
XX(__aeabi_llsr) \
XX(__aeabi_ui2d) \
XX(__aeabi_ui2f) \
XX(__aeabi_ul2d) \
XX(__aeabi_ul2f) \
XX(__cmpdf2) \
XX(__divdf3) \
XX(__divsf3) \
XX(__eqdf2) \
XX(__extendsfdf2) \
XX(__fixdfsi) \
XX(__fixsfsi) \
XX(__floatdidf) \
XX(__floatdisf) \
XX(__floatsidf) \
XX(__floatsisf) \
XX(__floatundidf) \
XX(__floatundisf) \
XX(__floatunsidf) \
XX(__floatunsisf) \
XX(__gedf2) \
XX(__gtdf2) \
XX(__ledf2) \
XX(__ltdf2) \
XX(__muldf3) \
XX(__muldi3) \
XX(__mulsf3) \
XX(__nedf2) \
XX(__subdf3) \
XX(__subsf3) \
XX(__truncdfsf2) \
XX(__unorddf2) \
XX(__unordsf2) \
#define XX(f) extern void f(void);
COMPAT_FUNCTIONS_LIST
#undef XX
void __bionic_libgcc_compat_hooks(void)
{
#define XX(f) f();
COMPAT_FUNCTIONS_LIST
#undef XX
}

View File

@@ -27,7 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <machine/asm.h>
#ifdef HAVE_32_BYTE_CACHE_LINE
@@ -107,11 +107,9 @@ ENTRY(memcmp)
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
/* since r0 hold the result, move the first source
* pointer somewhere else

View 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)

View File

@@ -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)
@@ -352,9 +352,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 +442,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 +563,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 +590,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 +617,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

View File

@@ -0,0 +1,406 @@
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Prototype: void *memcpy (void *dst, const void *src, size_t count). */
/* Use the version of memcpy implemented using LDRD and STRD.
This version is tuned for Cortex-A15.
This might not be the best for other ARMv7-A CPUs,
but there is no predefine to distinguish between
different CPUs in the same architecture,
and this version is better than the plain memcpy provided in newlib.
Therefore, we use this version for all ARMv7-A CPUS. */
/* To make the same code compile for both ARM and Thumb instruction
sets, switch to unified syntax at the beginning of this function.
However, by using the same code, we may be missing optimization
opportunities. For instance, in LDRD/STRD instructions, the first
destination register must be even and the second consecutive in
ARM state, but not in Thumb state. */
#include <machine/cpu-features.h>
#include <machine/asm.h>
.syntax unified
ENTRY(memcpy)
/* Assumes that n >= 0, and dst, src are valid pointers.
If there is at least 8 bytes to copy, use LDRD/STRD.
If src and dst are misaligned with different offsets,
first copy byte by byte until dst is aligned,
and then copy using LDRD/STRD and shift if needed.
When less than 8 left, copy a word and then byte by byte. */
/* Save registers (r0 holds the return value):
optimized push {r0, r4, r5, r6, r7, lr}.
To try and improve performance, stack layout changed,
i.e., not keeping the stack looking like users expect
(highest numbered register at highest address). */
.save {r0, lr}
push {r0, lr}
.save {r4, r5}
strd r4, r5, [sp, #-8]!
.save {r6, r7}
strd r6, r7, [sp, #-8]!
/* TODO: Add debug frame directives.
We don't need exception unwind directives, because the code below
does not throw any exceptions and does not call any other functions.
Generally, newlib functions like this lack debug information for
assembler source. */
/* Get copying of tiny blocks out of the way first. */
/* Is there at least 4 bytes to copy? */
subs r2, r2, #4
blt copy_less_than_4 /* If n < 4. */
/* Check word alignment. */
ands ip, r0, #3 /* ip = last 2 bits of dst. */
bne dst_not_word_aligned /* If dst is not word-aligned. */
/* Get here if dst is word-aligned. */
ands ip, r1, #3 /* ip = last 2 bits of src. */
bne src_not_word_aligned /* If src is not word-aligned. */
word_aligned:
/* Get here if source and dst both are word-aligned.
The number of bytes remaining to copy is r2+4. */
/* Is there is at least 64 bytes to copy? */
subs r2, r2, #60
blt copy_less_than_64 /* If r2 + 4 < 64. */
/* First, align the destination buffer to 8-bytes,
to make sure double loads and stores don't cross cache line boundary,
as they are then more expensive even if the data is in the cache
(require two load/store issue cycles instead of one).
If only one of the buffers is not 8-bytes aligned,
then it's more important to align dst than src,
because there is more penalty for stores
than loads that cross cacheline boundary.
This check and realignment are only worth doing
if there is a lot to copy. */
/* Get here if dst is word aligned,
i.e., the 2 least significant bits are 0.
If dst is not 2w aligned (i.e., the 3rd bit is not set in dst),
then copy 1 word (4 bytes). */
ands r3, r0, #4
beq 11f /* If dst already two-word aligned. */
ldr r3, [r1], #4
str r3, [r0], #4
subs r2, r2, #4
blt copy_less_than_64
11:
/* TODO: Align to cacheline (useful for PLD optimization). */
/* Every loop iteration copies 64 bytes. */
1:
.irp offset, #0, #8, #16, #24, #32, #40, #48, #56
ldrd r4, r5, [r1, \offset]
strd r4, r5, [r0, \offset]
.endr
add r0, r0, #64
add r1, r1, #64
subs r2, r2, #64
bge 1b /* If there is more to copy. */
copy_less_than_64:
/* Get here if less than 64 bytes to copy, -64 <= r2 < 0.
Restore the count if there is more than 7 bytes to copy. */
adds r2, r2, #56
blt copy_less_than_8
/* Copy 8 bytes at a time. */
2:
ldrd r4, r5, [r1], #8
strd r4, r5, [r0], #8
subs r2, r2, #8
bge 2b /* If there is more to copy. */
copy_less_than_8:
/* Get here if less than 8 bytes to copy, -8 <= r2 < 0.
Check if there is more to copy. */
cmn r2, #8
beq return /* If r2 + 8 == 0. */
/* Restore the count if there is more than 3 bytes to copy. */
adds r2, r2, #4
blt copy_less_than_4
/* Copy 4 bytes. */
ldr r3, [r1], #4
str r3, [r0], #4
copy_less_than_4:
/* Get here if less than 4 bytes to copy, -4 <= r2 < 0. */
/* Restore the count, check if there is more to copy. */
adds r2, r2, #4
beq return /* If r2 == 0. */
/* Get here with r2 is in {1,2,3}={01,10,11}. */
/* Logical shift left r2, insert 0s, update flags. */
lsls r2, r2, #31
/* Copy byte by byte.
Condition ne means the last bit of r2 is 0.
Condition cs means the second to last bit of r2 is set,
i.e., r2 is 1 or 3. */
itt ne
ldrbne r3, [r1], #1
strbne r3, [r0], #1
itttt cs
ldrbcs r4, [r1], #1
ldrbcs r5, [r1]
strbcs r4, [r0], #1
strbcs r5, [r0]
return:
/* Restore registers: optimized pop {r0, r4, r5, r6, r7, pc} */
/* This is the only return point of memcpy. */
ldrd r6, r7, [sp], #8
ldrd r4, r5, [sp], #8
pop {r0, pc}
#ifndef __ARM_FEATURE_UNALIGNED
/* The following assembly macro implements misaligned copy in software.
Assumes that dst is word aligned, src is at offset "pull" bits from
word, push = 32 - pull, and the number of bytes that remain to copy
is r2 + 4, r2 >= 0. */
/* In the code below, r2 is the number of bytes that remain to be
written. The number of bytes read is always larger, because we have
partial words in the shift queue. */
.macro miscopy pull push shiftleft shiftright
/* Align src to the previous word boundary. */
bic r1, r1, #3
/* Initialize the shift queue. */
ldr r5, [r1], #4 /* Load a word from source. */
subs r2, r2, #4
blt 6f /* Go to misaligned copy of less than 8 bytes. */
/* Get here if there is more than 8 bytes to copy.
The number of bytes to copy is r2+8, r2 >= 0. */
subs r2, r2, #56
blt 4f /* Go to misaligned copy of less than 64 bytes. */
3:
/* Get here if there is more than 64 bytes to copy.
The number of bytes to copy is r2+64, r2 >= 0. */
/* Copy 64 bytes in every iteration.
Use a partial word from the shift queue. */
.irp offset, #0, #8, #16, #24, #32, #40, #48, #56
mov r6, r5, \shiftleft #\pull
ldrd r4, r5, [r1, \offset]
orr r6, r6, r4, \shiftright #\push
mov r7, r4, \shiftleft #\pull
orr r7, r7, r5, \shiftright #\push
strd r6, r7, [r0, \offset]
.endr
add r1, r1, #64
add r0, r0, #64
subs r2, r2, #64
bge 3b
4:
/* Get here if there is less than 64 bytes to copy (-64 <= r2 < 0)
and they are misaligned. */
/* Restore the count if there is more than 7 bytes to copy. */
adds r2, r2, #56
blt 6f /* Go to misaligned copy of less than 8 bytes. */
5:
/* Copy 8 bytes at a time.
Use a partial word from the shift queue. */
mov r6, r5, \shiftleft #\pull
ldrd r4, r5, [r1], #8
orr r6, r6, r4, \shiftright #\push
mov r7, r4, \shiftleft #\pull
orr r7, r7, r5, \shiftright #\push
strd r6, r7, [r0], #8
subs r2, r2, #8
bge 5b /* If there is more to copy. */
6:
/* Get here if there less than 8 bytes to copy (-8 <= r2 < 0)
and they are misaligned. */
/* Check if there is more to copy. */
cmn r2, #8
beq return
/* Check if there is less than 4 bytes to copy. */
cmn r2, #4
itt lt
/* Restore src offset from word-align. */
sublt r1, r1, #(\push / 8)
blt copy_less_than_4
/* Use a partial word from the shift queue. */
mov r3, r5, \shiftleft #\pull
/* Load a word from src, but without writeback
(this word is not fully written to dst). */
ldr r5, [r1]
/* Restore src offset from word-align. */
add r1, r1, #(\pull / 8)
/* Shift bytes to create one dst word and store it. */
orr r3, r3, r5, \shiftright #\push
str r3, [r0], #4
/* Use single byte copying of the remaining bytes. */
b copy_less_than_4
.endm
#endif /* not __ARM_FEATURE_UNALIGNED */
dst_not_word_aligned:
/* Get here when dst is not aligned and ip has the last 2 bits of dst,
i.e., ip is the offset of dst from word.
The number of bytes that remains to copy is r2 + 4,
i.e., there are at least 4 bytes to copy.
Write a partial word (0 to 3 bytes), such that dst becomes
word-aligned. */
/* If dst is at ip bytes offset from a word (with 0 < ip < 4),
then there are (4 - ip) bytes to fill up to align dst to the next
word. */
rsb ip, ip, #4 /* ip = #4 - ip. */
cmp ip, #2
/* Copy byte by byte with conditionals. */
itt gt
ldrbgt r3, [r1], #1
strbgt r3, [r0], #1
itt ge
ldrbge r4, [r1], #1
strbge r4, [r0], #1
ldrb lr, [r1], #1
strb lr, [r0], #1
/* Update the count.
ip holds the number of bytes we have just copied. */
subs r2, r2, ip /* r2 = r2 - ip. */
blt copy_less_than_4 /* If r2 < ip. */
/* Get here if there are more than 4 bytes to copy.
Check if src is aligned. If beforehand src and dst were not word
aligned but congruent (same offset), then now they are both
word-aligned, and we can copy the rest efficiently (without
shifting). */
ands ip, r1, #3 /* ip = last 2 bits of src. */
beq word_aligned /* If r1 is word-aligned. */
src_not_word_aligned:
/* Get here when src is not word-aligned, but dst is word-aligned.
The number of bytes that remains to copy is r2+4. */
#ifdef __ARM_FEATURE_UNALIGNED
/* Copy word by word using LDR when alignment can be done in hardware,
i.e., SCTLR.A is set, supporting unaligned access in LDR and STR. */
subs r2, r2, #60
blt 8f
7:
/* Copy 64 bytes in every loop iteration. */
.irp offset, #0, #4, #8, #12, #16, #20, #24, #28, #32, #36, #40, #44, #48, #52, #56, #60
ldr r3, [r1, \offset]
str r3, [r0, \offset]
.endr
add r0, r0, #64
add r1, r1, #64
subs r2, r2, #64
bge 7b
8:
/* Get here if less than 64 bytes to copy, -64 <= r2 < 0.
Check if there is more than 3 bytes to copy. */
adds r2, r2, #60
blt copy_less_than_4
9:
/* Get here if there is less than 64 but at least 4 bytes to copy,
where the number of bytes to copy is r2+4. */
ldr r3, [r1], #4
str r3, [r0], #4
subs r2, r2, #4
bge 9b
b copy_less_than_4
#else /* not __ARM_FEATURE_UNALIGNED */
/* ip has last 2 bits of src,
i.e., ip is the offset of src from word, and ip > 0.
Compute shifts needed to copy from src to dst. */
cmp ip, #2
beq miscopy_16_16 /* If ip == 2. */
bge miscopy_24_8 /* If ip == 3. */
/* Get here if ip == 1. */
/* Endian independent macros for shifting bytes within registers. */
#ifndef __ARMEB__
miscopy_8_24: miscopy pull=8 push=24 shiftleft=lsr shiftright=lsl
miscopy_16_16: miscopy pull=16 push=16 shiftleft=lsr shiftright=lsl
miscopy_24_8: miscopy pull=24 push=8 shiftleft=lsr shiftright=lsl
#else /* not __ARMEB__ */
miscopy_8_24: miscopy pull=8 push=24 shiftleft=lsl shiftright=lsr
miscopy_16_16: miscopy pull=16 push=16 shiftleft=lsl shiftright=lsr
miscopy_24_8: miscopy pull=24 push=8 shiftleft=lsl shiftright=lsr
#endif /* not __ARMEB__ */
#endif /* not __ARM_FEATURE_UNALIGNED */
END(memcpy)

View File

@@ -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)

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/cpu-features.h>
#include <machine/asm.h>
/*
* Optimized memset() for ARM.
*
* memset() returns its first argument.
*/
#if defined(__ARM_NEON__)
.fpu neon
#endif
ENTRY(bzero)
mov r2, r1
mov r1, #0
// Fall through to memset...
END(bzero)
ENTRY(memset)
#if defined(__ARM_NEON__)
#ifdef NEON_MEMSET_DIVIDER
cmp r2, #NEON_MEMSET_DIVIDER
bhi 11f
#endif
.save {r0}
stmfd sp!, {r0}
vdup.8 q0, r1
#ifndef NEON_UNALIGNED_ACCESS
/* do we have at least 16-bytes to write (needed for alignment below) */
cmp r2, #16
blo 3f
/* align destination to 16 bytes for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 2f
/* write up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
movs ip, r3, lsl #29
bge 1f
// writes 4 bytes, 32-bits aligned
vst1.32 {d0[0]}, [r0, :32]!
1: bcc 2f
// writes 8 bytes, 64-bits aligned
vst1.8 {d0}, [r0, :64]!
2:
#endif
/* make sure we have at least 32 bytes to write */
subs r2, r2, #32
blo 2f
vmov q1, q0
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
#ifndef NEON_UNALIGNED_ACCESS
vst1.8 {d0 - d3}, [r0, :128]!
#else
vst1.8 {d0 - d3}, [r0]!
#endif
bhs 1b
2: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 3f
// writes 16 bytes, 128-bits aligned
#ifndef NEON_UNALIGNED_ACCESS
vst1.8 {d0, d1}, [r0, :128]!
#else
vst1.8 {d0, d1}, [r0]!
#endif
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r0]!
1: bge 2f
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
11:
#endif
/*
* Optimized memset() for ARM.
*
* memset() returns its first argument.
*/
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
.save {r0, r4-r7, lr}
stmfd sp!, {r0, r4-r7, lr}
rsb r3, r0, #0
ands r3, r3, #3
cmp r3, r2
movhi r3, r2
/* splat r1 */
mov r1, r1, lsl #24
orr r1, r1, r1, lsr #8
orr r1, r1, r1, lsr #16
movs r12, r3, lsl #31
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
strcsb r1, [r0], #1
strmib r1, [r0], #1
subs r2, r2, r3
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
bxls lr
/* align the destination to a cache-line */
mov r12, r1
mov lr, r1
mov r4, r1
mov r5, r1
mov r6, r1
mov r7, r1
rsb r3, r0, #0
ands r3, r3, #0x1C
beq 3f
cmp r3, r2
andhi r3, r2, #0x1C
sub r2, r2, r3
/* conditionally writes 0 to 7 words (length in r3) */
movs r3, r3, lsl #28
stmcsia r0!, {r1, lr}
stmcsia r0!, {r1, lr}
stmmiia r0!, {r1, lr}
movs r3, r3, lsl #2
strcs r1, [r0], #4
3:
subs r2, r2, #32
mov r3, r1
bmi 2f
1: subs r2, r2, #32
stmia r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
bhs 1b
2: add r2, r2, #32
/* conditionally stores 0 to 31 bytes */
movs r2, r2, lsl #28
stmcsia r0!, {r1,r3,r12,lr}
stmmiia r0!, {r1, lr}
movs r2, r2, lsl #2
strcs r1, [r0], #4
strmih r1, [r0], #2
movs r2, r2, lsl #2
strcsb r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(memset)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -0,0 +1,787 @@
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "arm_asm.h"
#ifdef __ARMEB__
#define S2LOMEM lsl
#define S2LOMEMEQ lsleq
#define S2HIMEM lsr
#define MSB 0x000000ff
#define LSB 0xff000000
#define BYTE0_OFFSET 24
#define BYTE1_OFFSET 16
#define BYTE2_OFFSET 8
#define BYTE3_OFFSET 0
#else /* not __ARMEB__ */
#define S2LOMEM lsr
#define S2LOMEMEQ lsreq
#define S2HIMEM lsl
#define BYTE0_OFFSET 0
#define BYTE1_OFFSET 8
#define BYTE2_OFFSET 16
#define BYTE3_OFFSET 24
#define MSB 0xff000000
#define LSB 0x000000ff
#endif /* not __ARMEB__ */
.syntax unified
#if defined (__thumb__)
.thumb
.thumb_func
#endif
.global strcmp
.type strcmp, %function
strcmp:
#if (defined (__thumb__) && !defined (__thumb2__))
1:
ldrb r2, [r0]
ldrb r3, [r1]
adds r0, r0, #1
adds r1, r1, #1
cmp r2, #0
beq 2f
cmp r2, r3
beq 1b
2:
subs r0, r2, r3
bx lr
#elif (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
1:
ldrb r2, [r0], #1
ldrb r3, [r1], #1
cmp r2, #1
it cs
cmpcs r2, r3
beq 1b
subs r0, r2, r3
RETURN
#elif (defined (_ISA_THUMB_2) || defined (_ISA_ARM_6))
/* Use LDRD whenever possible. */
/* The main thing to look out for when comparing large blocks is that
the loads do not cross a page boundary when loading past the index
of the byte with the first difference or the first string-terminator.
For example, if the strings are identical and the string-terminator
is at index k, byte by byte comparison will not load beyond address
s1+k and s2+k; word by word comparison may load up to 3 bytes beyond
k; double word - up to 7 bytes. If the load of these bytes crosses
a page boundary, it might cause a memory fault (if the page is not mapped)
that would not have happened in byte by byte comparison.
If an address is (double) word aligned, then a load of a (double) word
from that address will not cross a page boundary.
Therefore, the algorithm below considers word and double-word alignment
of strings separately. */
/* High-level description of the algorithm.
* The fast path: if both strings are double-word aligned,
use LDRD to load two words from each string in every loop iteration.
* If the strings have the same offset from a word boundary,
use LDRB to load and compare byte by byte until
the first string is aligned to a word boundary (at most 3 bytes).
This is optimized for quick return on short unaligned strings.
* If the strings have the same offset from a double-word boundary,
use LDRD to load two words from each string in every loop iteration, as in the fast path.
* If the strings do not have the same offset from a double-word boundary,
load a word from the second string before the loop to initialize the queue.
Use LDRD to load two words from every string in every loop iteration.
Inside the loop, load the second word from the second string only after comparing
the first word, using the queued value, to guarantee safety across page boundaries.
* If the strings do not have the same offset from a word boundary,
use LDR and a shift queue. Order of loads and comparisons matters,
similarly to the previous case.
* Use UADD8 and SEL to compare words, and use REV and CLZ to compute the return value.
* The only difference between ARM and Thumb modes is the use of CBZ instruction.
* The only difference between big and little endian is the use of REV in little endian
to compute the return value, instead of MOV.
* No preload. [TODO.]
*/
.macro m_cbz reg label
#ifdef __thumb2__
cbz \reg, \label
#else /* not defined __thumb2__ */
cmp \reg, #0
beq \label
#endif /* not defined __thumb2__ */
.endm /* m_cbz */
.macro m_cbnz reg label
#ifdef __thumb2__
cbnz \reg, \label
#else /* not defined __thumb2__ */
cmp \reg, #0
bne \label
#endif /* not defined __thumb2__ */
.endm /* m_cbnz */
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
strd r4, r5, [sp, #8]
strd r6, r7, [sp]
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
.macro magic_compare_and_branch w1 w2 label
/* Macro to compare registers w1 and w2 and conditionally branch to label. */
cmp \w1, \w2 /* Are w1 and w2 the same? */
magic_find_zero_bytes \w1
it eq
cmpeq ip, #0 /* Is there a zero byte in w1? */
bne \label
.endm /* magic_compare_and_branch */
.macro magic_find_zero_bytes w1
/* Macro to find all-zero bytes in w1, result is in ip. */
#if (defined (__ARM_FEATURE_DSP))
uadd8 ip, \w1, r6
sel ip, r7, r6
#else /* not defined (__ARM_FEATURE_DSP) */
/* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
Coincidently, these processors only have Thumb-2 mode, where we can use the
the (large) magic constant available directly as an immediate in instructions.
Note that we cannot use the magic constant in ARM mode, where we need
to create the constant in a register. */
sub ip, \w1, #0x01010101
bic ip, ip, \w1
and ip, ip, #0x80808080
#endif /* not defined (__ARM_FEATURE_DSP) */
.endm /* magic_find_zero_bytes */
.macro setup_return w1 w2
#ifdef __ARMEB__
mov r1, \w1
mov r2, \w2
#else /* not __ARMEB__ */
rev r1, \w1
rev r2, \w2
#endif /* not __ARMEB__ */
.endm /* setup_return */
/*
optpld r0, #0
optpld r1, #0
*/
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
bne do_align
/* Fast path. */
init
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
.p2align 2
2:
/*
optpld r0, #16
optpld r1, #16
*/
/* Load the next double-word from each string. */
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
to read until the next word boudnary is 4-ip. */
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq byte2
bcs byte3
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne fast_return
m_cbz reg=r3, label=fast_return
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne fast_return
m_cbz reg=r3, label=fast_return
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
fast_return:
mov r0, ip
bx lr
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne strcmp_unaligned
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
magic_compare_and_branch w1=r2 w2=r4 label=return_24
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
/* Initialize the queue. */
ldr r5, [r1], #4
/* Compare two words in every iteration. */
.p2align 2
3:
/*
optpld r0, #16
optpld r1, #16
*/
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
/* Macro to compare misaligned strings. */
/* r0, r1 are word-aligned, and at least one of the strings
is not double-word aligned. */
/* Compare one word in every loop iteration. */
/* OFFSETLO is the original bit-offset of r1 from a word-boundary,
OFFSETHI is 32 - OFFSETLO (i.e., offset from the next word). */
/* Initialize the shift queue. */
ldr r5, [r1], #4
/* Compare one word from each string in every loop iteration. */
.p2align 2
7:
ldr r3, [r0], #4
S2LOMEM r5, r5, #\offsetlo
magic_find_zero_bytes w1=r3
cmp r7, ip, S2HIMEM #\offsetlo
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne return_32
b 7b
.endm /* miscmp_word */
strcmp_unaligned:
/* r0 is word-aligned, r1 is at offset ip from a word. */
/* Align r1 to the (previous) word-boundary. */
bic r1, r1, #3
/* Unaligned comparison word by word using LDRs. */
cmp ip, #2
beq miscmp_word_16 /* If ip == 2. */
bge miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
return_32:
setup_return w1=r3, w2=r2
b do_return
return_34:
setup_return w1=r3, w2=r4
b do_return
return_25:
setup_return w1=r2, w2=r5
b do_return
return_35:
setup_return w1=r3, w2=r5
b do_return
return_24:
setup_return w1=r2, w2=r4
do_return:
#ifdef __ARMEB__
mov r0, ip
#else /* not __ARMEB__ */
rev r0, ip
#endif /* not __ARMEB__ */
/* Restore temporaries early, before computing the return value. */
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
m_cbz reg=r0, label=compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
/* Here, r0 contains the number of bits on the right of the first all-zero byte in r1. */
lsr r1, r1, r0
lsr r2, r2, r0
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
If r1>r2 then (C==1 and Z==0) and LS doesn't hold and r0 is #1 at return.
If r1<r2 then (C==0 and Z==0) and we execute SBC with carry_in=0,
which means r0:=r0-r0-1 and r0 is #-1 at return.
If r1=r2 then (C==1 and Z==1) and we execute SBC with carry_in=1,
which means r0:=r0-r0 and r0 is #0 at return.
(C==0 and Z==1) cannot happen because the carry bit is "not borrow". */
it ls
sbcls r0, r0, r0
bx lr
#else /* !(defined (_ISA_THUMB_2) || defined (_ISA_ARM_6)
defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) ||
(defined (__thumb__) && !defined (__thumb2__))) */
/* Use LDR whenever possible. */
#ifdef __thumb2__
#define magic1(REG) 0x01010101
#define magic2(REG) 0x80808080
#else
#define magic1(REG) REG
#define magic2(REG) REG, lsl #7
#endif
optpld r0
optpld r1
eor r2, r0, r1
tst r2, #3
/* Strings not at same byte offset from a word boundary. */
bne strcmp_unaligned
ands r2, r0, #3
bic r0, r0, #3
bic r1, r1, #3
ldr ip, [r0], #4
it eq
ldreq r3, [r1], #4
beq 1f
/* Although s1 and s2 have identical initial alignment, they are
not currently word aligned. Rather than comparing bytes,
make sure that any bytes fetched from before the addressed
bytes are forced to 0xff. Then they will always compare
equal. */
eor r2, r2, #3
lsl r2, r2, #3
mvn r3, MSB
S2LOMEM r2, r3, r2
ldr r3, [r1], #4
orr ip, ip, r2
orr r3, r3, r2
1:
#ifndef __thumb2__
/* Load the 'magic' constant 0x01010101. */
str r4, [sp, #-4]!
mov r4, #1
orr r4, r4, r4, lsl #8
orr r4, r4, r4, lsl #16
#endif
.p2align 2
4:
optpld r0, #8
optpld r1, #8
sub r2, ip, magic1(r4)
cmp ip, r3
itttt eq
/* check for any zero bytes in first word */
biceq r2, r2, ip
tsteq r2, magic2(r4)
ldreq ip, [r0], #4
ldreq r3, [r1], #4
beq 4b
2:
/* There's a zero or a different byte in the word */
S2HIMEM r0, ip, #24
S2LOMEM ip, ip, #8
cmp r0, #1
it cs
cmpcs r0, r3, S2HIMEM #24
it eq
S2LOMEMEQ r3, r3, #8
beq 2b
/* On a big-endian machine, r0 contains the desired byte in bits
0-7; on a little-endian machine they are in bits 24-31. In
both cases the other bits in r0 are all zero. For r3 the
interesting byte is at the other end of the word, but the
other bits are not necessarily zero. We need a signed result
representing the differnece in the unsigned bytes, so for the
little-endian case we can't just shift the interesting bits
up. */
#ifdef __ARMEB__
sub r0, r0, r3, lsr #24
#else
and r3, r3, #255
#ifdef __thumb2__
/* No RSB instruction in Thumb2 */
lsr r0, r0, #24
sub r0, r0, r3
#else
rsb r0, r3, r0, lsr #24
#endif
#endif
#ifndef __thumb2__
ldr r4, [sp], #4
#endif
RETURN
strcmp_unaligned:
#if 0
/* The assembly code below is based on the following alogrithm. */
#ifdef __ARMEB__
#define RSHIFT <<
#define LSHIFT >>
#else
#define RSHIFT >>
#define LSHIFT <<
#endif
#define body(shift) \
mask = 0xffffffffU RSHIFT shift; \
w1 = *wp1++; \
w2 = *wp2++; \
do \
{ \
t1 = w1 & mask; \
if (__builtin_expect(t1 != w2 RSHIFT shift, 0)) \
{ \
w2 RSHIFT= shift; \
break; \
} \
if (__builtin_expect(((w1 - b1) & ~w1) & (b1 << 7), 0)) \
{ \
/* See comment in assembler below re syndrome on big-endian */\
if ((((w1 - b1) & ~w1) & (b1 << 7)) & mask) \
w2 RSHIFT= shift; \
else \
{ \
w2 = *wp2; \
t1 = w1 RSHIFT (32 - shift); \
w2 = (w2 LSHIFT (32 - shift)) RSHIFT (32 - shift); \
} \
break; \
} \
w2 = *wp2++; \
t1 ^= w1; \
if (__builtin_expect(t1 != w2 LSHIFT (32 - shift), 0)) \
{ \
t1 = w1 >> (32 - shift); \
w2 = (w2 << (32 - shift)) RSHIFT (32 - shift); \
break; \
} \
w1 = *wp1++; \
} while (1)
const unsigned* wp1;
const unsigned* wp2;
unsigned w1, w2;
unsigned mask;
unsigned shift;
unsigned b1 = 0x01010101;
char c1, c2;
unsigned t1;
while (((unsigned) s1) & 3)
{
c1 = *s1++;
c2 = *s2++;
if (c1 == 0 || c1 != c2)
return c1 - (int)c2;
}
wp1 = (unsigned*) (((unsigned)s1) & ~3);
wp2 = (unsigned*) (((unsigned)s2) & ~3);
t1 = ((unsigned) s2) & 3;
if (t1 == 1)
{
body(8);
}
else if (t1 == 2)
{
body(16);
}
else
{
body (24);
}
do
{
#ifdef __ARMEB__
c1 = (char) t1 >> 24;
c2 = (char) w2 >> 24;
#else /* not __ARMEB__ */
c1 = (char) t1;
c2 = (char) w2;
#endif /* not __ARMEB__ */
t1 RSHIFT= 8;
w2 RSHIFT= 8;
} while (c1 != 0 && c1 == c2);
return c1 - c2;
#endif /* 0 */
wp1 .req r0
wp2 .req r1
b1 .req r2
w1 .req r4
w2 .req r5
t1 .req ip
@ r3 is scratch
/* First of all, compare bytes until wp1(sp1) is word-aligned. */
1:
tst wp1, #3
beq 2f
ldrb r2, [wp1], #1
ldrb r3, [wp2], #1
cmp r2, #1
it cs
cmpcs r2, r3
beq 1b
sub r0, r2, r3
RETURN
2:
str r5, [sp, #-4]!
str r4, [sp, #-4]!
//stmfd sp!, {r4, r5}
mov b1, #1
orr b1, b1, b1, lsl #8
orr b1, b1, b1, lsl #16
and t1, wp2, #3
bic wp2, wp2, #3
ldr w1, [wp1], #4
ldr w2, [wp2], #4
cmp t1, #2
beq 2f
bhi 3f
/* Critical inner Loop: Block with 3 bytes initial overlap */
.p2align 2
1:
bic t1, w1, MSB
cmp t1, w2, S2LOMEM #8
sub r3, w1, b1
bic r3, r3, w1
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, S2HIMEM #24
bne 6f
ldr w1, [wp1], #4
b 1b
4:
S2LOMEM w2, w2, #8
b 8f
5:
#ifdef __ARMEB__
/* The syndrome value may contain false ones if the string ends
with the bytes 0x01 0x00 */
tst w1, #0xff000000
itt ne
tstne w1, #0x00ff0000
tstne w1, #0x0000ff00
beq 7f
#else
bics r3, r3, #0xff000000
bne 7f
#endif
ldrb w2, [wp2]
S2LOMEM t1, w1, #24
#ifdef __ARMEB__
lsl w2, w2, #24
#endif
b 8f
6:
S2LOMEM t1, w1, #24
and w2, w2, LSB
b 8f
/* Critical inner Loop: Block with 2 bytes initial overlap */
.p2align 2
2:
S2HIMEM t1, w1, #16
sub r3, w1, b1
S2LOMEM t1, t1, #16
bic r3, r3, w1
cmp t1, w2, S2LOMEM #16
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, S2HIMEM #16
bne 6f
ldr w1, [wp1], #4
b 2b
5:
#ifdef __ARMEB__
/* The syndrome value may contain false ones if the string ends
with the bytes 0x01 0x00 */
tst w1, #0xff000000
it ne
tstne w1, #0x00ff0000
beq 7f
#else
lsls r3, r3, #16
bne 7f
#endif
ldrh w2, [wp2]
S2LOMEM t1, w1, #16
#ifdef __ARMEB__
lsl w2, w2, #16
#endif
b 8f
6:
S2HIMEM w2, w2, #16
S2LOMEM t1, w1, #16
4:
S2LOMEM w2, w2, #16
b 8f
/* Critical inner Loop: Block with 1 byte initial overlap */
.p2align 2
3:
and t1, w1, LSB
cmp t1, w2, S2LOMEM #24
sub r3, w1, b1
bic r3, r3, w1
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, S2HIMEM #8
bne 6f
ldr w1, [wp1], #4
b 3b
4:
S2LOMEM w2, w2, #24
b 8f
5:
/* The syndrome value may contain false ones if the string ends
with the bytes 0x01 0x00 */
tst w1, LSB
beq 7f
ldr w2, [wp2], #4
6:
S2LOMEM t1, w1, #8
bic w2, w2, MSB
b 8f
7:
mov r0, #0
//ldmfd sp!, {r4, r5}
ldr r4, [sp], #4
ldr r5, [sp], #4
RETURN
8:
and r2, t1, LSB
and r0, w2, LSB
cmp r0, #1
it cs
cmpcs r0, r2
itt eq
S2LOMEMEQ t1, t1, #8
S2LOMEMEQ w2, w2, #8
beq 8b
sub r0, r2, r0
//ldmfd sp!, {r4, r5}
ldr r4, [sp], #4
ldr r5, [sp], #4
RETURN
#endif /* !(defined (_ISA_THUMB_2) || defined (_ISA_ARM_6)
defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) ||
(defined (__thumb__) && !defined (__thumb2__))) */

View 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)

View 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;
}

View File

@@ -26,16 +26,12 @@
* SUCH DAMAGE.
*/
#include <private/bionic_asm.h>
#include <linux/err.h>
#include <machine/asm.h>
ENTRY(syscall)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mov r7, r0
mov r0, r1
mov r1, r2
@@ -43,9 +39,8 @@ ENTRY(syscall)
ldmfd ip, {r3, r4, r5, r6}
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
b __set_errno
END(syscall)

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <linux/err.h>
#include <asm/unistd.h>
#include <machine/asm.h>
/* unlike our auto-generated syscall stubs, this code saves lr
on the stack, as well as a few other registers. this makes
our stack unwinder happy, when we generate debug stack
traces after the C library or other parts of the system
abort due to a fatal runtime error (e.g. detection
of a corrupted malloc heap).
*/
ENTRY(tgkill)
stmfd sp!, {r4-r7, ip, lr}
ldr r7, =__NR_tgkill
swi #0
ldmfd sp!, {r4-r7, ip, lr}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(tgkill)

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <linux/err.h>
#include <asm/unistd.h>
#include <machine/asm.h>
/* unlike our auto-generated syscall stubs, this code saves lr
on the stack, as well as a few other registers. this makes
our stack unwinder happy, when we generate debug stack
traces after the C library or other parts of the system
abort due to a fatal runtime error (e.g. detection
of a corrupted malloc heap).
*/
ENTRY(tkill)
stmfd sp!, {r4-r7, ip, lr}
ldr r7, =__NR_tkill
swi #0
ldmfd sp!, {r4-r7, ip, lr}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(tkill)

View File

@@ -1,221 +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}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.save {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)
.save {r0, lr}
.save {r4, r5}
.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"

View File

@@ -1,182 +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}
.save {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)
.save {r0, lr}
.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"

View File

@@ -25,81 +25,122 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* Assumes neon instructions and a cache line size of 64 bytes. */
#include <machine/cpu-features.h>
#include <machine/asm.h>
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This code assumes it is running on a processor that supports all arm v7
* instructions, that supports neon instructions, and that has a 64 byte
* cache line.
*/
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
#include <private/bionic_asm.h>
#include <private/libc_events.h>
.text
.syntax unified
.fpu neon
ENTRY(__memcpy_chk)
cmp r2, r3
bhi __memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
#define CACHE_LINE_SIZE 64
ENTRY(memcpy)
pld [r1, #64]
push {r0, lr}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
.save {r0, lr}
/* start preloading as early as possible */
pld [r1, #(CACHE_LINE_SIZE*0)]
stmfd sp!, {r0, lr}
pld [r1, #(CACHE_LINE_SIZE*1)]
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
/* align destination to cache-line for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 0f
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
ldrmib lr, [r1], #1
strmib lr, [r0], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2:
0: /* preload immediately the next cache line, which we may need */
pld [r1, #(CACHE_LINE_SIZE*0)]
pld [r1, #(CACHE_LINE_SIZE*1)]
/* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
/* Preload all the cache lines we need.
* NOTE: The number of pld below depends on CACHE_LINE_SIZE,
* ideally we would increase the distance in the main loop to
* avoid the goofy code below. In practice this doesn't seem to make
* a big difference.
* NOTE: The value CACHE_LINE_SIZE * 4 was chosen through
* experimentation.
*/
pld [r1, #(CACHE_LINE_SIZE*2)]
pld [r1, #(CACHE_LINE_SIZE*3)]
pld [r1, #(CACHE_LINE_SIZE*4)]
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(CACHE_LINE_SIZE*4)]
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0, :128]!
vst1.8 {d4 - d7}, [r0, :128]!
bhs 1b
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
add r2, r2, #64
subs r2, r2, #32
blo 4f
3: /* 32 bytes at a time. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
bhs 3b
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: movs ip, r2, lsl #31
ldrmib r3, [r1], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strmib r3, [r0], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
END(memcpy)
#define MEMCPY_BASE __memcpy_base
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__memcpy_chk_fail)
// Preserve lr for backtrace.
push {lr}
.save {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"

View File

@@ -1,323 +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)
.save {r0, lr}
.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)
.save {r0, lr}
.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]!
.save {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
strd r6, r7, [sp, #-8]!
.save {r6, r7}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r6, 0
.cfi_rel_offset r7, 0
strd r8, r9, [sp, #-8]!
.save {r8, r9}
.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)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,167 +27,80 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/asm.h>
/*
* Optimized memset() for ARM.
/*
* Optimized memset() for ARM.
*
* memset() returns its first argument.
*/
*/
.fpu neon
.syntax unified
ENTRY(__memset_chk)
cmp r2, r3
bls .L_done
// Preserve lr for backtrace.
.save {lr}
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+8)
END(__memset_chk)
.fpu neon
ENTRY(bzero)
mov r2, r1
mov r1, #0
.L_done:
mov r2, r1
mov r1, #0
// Fall through to memset...
END(bzero)
ENTRY(memset)
.save {r0}
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
// The new algorithm is slower for copies < 16 so use the old
// neon code in that case.
vdup.8 q0, r1
/* do we have at least 16-bytes to write (needed for alignment below) */
cmp r2, #16
blo .L_set_less_than_16_unknown_align
blo 3f
// Use strd which requires an even and odd register so move the
// values so that:
// r0 and r1 contain the memset value
// r2 is the number of bytes to set
// r3 is the destination pointer
mov r3, r0
/* align destination to 16 bytes for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 2f
// Copy the byte value in every byte of r1.
mov r1, r1, lsl #24
orr r1, r1, r1, lsr #8
orr r1, r1, r1, lsr #16
/* write up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
movs ip, r3, lsl #29
bge 1f
.L_check_alignment:
// Align destination to a double word to avoid the strd crossing
// a cache line boundary.
ands ip, r3, #7
bne .L_do_double_word_align
// writes 4 bytes, 32-bits aligned
vst1.32 {d0[0]}, [r0, :32]!
1: bcc 2f
.L_double_word_aligned:
mov r0, r1
// writes 8 bytes, 64-bits aligned
vst1.8 {d0}, [r0, :64]!
2:
/* make sure we have at least 32 bytes to write */
subs r2, r2, #32
blo 2f
vmov q1, q0
subs r2, #64
blo .L_set_less_than_64
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
bhs 1b
1: // Main loop sets 64 bytes at a time.
.irp offset, #0, #8, #16, #24, #32, #40, #48, #56
strd r0, r1, [r3, \offset]
.endr
2: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 3f
add r3, #64
subs r2, #64
bge 1b
.L_set_less_than_64:
// Restore r2 to the count of bytes left to set.
add r2, #64
lsls ip, r2, #27
bcc .L_set_less_than_32
// Set 32 bytes.
.irp offset, #0, #8, #16, #24
strd r0, r1, [r3, \offset]
.endr
add r3, #32
.L_set_less_than_32:
bpl .L_set_less_than_16
// Set 16 bytes.
.irp offset, #0, #8
strd r0, r1, [r3, \offset]
.endr
add r3, #16
.L_set_less_than_16:
// Less than 16 bytes to set.
lsls ip, r2, #29
bcc .L_set_less_than_8
// Set 8 bytes.
strd r0, r1, [r3], #8
.L_set_less_than_8:
bpl .L_set_less_than_4
// Set 4 bytes
str r1, [r3], #4
.L_set_less_than_4:
lsls ip, r2, #31
it ne
strbne r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3]
ldmfd sp!, {r0}
bx lr
.L_do_double_word_align:
rsb ip, ip, #8
sub r2, r2, ip
movs r0, ip, lsl #31
it mi
strbmi r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3], #1
// Dst is at least word aligned by this point.
cmp ip, #4
blo .L_double_word_aligned
str r1, [r3], #4
b .L_double_word_aligned
.L_set_less_than_16_unknown_align:
// Set up to 15 bytes.
vdup.8 d0, r1
// writes 16 bytes, 128-bits aligned
vst1.8 {d0, d1}, [r0, :128]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r0]!
1: bge 2f
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
it mi
strbmi r1, [r0], #1
itt cs
strbcs r1, [r0], #1
strbcs r1, [r0], #1
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
END(memset)
.data
error_string:
.string "memset: prevented write past end of buffer"

View File

@@ -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)

View File

@@ -27,7 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <machine/asm.h>
#ifdef __ARMEB__
#define S2LOMEM lsl
@@ -123,13 +123,8 @@ ENTRY(strcmp)
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
.cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
strd r6, r7, [sp]
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -145,8 +140,19 @@ ENTRY(strcmp)
.macro magic_find_zero_bytes w1
/* Macro to find all-zero bytes in w1, result is in ip. */
#if (defined (__ARM_FEATURE_DSP))
uadd8 ip, \w1, r6
sel ip, r7, r6
#else /* not defined (__ARM_FEATURE_DSP) */
/* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
Coincidently, these processors only have Thumb-2 mode, where we can use the
the (large) magic constant available directly as an immediate in instructions.
Note that we cannot use the magic constant in ARM mode, where we need
to create the constant in a register. */
sub ip, \w1, #0x01010101
bic ip, ip, \w1
and ip, ip, #0x80808080
#endif /* not defined (__ARM_FEATURE_DSP) */
.endm /* magic_find_zero_bytes */
.macro setup_return w1 w2
@@ -165,13 +171,12 @@ ENTRY(strcmp)
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
bne .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -184,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -199,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -266,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -292,47 +297,47 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_strcmp_unaligned:
strcmp_unaligned:
/* r0 is word-aligned, r1 is at offset ip from a word. */
/* Align r1 to the (previous) word-boundary. */
bic r1, r1, #3
/* Unaligned comparison word by word using LDRs. */
cmp ip, #2
beq .L_miscmp_word_16 /* If ip == 2. */
bge .L_miscmp_word_24 /* If ip == 3. */
beq miscmp_word_16 /* If ip == 2. */
bge miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
.L_miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -344,16 +349,11 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
m_cbz reg=r0, label=.L_compute_return_value
m_cbz reg=r0, label=compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -361,7 +361,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.

View File

@@ -1,451 +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_copy_byte reg, cmd, label
ldrb \reg, [r1], #1
strb \reg, [r0], #1
\cmd \reg, \label
.endm // m_copy_byte
ENTRY(strcpy)
// 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=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:
pld [r1, #0]
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
END(strcpy)

View File

@@ -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)

View File

@@ -1,10 +1,5 @@
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/memset.S \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/strcmp.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/strlen.S \
arch-arm/cortex-a15/bionic/__strcat_chk.S \
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
bionic/memmove.c \
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a15/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a15/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a15/bionic/strcmp.S)
include bionic/libc/arch-arm/generic/generic.mk

View File

@@ -1 +0,0 @@
include bionic/libc/arch-arm/cortex-a15/cortex-a15.mk

View File

@@ -1,224 +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}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.save {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)
.save {r0, lr}
.save {r4, r5}
.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"

View File

@@ -1,187 +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}
.save {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)
.save {r0, lr}
.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"

View File

@@ -26,8 +26,8 @@
* SUCH DAMAGE.
*/
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/cpu-features.h>
#include <machine/asm.h>
/*
* This code assumes it is running on a processor that supports all arm v7
@@ -35,50 +35,177 @@
* cache line.
*/
.syntax unified
.text
.fpu neon
.thumb
.thumb_func
ENTRY(__memcpy_chk)
cmp r2, r3
bhi __memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
#define CACHE_LINE_SIZE 32
ENTRY(memcpy)
pld [r1, #0]
stmfd sp!, {r0, lr}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
pld [r1, #64]
.save {r0, lr}
/* start preloading as early as possible */
pld [r1, #(CACHE_LINE_SIZE * 0)]
stmfd sp!, {r0, lr}
pld [r1, #(CACHE_LINE_SIZE * 2)]
// Check so divider is at least 16 bytes, needed for alignment code.
cmp r2, #16
blo 5f
/* check if buffers are aligned. If so, run arm-only version */
eor r3, r0, r1
ands r3, r3, #0x3
beq 11f
/* Check the upper size limit for Neon unaligned memory access in memcpy */
cmp r2, #224
blo 3f
/* align destination to 16 bytes for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 3f
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
ldrmib lr, [r1], #1
strmib lr, [r0], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld1.32 {d0[0]}, [r1]!
vst1.32 {d0[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2:
/* preload immediately the next cache line, which we may need */
pld [r1, #(CACHE_LINE_SIZE * 0)]
pld [r1, #(CACHE_LINE_SIZE * 2)]
3:
/* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
/* preload all the cache lines we need */
pld [r1, #(CACHE_LINE_SIZE * 4)]
pld [r1, #(CACHE_LINE_SIZE * 6)]
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(CACHE_LINE_SIZE * 6)]
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0]!
vst1.8 {d4 - d7}, [r0]!
bhs 1b
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
add r2, r2, #64
subs r2, r2, #32
blo 4f
3: /* 32 bytes at a time. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0]!
bhs 3b
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld1.32 {d0[0]}, [r1]!
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
ldrmib r3, [r1], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strmib r3, [r0], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
11:
/* Simple arm-only copy loop to handle aligned copy operations */
stmfd sp!, {r4, r5, r6, r7, r8}
pld [r1, #(CACHE_LINE_SIZE * 4)]
/* Check alignment */
rsb r3, r1, #0
ands r3, #3
beq 2f
/* align source to 32 bits. We need to insert 2 instructions between
* a ldr[b|h] and str[b|h] because byte and half-word instructions
* stall 2 cycles.
*/
movs r12, r3, lsl #31
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
ldrmib r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb r5, [r1], #1
strmib r3, [r0], #1
strcsb r4, [r0], #1
strcsb r5, [r0], #1
2:
subs r2, r2, #64
blt 4f
3: /* Main copy loop, copying 64 bytes at a time */
pld [r1, #(CACHE_LINE_SIZE * 8)]
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
subs r2, r2, #64
bge 3b
4: /* Check if there are > 32 bytes left */
adds r2, r2, #64
subs r2, r2, #32
blt 5f
/* Copy 32 bytes */
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
subs r2, #32
5: /* Handle any remaining bytes */
adds r2, #32
beq 6f
movs r12, r2, lsl #28
ldmcsia r1!, {r3, r4, r5, r6} /* 16 bytes */
ldmmiia r1!, {r7, r8} /* 8 bytes */
stmcsia r0!, {r3, r4, r5, r6}
stmmiia r0!, {r7, r8}
movs r12, r2, lsl #30
ldrcs r3, [r1], #4 /* 4 bytes */
ldrmih r4, [r1], #2 /* 2 bytes */
strcs r3, [r0], #4
strmih r4, [r0], #2
tst r2, #0x1
ldrneb r3, [r1] /* last byte */
strneb r3, [r0]
6:
ldmfd sp!, {r4, r5, r6, r7, r8}
ldmfd sp!, {r0, pc}
END(memcpy)
#define MEMCPY_BASE __memcpy_base
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__memcpy_chk_fail)
// Preserve lr for backtrace.
push {lr}
.save {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"

View File

@@ -1,226 +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)
.save {r0, lr}
.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)
.save {r0, lr}
.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}
.save {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)

View File

@@ -26,8 +26,8 @@
* SUCH DAMAGE.
*/
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/cpu-features.h>
#include <machine/asm.h>
/*
* This code assumes it is running on a processor that supports all arm v7
@@ -36,45 +36,19 @@
.fpu neon
ENTRY(__memset_chk)
cmp r2, r3
bls .L_done
// Preserve lr for backtrace.
push {lr}
.save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+8)
END(__memset_chk)
ENTRY(bzero)
mov r2, r1
mov r1, #0
.L_done:
// Fall through to memset...
END(bzero)
/* memset() returns its first argument. */
ENTRY(memset)
// The neon memset only wins for less than 132.
# The neon memset only wins for less than 132.
cmp r2, #132
bhi __memset_large_copy
bhi 11f
stmfd sp!, {r0}
.save {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
stmfd sp!, {r0}
vdup.8 q0, r1
@@ -107,22 +81,13 @@ ENTRY(memset)
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
END(memset)
ENTRY_PRIVATE(__memset_large_copy)
11:
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
stmfd sp!, {r0, r4-r7, lr}
.save {r0, r4-r7, lr}
.cfi_def_cfa_offset 24
.cfi_rel_offset r0, 0
.cfi_rel_offset r4, 4
.cfi_rel_offset r5, 8
.cfi_rel_offset r6, 12
.cfi_rel_offset r7, 16
.cfi_rel_offset lr, 20
.save {r0, r4-r7, lr}
stmfd sp!, {r0, r4-r7, lr}
rsb r3, r0, #0
ands r3, r3, #3
cmp r3, r2
@@ -184,8 +149,4 @@ ENTRY_PRIVATE(__memset_large_copy)
strcsb r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(__memset_large_copy)
.data
error_string:
.string "memset: prevented write past end of buffer"
END(memset)

View File

@@ -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)

View File

@@ -27,7 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <machine/asm.h>
#ifdef __ARMEB__
#define S2LOMEM lsl
@@ -123,13 +123,8 @@ ENTRY(strcmp)
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
.cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
strd r6, r7, [sp]
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -145,8 +140,19 @@ ENTRY(strcmp)
.macro magic_find_zero_bytes w1
/* Macro to find all-zero bytes in w1, result is in ip. */
#if (defined (__ARM_FEATURE_DSP))
uadd8 ip, \w1, r6
sel ip, r7, r6
#else /* not defined (__ARM_FEATURE_DSP) */
/* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
Coincidently, these processors only have Thumb-2 mode, where we can use the
the (large) magic constant available directly as an immediate in instructions.
Note that we cannot use the magic constant in ARM mode, where we need
to create the constant in a register. */
sub ip, \w1, #0x01010101
bic ip, ip, \w1
and ip, ip, #0x80808080
#endif /* not defined (__ARM_FEATURE_DSP) */
.endm /* magic_find_zero_bytes */
.macro setup_return w1 w2
@@ -165,13 +171,12 @@ ENTRY(strcmp)
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
bne .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -184,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -199,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -266,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -292,33 +297,33 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -330,16 +335,11 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
m_cbz reg=r0, label=.L_compute_return_value
m_cbz reg=r0, label=compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -347,7 +347,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -367,7 +367,7 @@ ENTRY(strcmp)
* bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
* version of the code.
*/
.L_strcmp_unaligned:
strcmp_unaligned:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -520,11 +520,6 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
bx lr

View File

@@ -1,456 +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_copy_byte reg, cmd, label
ldrb \reg, [r1], #1
strb \reg, [r0], #1
\cmd \reg, \label
.endm // m_copy_byte
ENTRY(strcpy)
// Unroll the first 8 bytes that will be copied.
m_push
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
END(strcpy)

View File

@@ -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)

View File

@@ -1,10 +1,5 @@
libc_bionic_src_files_arm += \
arch-arm/cortex-a9/bionic/memcpy.S \
arch-arm/cortex-a9/bionic/memset.S \
arch-arm/cortex-a9/bionic/strcat.S \
arch-arm/cortex-a9/bionic/strcmp.S \
arch-arm/cortex-a9/bionic/strcpy.S \
arch-arm/cortex-a9/bionic/strlen.S \
arch-arm/cortex-a9/bionic/__strcat_chk.S \
arch-arm/cortex-a9/bionic/__strcpy_chk.S \
bionic/memmove.c \
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/cortex-a9/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/cortex-a9/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a9/bionic/strcmp.S)
include bionic/libc/arch-arm/generic/generic.mk

View File

@@ -1,221 +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}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.save {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)
.save {r0, lr}
.save {r4, r5}
.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"

View File

@@ -1,182 +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}
.save {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)
.save {r0, lr}
.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"

View File

@@ -1,105 +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}
.save {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}
.save {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"

View File

@@ -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)

View File

@@ -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)

View File

@@ -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"

View File

@@ -1,13 +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/strcat.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/strlen.S \
arch-arm/cortex-a15/bionic/strcmp.S \

View File

@@ -27,8 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/asm.h>
/*
* Optimized memcpy() for ARM.
@@ -37,13 +36,6 @@
* so we have to preserve R0.
*/
ENTRY(__memcpy_chk)
cmp r2, r3
bgt fortify_check_failed
// 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
@@ -57,9 +49,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
@@ -147,7 +139,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
@@ -268,7 +260,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
@@ -295,7 +287,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
@@ -322,7 +314,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
@@ -385,20 +377,4 @@ copy_last_3_and_return:
add sp, sp, #28
ldmfd sp!, {r0, r4, lr}
bx lr
// Only reached when the __memcpy_chk check fails.
fortify_check_failed:
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)
.data
error_string:
.string "memcpy: prevented write past end of buffer"

View File

@@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/asm.h>
/*
* Optimized memset() for ARM.
@@ -35,28 +34,9 @@
* 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)
@@ -127,7 +107,3 @@ ENTRY(memset)
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(memset)
.data
error_string:
.string "memset: prevented write past end of buffer"

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -1,10 +1,3 @@
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/strcat.c \
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/generic/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/generic/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/generic/bionic/strcmp.S)

View File

@@ -0,0 +1,110 @@
/* $OpenBSD: _types.h,v 1.3 2006/02/14 18:12:58 miod Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)types.h 8.3 (Berkeley) 1/5/94
* @(#)ansi.h 8.2 (Berkeley) 1/4/94
*/
#ifndef _ARM__TYPES_H_
#define _ARM__TYPES_H_
/* 7.18.1.1 Exact-width integer types */
typedef __signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short __int16_t;
typedef unsigned short __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
/* LONGLONG */
typedef long long __int64_t;
/* LONGLONG */
typedef unsigned long long __uint64_t;
/* 7.18.1.2 Minimum-width integer types */
typedef __int8_t __int_least8_t;
typedef __uint8_t __uint_least8_t;
typedef __int16_t __int_least16_t;
typedef __uint16_t __uint_least16_t;
typedef __int32_t __int_least32_t;
typedef __uint32_t __uint_least32_t;
typedef __int64_t __int_least64_t;
typedef __uint64_t __uint_least64_t;
/* 7.18.1.3 Fastest minimum-width integer types */
typedef __int32_t __int_fast8_t;
typedef __uint32_t __uint_fast8_t;
typedef __int32_t __int_fast16_t;
typedef __uint32_t __uint_fast16_t;
typedef __int32_t __int_fast32_t;
typedef __uint32_t __uint_fast32_t;
typedef __int64_t __int_fast64_t;
typedef __uint64_t __uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers */
typedef int __intptr_t;
typedef unsigned int __uintptr_t;
/* 7.18.1.5 Greatest-width integer types */
typedef __int64_t __intmax_t;
typedef __uint64_t __uintmax_t;
/* Register size */
typedef __int32_t __register_t;
/* VM system types */
typedef unsigned long __vaddr_t;
typedef unsigned long __paddr_t;
typedef unsigned long __vsize_t;
typedef unsigned long __psize_t;
/* Standard system types */
typedef int __clock_t;
typedef int __clockid_t;
typedef double __double_t;
typedef float __float_t;
typedef long __ptrdiff_t;
typedef int __time_t;
typedef int __timer_t;
#if defined(__GNUC__) && __GNUC__ >= 3
typedef __builtin_va_list __va_list;
#else
typedef char * __va_list;
#endif
/* Wide character support types */
#ifndef __cplusplus
typedef int __wchar_t;
#endif
typedef int __wint_t;
typedef int __rune_t;
typedef void * __wctrans_t;
typedef void * __wctype_t;
#endif /* _ARM__TYPES_H_ */

View File

@@ -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_ */

View 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_ */

View File

@@ -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 */

View File

@@ -33,6 +33,15 @@
#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.
*
@@ -46,13 +55,13 @@
*/
#define __swap16md(x) ({ \
register u_int16_t _x = (x); \
__asm__ __volatile__("rev16 %0, %0" : "+l" (_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)); \
__asm volatile ("rev %0, %0" : "+l" (_x)); \
_x; \
})
@@ -65,6 +74,7 @@
/* Tell sys/endian.h we have MD variants of the swap macros. */
#define MD_SWAP
#endif /* __ARM_ARCH__ */
#endif /* __GNUC__ */
#if defined(__ARMEB__)

View 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__ */

View 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

View File

@@ -0,0 +1,42 @@
/*
* 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.
*/
#ifndef _ARCH_ARM_KERNEL_H
#define _ARCH_ARM_KERNEL_H
/* this file contains kernel-specific definitions that were optimized out of
our processed kernel headers, but still useful nonetheless... */
typedef unsigned long __kernel_blkcnt_t;
typedef unsigned long __kernel_blksize_t;
/* these aren't really defined by the kernel headers though... */
typedef unsigned long __kernel_fsblkcnt_t;
typedef unsigned long __kernel_fsfilcnt_t;
typedef unsigned int __kernel_id_t;
#endif /* _ARCH_ARM_KERNEL_H */

View File

@@ -0,0 +1,63 @@
/* $OpenBSD: limits.h,v 1.3 2006/01/06 22:48:46 millert Exp $ */
/* $NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $ */
/*
* Copyright (c) 1988 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.
*
* from: @(#)limits.h 7.2 (Berkeley) 6/28/90
*/
#ifndef _ARM32_LIMITS_H_
#define _ARM32_LIMITS_H_
#include <sys/cdefs.h>
#define MB_LEN_MAX 1 /* no multibyte characters */
#ifndef SIZE_MAX
#define SIZE_MAX UINT_MAX /* max value for a size_t */
#endif
#ifndef SSIZE_MAX
#define SSIZE_MAX INT_MAX /* max value for a ssize_t */
#endif
#if __BSD_VISIBLE
#define SIZE_T_MAX UINT_MAX /* max value for a size_t (historic) */
#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */
#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */
#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */
#endif /* __BSD_VISIBLE */
#define LONGLONG_BIT 64
#define LONGLONG_MIN (-9223372036854775807LL-1)
#define LONGLONG_MAX 9223372036854775807LL
#define ULONGLONG_MAX 18446744073709551615ULL
#endif /* _ARM32_LIMITS_H_ */

View File

@@ -1,219 +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}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.save {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)
.save {r0, lr}
.save {r4, r5}
.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"

View File

@@ -1,182 +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}
.save {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)
.save {r0, lr}
.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"

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,8 +28,8 @@
/* Assumes neon instructions and a cache line size of 32 bytes. */
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/cpu-features.h>
#include <machine/asm.h>
/*
* This code assumes it is running on a processor that supports all arm v7
@@ -38,49 +38,109 @@
*/
.text
.syntax unified
.fpu neon
.thumb
.thumb_func
ENTRY(__memcpy_chk)
cmp r2, r3
bhi __memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
#define CACHE_LINE_SIZE 32
ENTRY(memcpy)
pld [r1, #64]
stmfd sp!, {r0, lr}
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
.save {r0, lr}
/* start preloading as early as possible */
pld [r1, #(CACHE_LINE_SIZE*0)]
stmfd sp!, {r0, lr}
pld [r1, #(CACHE_LINE_SIZE*2)]
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
/* align destination to cache-line for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 0f
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
ldrmib lr, [r1], #1
strmib lr, [r0], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2:
0: /* preload immediately the next cache line, which we may need */
pld [r1, #(CACHE_LINE_SIZE*0)]
pld [r1, #(CACHE_LINE_SIZE*2)]
/* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
/* Preload all the cache lines we need.
* NOTE: The number of pld below depends on CACHE_LINE_SIZE,
* ideally we would increase the distance in the main loop to
* avoid the goofy code below. In practice this doesn't seem to make
* a big difference.
* NOTE: The value CACHE_LINE_SIZE * 8 was chosen through
* experimentation.
*/
pld [r1, #(CACHE_LINE_SIZE*4)]
pld [r1, #(CACHE_LINE_SIZE*6)]
pld [r1, #(CACHE_LINE_SIZE*8)]
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(CACHE_LINE_SIZE*8)]
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0, :128]!
vst1.8 {d4 - d7}, [r0, :128]!
bhs 1b
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
add r2, r2, #64
subs r2, r2, #32
blo 4f
3: /* 32 bytes at a time. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
bhs 3b
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: movs ip, r2, lsl #31
ldrmib r3, [r1], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strmib r3, [r0], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
END(memcpy)
#define MEMCPY_BASE __memcpy_base
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__memcpy_chk_fail)
// Preserve lr for backtrace.
push {lr}
.save {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"

View File

@@ -1,124 +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.
*/
/*
* 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.
*/
// Assumes neon instructions and a cache line size of 32 bytes.
ENTRY_PRIVATE(MEMCPY_BASE)
.save {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
/* align destination to cache-line for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 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, destination 32-bits aligned
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2: /* 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, #(32*8)]
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 4f
/* Copy 32 bytes. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
sub r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: movs ip, r2, lsl #31
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)

View File

@@ -27,8 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include <machine/asm.h>
/*
* This code assumes it is running on a processor that supports all arm v7
@@ -38,41 +37,15 @@
.fpu neon
ENTRY(__memset_chk)
cmp r2, r3
bls .L_done
// Preserve lr for backtrace.
.save {lr}
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)
.save {r0}
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
vdup.8 q0, r1
@@ -106,7 +79,3 @@ ENTRY(memset)
ldmfd sp!, {r0}
bx lr
END(memset)
.data
error_string:
.string "memset: prevented write past end of buffer"

View File

@@ -27,7 +27,7 @@
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <machine/asm.h>
#ifdef __ARMEB__
#define S2LOMEM lsl
@@ -123,13 +123,8 @@ ENTRY(strcmp)
.macro init
/* Macro to save temporary registers and prepare magic values. */
subs sp, sp, #16
.cfi_def_cfa_offset 16
strd r4, r5, [sp, #8]
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
strd r6, r7, [sp]
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mvn r6, #0 /* all F */
mov r7, #0 /* all 0 */
.endm /* init */
@@ -145,8 +140,19 @@ ENTRY(strcmp)
.macro magic_find_zero_bytes w1
/* Macro to find all-zero bytes in w1, result is in ip. */
#if (defined (__ARM_FEATURE_DSP))
uadd8 ip, \w1, r6
sel ip, r7, r6
#else /* not defined (__ARM_FEATURE_DSP) */
/* __ARM_FEATURE_DSP is not defined for some Cortex-M processors.
Coincidently, these processors only have Thumb-2 mode, where we can use the
the (large) magic constant available directly as an immediate in instructions.
Note that we cannot use the magic constant in ARM mode, where we need
to create the constant in a register. */
sub ip, \w1, #0x01010101
bic ip, ip, \w1
and ip, ip, #0x80808080
#endif /* not defined (__ARM_FEATURE_DSP) */
.endm /* magic_find_zero_bytes */
.macro setup_return w1 w2
@@ -165,13 +171,12 @@ ENTRY(strcmp)
/* Are both strings double-word aligned? */
orr ip, r0, r1
tst ip, #7
bne .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -184,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq word_aligned_r0
/* Fast compare byte by byte until the first string is word-aligned. */
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
@@ -199,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq doubleword_aligned_r0
/* If r0 is not double-word aligned yet, align it by loading
and comparing the next word from each string. */
ldr r2, [r0], #4
ldr r4, [r1], #4
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -266,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -292,46 +297,46 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_strcmp_unaligned:
strcmp_unaligned:
/* r0 is word-aligned, r1 is at offset ip from a word. */
/* Align r1 to the (previous) word-boundary. */
bic r1, r1, #3
/* Unaligned comparison word by word using LDRs. */
cmp ip, #2
beq .L_miscmp_word_16 /* If ip == 2. */
bge .L_miscmp_word_24 /* If ip == 3. */
beq miscmp_word_16 /* If ip == 2. */
bge miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -343,16 +348,11 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
/* There is a zero or a different byte between r1 and r2. */
/* r0 contains a mask of all-zero bytes in r1. */
/* Using r0 and not ip here because cbz requires low register. */
m_cbz reg=r0, label=.L_compute_return_value
m_cbz reg=r0, label=compute_return_value
clz r0, r0
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
rsb r0, r0, #24
@@ -360,7 +360,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -380,7 +380,7 @@ ENTRY(strcmp)
* previous version. See bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S
* for the unedited version of this code.
*/
.L_miscmp_word_16:
miscmp_word_16:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -453,11 +453,6 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
bx lr
@@ -477,11 +472,6 @@ ENTRY(strcmp)
ldrd r6, r7, [sp]
ldrd r4, r5, [sp, #8]
adds sp, sp, #16
.cfi_def_cfa_offset 0
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
bx lr
END(strcmp)

View File

@@ -1,13 +1,5 @@
libc_bionic_src_files_arm += \
arch-arm/krait/bionic/memcpy.S \
arch-arm/krait/bionic/memset.S \
arch-arm/krait/bionic/strcmp.S \
arch-arm/krait/bionic/__strcat_chk.S \
arch-arm/krait/bionic/__strcpy_chk.S \
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/krait/bionic/memcpy.S)
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/krait/bionic/memset.S)
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/krait/bionic/strcmp.S)
# Use cortex-a15 versions of strcat/strcpy/strlen and standard memmove
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/strlen.S \
bionic/memmove.c \
include bionic/libc/arch-arm/generic/generic.mk

Some files were not shown because too many files have changed in this diff Show More