Compare commits
2 Commits
android-we
...
android-5.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
023c327cbb | ||
![]() |
3da136aa47 |
12
ABI-bugs.txt
Normal file
12
ABI-bugs.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
KNOWN ABI BUGS
|
||||
--------------
|
||||
|
||||
time_t is 32-bit. http://b/5819737
|
||||
|
||||
off_t is 32-bit. There is off64_t, but no _FILE_OFFSET_BITS support.
|
||||
|
||||
sigset_t is too small on ARM and x86 (but correct on MIPS), so support
|
||||
for real-time signals is broken. http://b/5828899
|
||||
|
||||
atexit(3) handlers registered by a shared library aren't called on
|
||||
dlclose(3); this only affects ARM. http://b/4998315
|
@@ -1,2 +0,0 @@
|
||||
set noparent
|
||||
filter=-build/header_guard,-runtime/int,-readability/function
|
@@ -4,52 +4,40 @@ Working on bionic
|
||||
What are the big pieces of bionic?
|
||||
----------------------------------
|
||||
|
||||
#### libc/ --- libc.so, libc.a
|
||||
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.
|
||||
|
||||
The C library. Stuff like `fopen(3)` and `kill(2)`.
|
||||
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).
|
||||
|
||||
#### 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.
|
||||
tests/ --- unit tests
|
||||
The tests/ directory contains unit tests. Roughly arranged as one file per
|
||||
publicly-exported header file.
|
||||
benchmarks/ --- benchmarks
|
||||
The benchmarks/ directory contains benchmarks.
|
||||
|
||||
|
||||
What's in libc/?
|
||||
----------------
|
||||
|
||||
<pre>
|
||||
libc/
|
||||
arch-arm/
|
||||
arch-arm64/
|
||||
@@ -133,7 +121,6 @@ libc/
|
||||
zoneinfo/
|
||||
# Android-format time zone data.
|
||||
# See 'Updating tzdata' later.
|
||||
</pre>
|
||||
|
||||
|
||||
Adding system calls
|
||||
@@ -173,101 +160,3 @@ This is fully automated:
|
||||
|
||||
1. Run update-tzdata.py.
|
||||
|
||||
|
||||
Verifying changes
|
||||
-----------------
|
||||
|
||||
If you make a change that is likely to have a wide effect on the tree (such as a
|
||||
libc header change), you should run `make checkbuild`. A regular `make` will
|
||||
_not_ build the entire tree; just the minimum number of projects that are
|
||||
required for the device. Tests, additional developer tools, and various other
|
||||
modules will not be built. Note that `make checkbuild` will not be complete
|
||||
either, as `make tests` covers a few additional modules, but generally speaking
|
||||
`make checkbuild` is enough.
|
||||
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
|
||||
The tests are all built from the tests/ directory.
|
||||
|
||||
### Device tests
|
||||
|
||||
$ mma
|
||||
$ adb sync
|
||||
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
|
||||
$ adb shell \
|
||||
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
|
||||
# Only for 64-bit targets
|
||||
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
|
||||
$ adb shell \
|
||||
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
|
||||
|
||||
### Host tests
|
||||
|
||||
The host tests require that you have `lunch`ed either an x86 or x86_64 target.
|
||||
|
||||
$ mma
|
||||
$ mm bionic-unit-tests-run-on-host32
|
||||
$ mm bionic-unit-tests-run-on-host64 # For 64-bit *targets* only.
|
||||
|
||||
### Against glibc
|
||||
|
||||
As a way to check that our tests do in fact test the correct behavior (and not
|
||||
just the behavior we think is correct), it is possible to run the tests against
|
||||
the host's glibc. The executables are already in your path.
|
||||
|
||||
$ mma
|
||||
$ bionic-unit-tests-glibc32
|
||||
$ bionic-unit-tests-glibc64
|
||||
|
||||
|
||||
Gathering test coverage
|
||||
-----------------------
|
||||
|
||||
For either host or target coverage, you must first:
|
||||
|
||||
* `$ export NATIVE_COVERAGE=true`
|
||||
* Note that the build system is ignorant to this flag being toggled, i.e. if
|
||||
you change this flag, you will have to manually rebuild bionic.
|
||||
* Set `bionic_coverage=true` in `libc/Android.mk` and `libm/Android.mk`.
|
||||
|
||||
### Coverage from device tests
|
||||
|
||||
$ mma
|
||||
$ adb sync
|
||||
$ adb shell \
|
||||
GCOV_PREFIX=/data/local/tmp/gcov \
|
||||
GCOV_PREFIX_STRIP=`echo $ANDROID_BUILD_TOP | grep -o / | wc -l` \
|
||||
/data/nativetest/bionic-unit-tests/bionic-unit-tests32
|
||||
$ acov
|
||||
|
||||
`acov` will pull all coverage information from the device, push it to the right
|
||||
directories, run `lcov`, and open the coverage report in your browser.
|
||||
|
||||
### Coverage from host tests
|
||||
|
||||
First, build and run the host tests as usual (see above).
|
||||
|
||||
$ croot
|
||||
$ lcov -c -d $ANDROID_PRODUCT_OUT -o coverage.info
|
||||
$ genhtml -o covreport coverage.info # or lcov --list coverage.info
|
||||
|
||||
The coverage report is now available at `covreport/index.html`.
|
||||
|
||||
|
||||
LP32 ABI bugs
|
||||
-------------
|
||||
|
||||
This probably belongs in the NDK documentation rather than here, but these
|
||||
are the known ABI bugs in LP32:
|
||||
|
||||
* `time_t` is 32-bit. <http://b/5819737>
|
||||
|
||||
* `off_t` is 32-bit. There is `off64_t`, but no `_FILE_OFFSET_BITS` support.
|
||||
Many of the `off64_t` functions are missing in older releases, and
|
||||
stdio uses 32-bit offsets, so there's no way to fully implement
|
||||
`_FILE_OFFSET_BITS`.
|
||||
|
||||
* `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
|
||||
for real-time signals is broken. <http://b/5828899>
|
@@ -14,56 +14,23 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
ifneq ($(BUILD_TINY_ANDROID), true)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Benchmarks library, usable by projects outside this directory.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
benchmark_cflags := \
|
||||
-O2 \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Wunused \
|
||||
|
||||
benchmark_cppflags := \
|
||||
-std=gnu++11 \
|
||||
|
||||
benchmarklib_src_files := \
|
||||
Benchmark.cpp \
|
||||
utils.cpp \
|
||||
main.cpp \
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libbenchmark
|
||||
LOCAL_CFLAGS := $(benchmark_cflags)
|
||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
|
||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
|
||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
|
||||
LOCAL_STATIC_LIBRARIES := libbase
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# Only supported on linux systems.
|
||||
ifeq ($(HOST_OS),linux)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libbenchmark
|
||||
LOCAL_CFLAGS := $(benchmark_cflags)
|
||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
|
||||
LOCAL_SRC_FILES := $(benchmarklib_src_files)
|
||||
LOCAL_C_INCLUDES := $(benchmark_c_includes)
|
||||
LOCAL_MULTILIB := both
|
||||
LOCAL_STATIC_LIBRARIES := libbase
|
||||
include $(BUILD_HOST_STATIC_LIBRARY)
|
||||
|
||||
endif
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Benchmarks.
|
||||
# -----------------------------------------------------------------------------
|
||||
benchmark_src_files := \
|
||||
|
||||
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 \
|
||||
@@ -74,58 +41,40 @@ benchmark_src_files := \
|
||||
unistd_benchmark.cpp \
|
||||
|
||||
# Build benchmarks for the device (with bionic's .so). Run with:
|
||||
# adb shell bionic-benchmarks32
|
||||
# adb shell bionic-benchmarks64
|
||||
# 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_CFLAGS := $(benchmark_cflags)
|
||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
|
||||
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)
|
||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
# We don't build a static benchmark executable because it's not usually
|
||||
# useful. If you're trying to run the current benchmarks on an older
|
||||
# release, it's (so far at least) always because you want to measure the
|
||||
# performance of the old release's libc, and a static benchmark isn't
|
||||
# going to let you do that.
|
||||
|
||||
# Only supported on linux systems.
|
||||
ifeq ($(HOST_OS),linux)
|
||||
|
||||
# Build benchmarks for the host (against glibc!). Run with:
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := bionic-benchmarks-glibc
|
||||
LOCAL_MODULE_STEM_32 := bionic-benchmarks-glibc32
|
||||
LOCAL_MODULE_STEM_64 := bionic-benchmarks-glibc64
|
||||
LOCAL_MULTILIB := both
|
||||
LOCAL_CFLAGS := $(benchmark_cflags)
|
||||
LOCAL_CPPFLAGS := $(benchmark_cppflags)
|
||||
LOCAL_LDFLAGS := -lrt
|
||||
LOCAL_SRC_FILES := $(benchmark_src_files)
|
||||
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
|
||||
include $(BUILD_HOST_EXECUTABLE)
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
|
||||
include $(LOCAL_PATH)/../build/run-on-host.mk
|
||||
ifeq ($(TARGET_ARCH),x86)
|
||||
LINKER = linker
|
||||
NATIVE_SUFFIX=32
|
||||
else
|
||||
LINKER = linker64
|
||||
NATIVE_SUFFIX=64
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
|
||||
bionic-benchmarks-run-on-host32: bionic-benchmarks bionic-prepare-run-on-host
|
||||
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) \
|
||||
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks32 $(BIONIC_BENCHMARKS_FLAGS)
|
||||
endif
|
||||
LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
|
||||
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks$(NATIVE_SUFFIX) $(BIONIC_BENCHMARKS_FLAGS)
|
||||
endif # linux-x86
|
||||
|
||||
ifeq ($(TARGET_IS_64_BIT),true)
|
||||
bionic-benchmarks-run-on-host64: bionic-benchmarks bionic-prepare-run-on-host
|
||||
ANDROID_DATA=$(TARGET_OUT_DATA) \
|
||||
ANDROID_ROOT=$(TARGET_OUT) \
|
||||
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks64 $(BIONIC_BENCHMARKS_FLAGS)
|
||||
endif
|
||||
|
||||
endif
|
||||
endif # !BUILD_TINY_ANDROID
|
||||
|
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
static uint64_t NanoTime() {
|
||||
struct timespec t;
|
||||
t.tv_sec = t.tv_nsec = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
|
||||
}
|
||||
|
||||
bool Benchmark::header_printed_;
|
||||
|
||||
std::vector<Benchmark*>& Benchmark::List() {
|
||||
static std::vector<Benchmark*> list;
|
||||
return list;
|
||||
}
|
||||
|
||||
int Benchmark::MaxNameColumnWidth() {
|
||||
size_t max = 20;
|
||||
for (auto& benchmark : List()) {
|
||||
max = std::max(max, benchmark->NameColumnWidth());
|
||||
}
|
||||
return static_cast<int>(max);
|
||||
}
|
||||
|
||||
size_t Benchmark::RunAll(std::vector<regex_t*>& regs) {
|
||||
size_t benchmarks_run = 0;
|
||||
header_printed_ = false;
|
||||
for (auto& benchmark : List()) {
|
||||
benchmarks_run += benchmark->RunAllArgs(regs);
|
||||
}
|
||||
return benchmarks_run;
|
||||
}
|
||||
|
||||
void Benchmark::PrintHeader() {
|
||||
if (!header_printed_) {
|
||||
printf("%-*s %10s %10s\n", MaxNameColumnWidth(), "", "iterations", "ns/op");
|
||||
header_printed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool BenchmarkT<T>::ShouldRun(std::vector<regex_t*>& regs, T arg) {
|
||||
if (regs.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& re : regs) {
|
||||
if (regexec(re, GetNameStr(arg).c_str(), 0, NULL, 0) != REG_NOMATCH) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Benchmark::StopBenchmarkTiming() {
|
||||
if (start_time_ns_ != 0) {
|
||||
total_time_ns_ += NanoTime() - start_time_ns_;
|
||||
}
|
||||
start_time_ns_ = 0;
|
||||
}
|
||||
|
||||
void Benchmark::StartBenchmarkTiming() {
|
||||
if (start_time_ns_ == 0) {
|
||||
start_time_ns_ = NanoTime();
|
||||
}
|
||||
}
|
||||
|
||||
std::string BenchmarkWithoutArg::GetNameStr(void*) {
|
||||
return Name();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string BenchmarkWithArg<int>::GetNameStr(int arg) {
|
||||
return Name() + "/" + PrettyInt(arg, 2);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string BenchmarkWithArg<double>::GetNameStr(double arg) {
|
||||
return Name() + "/" + android::base::StringPrintf("%0.6f", arg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BenchmarkT<T>::RunWithArg(T arg) {
|
||||
int new_iterations = 1;
|
||||
int iterations;
|
||||
while (new_iterations < 1e8) {
|
||||
bytes_processed_ = 0;
|
||||
total_time_ns_ = 0;
|
||||
start_time_ns_ = 0;
|
||||
|
||||
iterations = new_iterations;
|
||||
RunIterations(iterations, arg);
|
||||
if (total_time_ns_ >= 1e9) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (total_time_ns_/iterations == 0) {
|
||||
new_iterations = 1e9;
|
||||
} else {
|
||||
new_iterations = 1e9/ (total_time_ns_/iterations);
|
||||
}
|
||||
new_iterations = std::max(iterations + 1,
|
||||
std::min(new_iterations + new_iterations/2, 100*iterations));
|
||||
|
||||
new_iterations = Round(new_iterations);
|
||||
}
|
||||
|
||||
printf("%-*s %10s %10" PRId64, MaxNameColumnWidth(), GetNameStr(arg).c_str(),
|
||||
PrettyInt(iterations, 10).c_str(), total_time_ns_/iterations);
|
||||
|
||||
if (total_time_ns_ > 0 && bytes_processed_ > 0) {
|
||||
double gib_processed = static_cast<double>(bytes_processed_)/1e9;
|
||||
double seconds = static_cast<double>(total_time_ns_)/1e9;
|
||||
printf(" %8.3f GiB/s", gib_processed/seconds);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
template class BenchmarkT<int>;
|
||||
template class BenchmarkT<double>;
|
||||
template class BenchmarkT<void*>;
|
||||
|
||||
template class BenchmarkWithArg<int>;
|
||||
template class BenchmarkWithArg<double>;
|
||||
|
||||
} // namespace testing
|
61
benchmarks/benchmark.h
Normal file
61
benchmarks/benchmark.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace testing {
|
||||
|
||||
class Benchmark {
|
||||
public:
|
||||
Benchmark(const char* name, void (*fn)(int)) {
|
||||
Register(name, fn, NULL);
|
||||
}
|
||||
|
||||
Benchmark(const char* name, void (*fn_range)(int, int)) {
|
||||
Register(name, NULL, fn_range);
|
||||
}
|
||||
|
||||
Benchmark* Arg(int x);
|
||||
|
||||
const char* Name();
|
||||
|
||||
bool ShouldRun(int argc, char* argv[]);
|
||||
void Run();
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
|
||||
void (*fn_)(int);
|
||||
void (*fn_range_)(int, int);
|
||||
|
||||
std::vector<int> args_;
|
||||
|
||||
void Register(const char* name, void (*fn)(int), void (*fn_range)(int, int));
|
||||
void RunRepeatedlyWithArg(int iterations, int arg);
|
||||
void RunWithArg(int arg);
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
|
||||
void SetBenchmarkBytesProcessed(int64_t);
|
||||
void StopBenchmarkTiming();
|
||||
void StartBenchmarkTiming();
|
||||
|
||||
#define BENCHMARK(f) \
|
||||
static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
|
||||
(new ::testing::Benchmark(#f, f))
|
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BENCHMARKS_BENCHMARK_H_
|
||||
#define BENCHMARKS_BENCHMARK_H_
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace testing {
|
||||
|
||||
class Benchmark {
|
||||
public:
|
||||
Benchmark() {
|
||||
List().push_back(this);
|
||||
}
|
||||
virtual ~Benchmark() {}
|
||||
|
||||
virtual std::string Name() = 0;
|
||||
|
||||
virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
|
||||
|
||||
void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
|
||||
void StopBenchmarkTiming();
|
||||
void StartBenchmarkTiming();
|
||||
|
||||
// Run all of the benchmarks that have registered.
|
||||
static size_t RunAll(std::vector<regex_t*>&);
|
||||
|
||||
static std::vector<Benchmark*>& List();
|
||||
|
||||
static int MaxNameColumnWidth();
|
||||
|
||||
protected:
|
||||
virtual size_t NameColumnWidth() = 0;
|
||||
|
||||
uint64_t bytes_processed_;
|
||||
uint64_t total_time_ns_;
|
||||
uint64_t start_time_ns_;
|
||||
|
||||
static bool header_printed_;
|
||||
|
||||
static void PrintHeader();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BenchmarkT : public Benchmark {
|
||||
public:
|
||||
BenchmarkT() {}
|
||||
virtual ~BenchmarkT() {}
|
||||
|
||||
protected:
|
||||
bool ShouldRun(std::vector<regex_t*>&, T arg);
|
||||
void RunWithArg(T arg);
|
||||
virtual void RunIterations(int, T) = 0;
|
||||
virtual std::string GetNameStr(T) = 0;
|
||||
};
|
||||
|
||||
class BenchmarkWithoutArg : public BenchmarkT<void*> {
|
||||
public:
|
||||
BenchmarkWithoutArg() {}
|
||||
virtual ~BenchmarkWithoutArg() {}
|
||||
|
||||
protected:
|
||||
virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
|
||||
size_t benchmarks_run = 0;
|
||||
if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
|
||||
PrintHeader();
|
||||
RunWithArg(nullptr);
|
||||
benchmarks_run++;
|
||||
}
|
||||
return benchmarks_run;
|
||||
}
|
||||
|
||||
virtual void RunIterations(int iters, void*) override {
|
||||
Run(iters);
|
||||
}
|
||||
|
||||
virtual void Run(int) = 0;
|
||||
|
||||
virtual size_t NameColumnWidth() override {
|
||||
return Name().size();
|
||||
}
|
||||
|
||||
virtual std::string GetNameStr(void *) override;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class BenchmarkWithArg : public BenchmarkT<T> {
|
||||
public:
|
||||
BenchmarkWithArg() {}
|
||||
virtual ~BenchmarkWithArg() {}
|
||||
|
||||
BenchmarkWithArg* Arg(T arg) {
|
||||
args_.push_back(arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual size_t NameColumnWidth() override {
|
||||
size_t max = 0;
|
||||
for (const auto& arg : args_) {
|
||||
max = std::max(max, GetNameStr(arg).size());
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
std::string GetNameStr(T arg) override;
|
||||
|
||||
virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
|
||||
size_t benchmarks_run = 0;
|
||||
for (T& arg : args_) {
|
||||
if (BenchmarkT<T>::ShouldRun(regs, arg)) {
|
||||
Benchmark::PrintHeader();
|
||||
BenchmarkT<T>::RunWithArg(arg);
|
||||
benchmarks_run++;
|
||||
}
|
||||
}
|
||||
return benchmarks_run;
|
||||
}
|
||||
|
||||
virtual void RunIterations(int iters, T arg) override {
|
||||
Run(iters, arg);
|
||||
}
|
||||
|
||||
virtual void Run(int iters, T arg) = 0;
|
||||
|
||||
private:
|
||||
std::vector<T> args_;
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#define BENCHMARK_START(f, super_class) \
|
||||
class f : public super_class { \
|
||||
public: \
|
||||
f() {} \
|
||||
virtual ~f() {} \
|
||||
virtual std::string Name() override { return #f; } \
|
||||
|
||||
#define BENCHMARK_NO_ARG(f) \
|
||||
BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
|
||||
virtual void Run(int) override; \
|
||||
}; \
|
||||
static ::testing::Benchmark* __benchmark_##f = new f()
|
||||
|
||||
#define BENCHMARK_WITH_ARG(f, arg_type) \
|
||||
BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
|
||||
virtual void Run(int, arg_type) override; \
|
||||
}; \
|
||||
static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
|
||||
|
||||
#endif // BENCHMARKS_BENCHMARK_H_
|
226
benchmarks/benchmark_main.cpp
Normal file
226
benchmarks/benchmark_main.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
static int64_t g_bytes_processed;
|
||||
static int64_t g_benchmark_total_time_ns;
|
||||
static int64_t g_benchmark_start_time_ns;
|
||||
|
||||
typedef std::map<std::string, ::testing::Benchmark*> BenchmarkMap;
|
||||
typedef BenchmarkMap::iterator BenchmarkMapIt;
|
||||
static BenchmarkMap g_benchmarks;
|
||||
static int g_name_column_width = 20;
|
||||
|
||||
static int Round(int n) {
|
||||
int base = 1;
|
||||
while (base*10 < n) {
|
||||
base *= 10;
|
||||
}
|
||||
if (n < 2*base) {
|
||||
return 2*base;
|
||||
}
|
||||
if (n < 5*base) {
|
||||
return 5*base;
|
||||
}
|
||||
return 10*base;
|
||||
}
|
||||
|
||||
static int64_t NanoTime() {
|
||||
struct timespec t;
|
||||
t.tv_sec = t.tv_nsec = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
|
||||
}
|
||||
|
||||
namespace testing {
|
||||
|
||||
Benchmark* Benchmark::Arg(int arg) {
|
||||
args_.push_back(arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
const char* Benchmark::Name() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool Benchmark::ShouldRun(int argc, char* argv[]) {
|
||||
if (argc == 1) {
|
||||
return true; // With no arguments, we run all benchmarks.
|
||||
}
|
||||
// Otherwise, we interpret each argument as a regular expression and
|
||||
// see if any of our benchmarks match.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
regex_t re;
|
||||
if (regcomp(&re, argv[i], 0) != 0) {
|
||||
fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int match = regexec(&re, name_, 0, NULL, 0);
|
||||
regfree(&re);
|
||||
if (match != REG_NOMATCH) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int, int)) {
|
||||
name_ = name;
|
||||
fn_ = fn;
|
||||
fn_range_ = fn_range;
|
||||
|
||||
if (fn_ == NULL && fn_range_ == NULL) {
|
||||
fprintf(stderr, "%s: missing function\n", name_);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_benchmarks.insert(std::make_pair(name, this));
|
||||
}
|
||||
|
||||
void Benchmark::Run() {
|
||||
if (fn_ != NULL) {
|
||||
RunWithArg(0);
|
||||
} else {
|
||||
if (args_.empty()) {
|
||||
fprintf(stderr, "%s: no args!\n", name_);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (size_t i = 0; i < args_.size(); ++i) {
|
||||
RunWithArg(args_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
|
||||
g_bytes_processed = 0;
|
||||
g_benchmark_total_time_ns = 0;
|
||||
g_benchmark_start_time_ns = NanoTime();
|
||||
if (fn_ != NULL) {
|
||||
fn_(iterations);
|
||||
} else {
|
||||
fn_range_(iterations, arg);
|
||||
}
|
||||
if (g_benchmark_start_time_ns != 0) {
|
||||
g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
|
||||
}
|
||||
}
|
||||
|
||||
void Benchmark::RunWithArg(int arg) {
|
||||
// run once in case it's expensive
|
||||
int iterations = 1;
|
||||
RunRepeatedlyWithArg(iterations, arg);
|
||||
while (g_benchmark_total_time_ns < 1e9 && iterations < 1e9) {
|
||||
int last = iterations;
|
||||
if (g_benchmark_total_time_ns/iterations == 0) {
|
||||
iterations = 1e9;
|
||||
} else {
|
||||
iterations = 1e9 / (g_benchmark_total_time_ns/iterations);
|
||||
}
|
||||
iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last));
|
||||
iterations = Round(iterations);
|
||||
RunRepeatedlyWithArg(iterations, arg);
|
||||
}
|
||||
|
||||
char throughput[100];
|
||||
throughput[0] = '\0';
|
||||
if (g_benchmark_total_time_ns > 0 && g_bytes_processed > 0) {
|
||||
double mib_processed = static_cast<double>(g_bytes_processed)/1e6;
|
||||
double seconds = static_cast<double>(g_benchmark_total_time_ns)/1e9;
|
||||
snprintf(throughput, sizeof(throughput), " %8.2f MiB/s", mib_processed/seconds);
|
||||
}
|
||||
|
||||
char full_name[100];
|
||||
if (fn_range_ != NULL) {
|
||||
if (arg >= (1<<20)) {
|
||||
snprintf(full_name, sizeof(full_name), "%s/%dM", name_, arg/(1<<20));
|
||||
} else if (arg >= (1<<10)) {
|
||||
snprintf(full_name, sizeof(full_name), "%s/%dK", name_, arg/(1<<10));
|
||||
} else {
|
||||
snprintf(full_name, sizeof(full_name), "%s/%d", name_, arg);
|
||||
}
|
||||
} else {
|
||||
snprintf(full_name, sizeof(full_name), "%s", name_);
|
||||
}
|
||||
|
||||
printf("%-*s %10d %10" PRId64 "%s\n", g_name_column_width, full_name,
|
||||
iterations, g_benchmark_total_time_ns/iterations, throughput);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
void SetBenchmarkBytesProcessed(int64_t x) {
|
||||
g_bytes_processed = x;
|
||||
}
|
||||
|
||||
void StopBenchmarkTiming() {
|
||||
if (g_benchmark_start_time_ns != 0) {
|
||||
g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
|
||||
}
|
||||
g_benchmark_start_time_ns = 0;
|
||||
}
|
||||
|
||||
void StartBenchmarkTiming() {
|
||||
if (g_benchmark_start_time_ns == 0) {
|
||||
g_benchmark_start_time_ns = NanoTime();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (g_benchmarks.empty()) {
|
||||
fprintf(stderr, "No benchmarks registered!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
|
||||
int name_width = static_cast<int>(strlen(it->second->Name()));
|
||||
g_name_column_width = std::max(g_name_column_width, name_width);
|
||||
}
|
||||
|
||||
bool need_header = true;
|
||||
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
|
||||
::testing::Benchmark* b = it->second;
|
||||
if (b->ShouldRun(argc, argv)) {
|
||||
if (need_header) {
|
||||
printf("%-*s %10s %10s\n", g_name_column_width, "", "iterations", "ns/op");
|
||||
fflush(stdout);
|
||||
need_header = false;
|
||||
}
|
||||
b->Run();
|
||||
}
|
||||
}
|
||||
|
||||
if (need_header) {
|
||||
fprintf(stderr, "No matching benchmarks!\n");
|
||||
fprintf(stderr, "Available benchmarks:\n");
|
||||
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
|
||||
fprintf(stderr, " %s\n", it->second->Name());
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (::testing::Benchmark::List().empty()) {
|
||||
fprintf(stderr, "No benchmarks registered!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::vector<regex_t*> regs;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
regex_t* re = new regex_t;
|
||||
int errcode = regcomp(re, argv[i], 0);
|
||||
if (errcode != 0) {
|
||||
size_t errbuf_size = regerror(errcode, re, NULL, 0);
|
||||
if (errbuf_size > 0) {
|
||||
char* errbuf = new char[errbuf_size];
|
||||
regerror(errcode, re, errbuf, errbuf_size);
|
||||
fprintf(stderr, "Couldn't compile \"%s\" as a regular expression: %s\n",
|
||||
argv[i], errbuf);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown compile error for \"%s\" as a regular expression!\n", argv[i]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
regs.push_back(re);
|
||||
}
|
||||
|
||||
if (::testing::Benchmark::RunAll(regs) == 0) {
|
||||
fprintf(stderr, "No matching benchmarks!\n");
|
||||
fprintf(stderr, "Available benchmarks:\n");
|
||||
for (const auto& benchmark : ::testing::Benchmark::List()) {
|
||||
fprintf(stderr, " %s\n", benchmark->Name().c_str());
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -14,20 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <fenv.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
#define AT_COMMON_VALS \
|
||||
Arg(1234.0)->Arg(nan(""))->Arg(HUGE_VAL)->Arg(0.0)
|
||||
|
||||
// Avoid optimization.
|
||||
volatile double d;
|
||||
volatile double v;
|
||||
double d;
|
||||
double v;
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_sqrt);
|
||||
void BM_math_sqrt::Run(int iters) {
|
||||
static void BM_math_sqrt(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 0.0;
|
||||
@@ -38,9 +34,9 @@ void BM_math_sqrt::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_sqrt);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_log10);
|
||||
void BM_math_log10::Run(int iters) {
|
||||
static void BM_math_log10(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 0.0;
|
||||
@@ -51,9 +47,9 @@ void BM_math_log10::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_log10);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_logb);
|
||||
void BM_math_logb::Run(int iters) {
|
||||
static void BM_math_logb(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 0.0;
|
||||
@@ -64,22 +60,61 @@ void BM_math_logb::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_logb);
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
|
||||
void BM_math_isinf::Run(int iters, double value) {
|
||||
static void BM_math_isinf_NORMAL(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 0.0;
|
||||
v = value;
|
||||
v = 1234.0; // FP_NORMAL
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
d += (isinf)(v);
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_isinf_NORMAL);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_sin_fast);
|
||||
void BM_math_sin_fast::Run(int iters) {
|
||||
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;
|
||||
@@ -89,9 +124,9 @@ void BM_math_sin_fast::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_sin_fast);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_sin_feupdateenv);
|
||||
void BM_math_sin_feupdateenv::Run(int iters) {
|
||||
static void BM_math_sin_feupdateenv(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 1.0;
|
||||
@@ -105,9 +140,9 @@ void BM_math_sin_feupdateenv::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_sin_feupdateenv);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_math_sin_fesetenv);
|
||||
void BM_math_sin_fesetenv::Run(int iters) {
|
||||
static void BM_math_sin_fesetenv(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 1.0;
|
||||
@@ -121,16 +156,56 @@ void BM_math_sin_fesetenv::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_math_sin_fesetenv);
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_math_fpclassify, double)->AT_COMMON_VALS;
|
||||
void BM_math_fpclassify::Run(int iters, double value) {
|
||||
static void BM_math_fpclassify_NORMAL(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
d = 0.0;
|
||||
v = value;
|
||||
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);
|
||||
|
@@ -14,21 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "benchmark.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
extern void* __system_property_area__;
|
||||
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.
|
||||
@@ -36,198 +34,200 @@ extern void* __system_property_area__;
|
||||
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-_.";
|
||||
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--;
|
||||
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;
|
||||
}
|
||||
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)];
|
||||
}
|
||||
old_pa = __system_property_area__;
|
||||
__system_property_area__ = NULL;
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
~LocalPropertyTestState() {
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
~LocalPropertyTestState() {
|
||||
if (!valid)
|
||||
return;
|
||||
__system_property_area__ = old_pa;
|
||||
|
||||
__system_property_area__ = old_pa;
|
||||
__system_property_set_filename(PROP_FILENAME);
|
||||
unlink(pa_filename.c_str());
|
||||
rmdir(pa_dirname.c_str());
|
||||
|
||||
__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];
|
||||
for (int i = 0; i < nprops; i++) {
|
||||
delete names[i];
|
||||
delete values[i];
|
||||
}
|
||||
delete[] names;
|
||||
delete[] name_lens;
|
||||
delete[] values;
|
||||
delete[] value_lens;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
std::string pa_dirname;
|
||||
std::string pa_filename;
|
||||
void *old_pa;
|
||||
};
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
|
||||
void BM_property_get::Run(int iters, int nprops) {
|
||||
StopBenchmarkTiming();
|
||||
static void BM_property_get(int iters, int nprops)
|
||||
{
|
||||
StopBenchmarkTiming();
|
||||
|
||||
LocalPropertyTestState pa(nprops);
|
||||
char value[PROP_VALUE_MAX];
|
||||
LocalPropertyTestState pa(nprops);
|
||||
char value[PROP_VALUE_MAX];
|
||||
|
||||
if (!pa.valid)
|
||||
return;
|
||||
if (!pa.valid)
|
||||
return;
|
||||
|
||||
srandom(iters * nprops);
|
||||
srandom(iters * nprops);
|
||||
|
||||
StartBenchmarkTiming();
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_get(pa.names[random() % nprops], value);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_get(pa.names[random() % nprops], value);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
|
||||
void BM_property_find::Run(int iters, int nprops) {
|
||||
StopBenchmarkTiming();
|
||||
static void BM_property_find(int iters, int nprops)
|
||||
{
|
||||
StopBenchmarkTiming();
|
||||
|
||||
LocalPropertyTestState pa(nprops);
|
||||
LocalPropertyTestState pa(nprops);
|
||||
|
||||
if (!pa.valid)
|
||||
return;
|
||||
if (!pa.valid)
|
||||
return;
|
||||
|
||||
srandom(iters * nprops);
|
||||
srandom(iters * nprops);
|
||||
|
||||
StartBenchmarkTiming();
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_find(pa.names[random() % nprops]);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_find(pa.names[random() % nprops]);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
|
||||
void BM_property_read::Run(int iters, int nprops) {
|
||||
StopBenchmarkTiming();
|
||||
static void BM_property_read(int iters, int nprops)
|
||||
{
|
||||
StopBenchmarkTiming();
|
||||
|
||||
LocalPropertyTestState pa(nprops);
|
||||
LocalPropertyTestState pa(nprops);
|
||||
|
||||
if (!pa.valid)
|
||||
return;
|
||||
if (!pa.valid)
|
||||
return;
|
||||
|
||||
srandom(iters * nprops);
|
||||
const prop_info** pinfo = new const prop_info*[iters];
|
||||
char propvalue[PROP_VALUE_MAX];
|
||||
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]);
|
||||
}
|
||||
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();
|
||||
StartBenchmarkTiming();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_read(pinfo[i], 0, propvalue);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
|
||||
delete[] pinfo;
|
||||
delete[] pinfo;
|
||||
}
|
||||
BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
|
||||
void BM_property_serial::Run(int iters, int nprops) {
|
||||
StopBenchmarkTiming();
|
||||
static void BM_property_serial(int iters, int nprops)
|
||||
{
|
||||
StopBenchmarkTiming();
|
||||
|
||||
LocalPropertyTestState pa(nprops);
|
||||
LocalPropertyTestState pa(nprops);
|
||||
|
||||
if (!pa.valid)
|
||||
return;
|
||||
if (!pa.valid)
|
||||
return;
|
||||
|
||||
srandom(iters * nprops);
|
||||
const prop_info** pinfo = new const prop_info*[iters];
|
||||
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]);
|
||||
}
|
||||
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();
|
||||
StartBenchmarkTiming();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
__system_property_serial(pinfo[i]);
|
||||
}
|
||||
StopBenchmarkTiming();
|
||||
|
||||
delete[] pinfo;
|
||||
delete[] pinfo;
|
||||
}
|
||||
|
||||
#endif // __BIONIC__
|
||||
BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
|
||||
|
@@ -14,15 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// Stop GCC optimizing out our pure function.
|
||||
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_self);
|
||||
void BM_pthread_self::Run(int iters) {
|
||||
static void BM_pthread_self(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -31,9 +30,9 @@ void BM_pthread_self::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_pthread_self);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_getspecific);
|
||||
void BM_pthread_getspecific::Run(int iters) {
|
||||
static void BM_pthread_getspecific(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_t key;
|
||||
pthread_key_create(&key, NULL);
|
||||
@@ -46,27 +45,12 @@ void BM_pthread_getspecific::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_delete(key);
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_setspecific);
|
||||
void BM_pthread_setspecific::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_t key;
|
||||
pthread_key_create(&key, NULL);
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
pthread_setspecific(key, NULL);
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_delete(key);
|
||||
}
|
||||
BENCHMARK(BM_pthread_getspecific);
|
||||
|
||||
static void DummyPthreadOnceInitFunction() {
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_once);
|
||||
void BM_pthread_once::Run(int iters) {
|
||||
static void BM_pthread_once(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&once, DummyPthreadOnceInitFunction);
|
||||
@@ -78,9 +62,9 @@ void BM_pthread_once::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_pthread_once);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock);
|
||||
void BM_pthread_mutex_lock::Run(int iters) {
|
||||
static void BM_pthread_mutex_lock(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
StartBenchmarkTiming();
|
||||
@@ -92,11 +76,11 @@ void BM_pthread_mutex_lock::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_pthread_mutex_lock);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_ERRORCHECK);
|
||||
void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
|
||||
static void BM_pthread_mutex_lock_ERRORCHECK(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -106,11 +90,11 @@ void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_RECURSIVE);
|
||||
void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
|
||||
static void BM_pthread_mutex_lock_RECURSIVE(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -120,114 +104,4 @@ void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_read);
|
||||
void BM_pthread_rwlock_read::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_rwlock_t lock;
|
||||
pthread_rwlock_init(&lock, NULL);
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
pthread_rwlock_rdlock(&lock);
|
||||
pthread_rwlock_unlock(&lock);
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
pthread_rwlock_destroy(&lock);
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_rwlock_write);
|
||||
void BM_pthread_rwlock_write::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_rwlock_t lock;
|
||||
pthread_rwlock_init(&lock, NULL);
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
pthread_rwlock_wrlock(&lock);
|
||||
pthread_rwlock_unlock(&lock);
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
pthread_rwlock_destroy(&lock);
|
||||
}
|
||||
|
||||
static void* IdleThread(void*) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_create);
|
||||
void BM_pthread_create::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_t thread;
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
StartBenchmarkTiming();
|
||||
pthread_create(&thread, NULL, IdleThread, NULL);
|
||||
StopBenchmarkTiming();
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void* RunThread(void* arg) {
|
||||
::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
|
||||
benchmark->StopBenchmarkTiming();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_create_and_run);
|
||||
void BM_pthread_create_and_run::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_t thread;
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
StartBenchmarkTiming();
|
||||
pthread_create(&thread, NULL, RunThread, this);
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void* ExitThread(void* arg) {
|
||||
::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
|
||||
benchmark->StartBenchmarkTiming();
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_exit_and_join);
|
||||
void BM_pthread_exit_and_join::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_t thread;
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
pthread_create(&thread, NULL, ExitThread, this);
|
||||
pthread_join(thread, NULL);
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_key_create);
|
||||
void BM_pthread_key_create::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_t key;
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
StartBenchmarkTiming();
|
||||
pthread_key_create(&key, NULL);
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_pthread_key_delete);
|
||||
void BM_pthread_key_delete::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
pthread_key_t key;
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
pthread_key_create(&key, NULL);
|
||||
StartBenchmarkTiming();
|
||||
pthread_key_delete(key);
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
|
||||
|
@@ -14,15 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
BENCHMARK_NO_ARG(BM_semaphore_sem_getvalue);
|
||||
void BM_semaphore_sem_getvalue::Run(int iters) {
|
||||
static void BM_semaphore_sem_getvalue(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
sem_t semaphore;
|
||||
sem_init(&semaphore, 1, 1);
|
||||
@@ -35,9 +31,9 @@ void BM_semaphore_sem_getvalue::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_semaphore_sem_getvalue);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_semaphore_sem_wait_sem_post);
|
||||
void BM_semaphore_sem_wait_sem_post::Run(int iters) {
|
||||
static void BM_semaphore_sem_wait_sem_post(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
sem_t semaphore;
|
||||
sem_init(&semaphore, 1, 1);
|
||||
@@ -50,94 +46,4 @@ void BM_semaphore_sem_wait_sem_post::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
|
||||
/*
|
||||
* This test reports the overhead of the underlying futex wake syscall on
|
||||
* the producer. It does not report the overhead from issuing the wake to the
|
||||
* point where the posted consumer thread wakes up. It suffers from
|
||||
* clock_gettime syscall overhead. Lock the CPU speed for consistent results
|
||||
* as we may not reach >50% cpu utilization.
|
||||
*
|
||||
* We will run a background thread that catches the sem_post wakeup and
|
||||
* loops immediately returning back to sleep in sem_wait for the next one. This
|
||||
* thread is run with policy SCHED_OTHER (normal policy), a middle policy.
|
||||
*
|
||||
* The primary thread will run at SCHED_IDLE (lowest priority policy) when
|
||||
* monitoring the background thread to detect when it hits sem_wait sleep. It
|
||||
* will do so with no clock running. Once we are ready, we will switch to
|
||||
* SCHED_FIFO (highest priority policy) to time the act of running sem_post
|
||||
* with the benchmark clock running. This ensures nothing else in the system
|
||||
* can preempt our timed activity, including the background thread. We are
|
||||
* also protected with the scheduling policy of letting a process hit a
|
||||
* resource limit rather than get hit with a context switch.
|
||||
*
|
||||
* The background thread will start executing either on another CPU, or
|
||||
* after we back down from SCHED_FIFO, but certainly not in the context of
|
||||
* the timing of the sem_post.
|
||||
*/
|
||||
static atomic_int BM_semaphore_sem_post_running;
|
||||
|
||||
static void *BM_semaphore_sem_post_start_thread(void *obj) {
|
||||
sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
|
||||
|
||||
while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
|
||||
;
|
||||
}
|
||||
BM_semaphore_sem_post_running = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_semaphore_sem_post);
|
||||
void BM_semaphore_sem_post::Run(int iters) {
|
||||
StopBenchmarkTiming();
|
||||
|
||||
sem_t semaphore;
|
||||
sem_init(&semaphore, 0, 0);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
BM_semaphore_sem_post_running = 1;
|
||||
struct sched_param param = { 0, };
|
||||
pthread_attr_setschedparam(&attr, ¶m);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_t pthread;
|
||||
pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
int trys = 3, dummy = 0;
|
||||
do {
|
||||
if (BM_semaphore_sem_post_running < 0) {
|
||||
sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
|
||||
fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
|
||||
return;
|
||||
}
|
||||
sched_yield();
|
||||
sem_getvalue(&semaphore, &dummy);
|
||||
if (dummy < 0) { // POSIX.1-2001 possibility 1
|
||||
break;
|
||||
}
|
||||
if (dummy == 0) { // POSIX.1-2001 possibility 2
|
||||
--trys;
|
||||
}
|
||||
} while (trys);
|
||||
param.sched_priority = 1;
|
||||
sched_setscheduler((pid_t)0, SCHED_FIFO, ¶m);
|
||||
StartBenchmarkTiming();
|
||||
sem_post(&semaphore);
|
||||
StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
|
||||
param.sched_priority = 0;
|
||||
sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
|
||||
}
|
||||
sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
|
||||
|
||||
if (BM_semaphore_sem_post_running > 0) {
|
||||
BM_semaphore_sem_post_running = 0;
|
||||
}
|
||||
do {
|
||||
sem_post(&semaphore);
|
||||
sched_yield();
|
||||
} while (!BM_semaphore_sem_post_running);
|
||||
}
|
||||
BENCHMARK(BM_semaphore_sem_wait_sem_post);
|
||||
|
@@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define KB 1024
|
||||
#define MB 1024*KB
|
||||
@@ -26,68 +25,37 @@
|
||||
Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
|
||||
Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
|
||||
|
||||
template <typename Fn>
|
||||
void ReadWriteTest(::testing::Benchmark* benchmark, int iters, int chunk_size, Fn f, bool buffered) {
|
||||
benchmark->StopBenchmarkTiming();
|
||||
static void BM_stdio_fread(int iters, int chunk_size) {
|
||||
StopBenchmarkTiming();
|
||||
FILE* fp = fopen("/dev/zero", "rw");
|
||||
__fsetlocking(fp, FSETLOCKING_BYCALLER);
|
||||
char* buf = new char[chunk_size];
|
||||
benchmark->StartBenchmarkTiming();
|
||||
|
||||
if (!buffered) {
|
||||
setvbuf(fp, 0, _IONBF, 0);
|
||||
}
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
f(buf, chunk_size, 1, fp);
|
||||
fread(buf, chunk_size, 1, fp);
|
||||
}
|
||||
|
||||
benchmark->StopBenchmarkTiming();
|
||||
benchmark->SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
|
||||
delete[] buf;
|
||||
fclose(fp);
|
||||
}
|
||||
BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_stdio_fread, int)->AT_COMMON_SIZES;
|
||||
void BM_stdio_fread::Run(int iters, int chunk_size) {
|
||||
ReadWriteTest(this, iters, chunk_size, fread, true);
|
||||
}
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite, int)->AT_COMMON_SIZES;
|
||||
void BM_stdio_fwrite::Run(int iters, int chunk_size) {
|
||||
ReadWriteTest(this, iters, chunk_size, fwrite, true);
|
||||
}
|
||||
static void BM_stdio_fwrite(int iters, int chunk_size) {
|
||||
StopBenchmarkTiming();
|
||||
FILE* fp = fopen("/dev/zero", "rw");
|
||||
char* buf = new char[chunk_size];
|
||||
StartBenchmarkTiming();
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, int)->AT_COMMON_SIZES;
|
||||
void BM_stdio_fread_unbuffered::Run(int iters, int chunk_size) {
|
||||
ReadWriteTest(this, iters, chunk_size, fread, false);
|
||||
}
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, int)->AT_COMMON_SIZES;
|
||||
void BM_stdio_fwrite_unbuffered::Run(int iters, int chunk_size) {
|
||||
ReadWriteTest(this, iters, chunk_size, fwrite, false);
|
||||
}
|
||||
|
||||
static void FopenFgetsFclose(int iters, bool no_locking) {
|
||||
char buf[1024];
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
FILE* fp = fopen("/proc/version", "re");
|
||||
if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
|
||||
fgets(buf, sizeof(buf), fp);
|
||||
fclose(fp);
|
||||
fwrite(buf, chunk_size, 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_locking);
|
||||
void BM_stdio_fopen_fgets_fclose_locking::Run(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
FopenFgetsFclose(iters, false);
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
|
||||
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_no_locking);
|
||||
void BM_stdio_fopen_fgets_fclose_no_locking::Run(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
FopenFgetsFclose(iters, true);
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
|
||||
delete[] buf;
|
||||
fclose(fp);
|
||||
}
|
||||
BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
|
||||
|
@@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
#include <string.h>
|
||||
|
||||
#define KB 1024
|
||||
#define MB 1024*KB
|
||||
@@ -27,8 +26,7 @@
|
||||
|
||||
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_string_memcmp, int)->AT_COMMON_SIZES;
|
||||
void BM_string_memcmp::Run(int iters, int nbytes) {
|
||||
static void BM_string_memcmp(int iters, int nbytes) {
|
||||
StopBenchmarkTiming();
|
||||
char* src = new char[nbytes]; char* dst = new char[nbytes];
|
||||
memset(src, 'x', nbytes);
|
||||
@@ -41,13 +39,13 @@ void BM_string_memcmp::Run(int iters, int nbytes) {
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
|
||||
delete[] src;
|
||||
delete[] dst;
|
||||
}
|
||||
BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_string_memcpy, int)->AT_COMMON_SIZES;
|
||||
void BM_string_memcpy::Run(int iters, int nbytes) {
|
||||
static void BM_string_memcpy(int iters, int nbytes) {
|
||||
StopBenchmarkTiming();
|
||||
char* src = new char[nbytes]; char* dst = new char[nbytes];
|
||||
memset(src, 'x', nbytes);
|
||||
@@ -58,13 +56,13 @@ void BM_string_memcpy::Run(int iters, int nbytes) {
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
|
||||
delete[] src;
|
||||
delete[] dst;
|
||||
}
|
||||
BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_string_memmove, int)->AT_COMMON_SIZES;
|
||||
void BM_string_memmove::Run(int iters, int nbytes) {
|
||||
static void BM_string_memmove(int iters, int nbytes) {
|
||||
StopBenchmarkTiming();
|
||||
char* buf = new char[nbytes + 64];
|
||||
memset(buf, 'x', nbytes + 64);
|
||||
@@ -75,12 +73,12 @@ void BM_string_memmove::Run(int iters, int nbytes) {
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
|
||||
delete[] buf;
|
||||
}
|
||||
BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_string_memset, int)->AT_COMMON_SIZES;
|
||||
void BM_string_memset::Run(int iters, int nbytes) {
|
||||
static void BM_string_memset(int iters, int nbytes) {
|
||||
StopBenchmarkTiming();
|
||||
char* dst = new char[nbytes];
|
||||
StartBenchmarkTiming();
|
||||
@@ -90,12 +88,12 @@ void BM_string_memset::Run(int iters, int nbytes) {
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
|
||||
delete[] dst;
|
||||
}
|
||||
BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
|
||||
|
||||
BENCHMARK_WITH_ARG(BM_string_strlen, int)->AT_COMMON_SIZES;
|
||||
void BM_string_strlen::Run(int iters, int nbytes) {
|
||||
static void BM_string_strlen(int iters, int nbytes) {
|
||||
StopBenchmarkTiming();
|
||||
char* s = new char[nbytes];
|
||||
memset(s, 'x', nbytes);
|
||||
@@ -108,6 +106,7 @@ void BM_string_strlen::Run(int iters, int nbytes) {
|
||||
}
|
||||
|
||||
StopBenchmarkTiming();
|
||||
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
|
||||
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
|
||||
delete[] s;
|
||||
}
|
||||
BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;
|
||||
|
@@ -14,14 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
BENCHMARK_NO_ARG(BM_time_clock_gettime);
|
||||
void BM_time_clock_gettime::Run(int iters) {
|
||||
static void BM_time_clock_gettime(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
timespec t;
|
||||
@@ -31,9 +29,9 @@ void BM_time_clock_gettime::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_time_clock_gettime);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_time_clock_gettime_syscall);
|
||||
void BM_time_clock_gettime_syscall::Run(int iters) {
|
||||
static void BM_time_clock_gettime_syscall(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
timespec t;
|
||||
@@ -43,9 +41,9 @@ void BM_time_clock_gettime_syscall::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_time_clock_gettime_syscall);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_time_gettimeofday);
|
||||
void BM_time_gettimeofday::Run(int iters) {
|
||||
static void BM_time_gettimeofday(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
timeval tv;
|
||||
@@ -55,9 +53,9 @@ void BM_time_gettimeofday::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_time_gettimeofday);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_time_gettimeofday_syscall);
|
||||
void BM_time_gettimeofday_syscall::Run(int iters) {
|
||||
static void BM_time_gettimeofday_syscall(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
timeval tv;
|
||||
@@ -67,9 +65,9 @@ void BM_time_gettimeofday_syscall::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_time_gettimeofday_syscall);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_time_time);
|
||||
void BM_time_time::Run(int iters) {
|
||||
static void BM_time_time(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -78,3 +76,4 @@ void BM_time_time::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_time_time);
|
||||
|
@@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "benchmark.h"
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
BENCHMARK_NO_ARG(BM_unistd_getpid);
|
||||
void BM_unistd_getpid::Run(int iters) {
|
||||
static void BM_unistd_getpid(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -29,9 +28,9 @@ void BM_unistd_getpid::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_unistd_getpid);
|
||||
|
||||
BENCHMARK_NO_ARG(BM_unistd_getpid_syscall);
|
||||
void BM_unistd_getpid_syscall::Run(int iters) {
|
||||
static void BM_unistd_getpid_syscall(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -40,14 +39,12 @@ void BM_unistd_getpid_syscall::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
BENCHMARK(BM_unistd_getpid_syscall);
|
||||
|
||||
// Stop GCC optimizing out our pure function.
|
||||
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
|
||||
|
||||
BENCHMARK_NO_ARG(BM_unistd_gettid);
|
||||
void BM_unistd_gettid::Run(int iters) {
|
||||
static void BM_unistd_gettid(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -56,11 +53,9 @@ void BM_unistd_gettid::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_unistd_gettid);
|
||||
|
||||
#endif
|
||||
|
||||
BENCHMARK_NO_ARG(BM_unistd_gettid_syscall);
|
||||
void BM_unistd_gettid_syscall::Run(int iters) {
|
||||
static void BM_unistd_gettid_syscall(int iters) {
|
||||
StartBenchmarkTiming();
|
||||
|
||||
for (int i = 0; i < iters; ++i) {
|
||||
@@ -69,3 +64,4 @@ void BM_unistd_gettid_syscall::Run(int iters) {
|
||||
|
||||
StopBenchmarkTiming();
|
||||
}
|
||||
BENCHMARK(BM_unistd_gettid_syscall);
|
||||
|
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
int Round(int n) {
|
||||
int base = 1;
|
||||
while (base*10 < n) {
|
||||
base *= 10;
|
||||
}
|
||||
if (n < 2*base) {
|
||||
return 2*base;
|
||||
}
|
||||
if (n < 5*base) {
|
||||
return 5*base;
|
||||
}
|
||||
return 10*base;
|
||||
}
|
||||
|
||||
// Similar to the code in art, but supporting both binary and decimal prefixes.
|
||||
std::string PrettyInt(long value, size_t base) {
|
||||
if (base != 2 && base != 10) abort();
|
||||
|
||||
uint64_t count = static_cast<uint64_t>(value);
|
||||
bool negative_number = false;
|
||||
if (value < 0) {
|
||||
negative_number = true;
|
||||
count = static_cast<uint64_t>(-value);
|
||||
}
|
||||
|
||||
// The byte thresholds at which we display amounts. A count is displayed
|
||||
// in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
|
||||
static const uint64_t kUnitThresholds2[] = {
|
||||
1024*1024*1024 /* Gi */, 2*1024*1024 /* Mi */, 3*1024 /* Ki */, 0,
|
||||
};
|
||||
static const uint64_t kUnitThresholds10[] = {
|
||||
1000*1000*1000 /* G */, 2*1000*1000 /* M */, 3*1000 /* k */, 0,
|
||||
};
|
||||
static const uint64_t kAmountPerUnit2[] = { 1024*1024*1024, 1024*1024, 1024, 1 };
|
||||
static const uint64_t kAmountPerUnit10[] = { 1000*1000*1000, 1000*1000, 1000, 1 };
|
||||
static const char* const kUnitStrings2[] = { "Gi", "Mi", "Ki", "" };
|
||||
static const char* const kUnitStrings10[] = { "G", "M", "k", "" };
|
||||
|
||||
// Which set are we using?
|
||||
const uint64_t* kUnitThresholds = ((base == 2) ? kUnitThresholds2 : kUnitThresholds10);
|
||||
const uint64_t* kAmountPerUnit = ((base == 2) ? kAmountPerUnit2 : kAmountPerUnit10);
|
||||
const char* const* kUnitStrings = ((base == 2) ? kUnitStrings2 : kUnitStrings10);
|
||||
|
||||
size_t i = 0;
|
||||
for (; kUnitThresholds[i] != 0; ++i) {
|
||||
if (count >= kUnitThresholds[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
char* s = NULL;
|
||||
asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
|
||||
count / kAmountPerUnit[i], kUnitStrings[i]);
|
||||
std::string result(s);
|
||||
free(s);
|
||||
return result;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BENCHMARKS_UTILS_H
|
||||
#define BENCHMARKS_UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
int Round(int n);
|
||||
std::string PrettyInt(long value, size_t base);
|
||||
|
||||
#endif // BENCHMARKS_UTILS_H
|
@@ -1,44 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2014 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Include once
|
||||
ifneq ($(bionic_run_on_host_mk_included),true)
|
||||
bionic_run_on_host_mk_included:=true
|
||||
|
||||
ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
|
||||
LINKER = linker64
|
||||
else
|
||||
LINKER = linker
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
|
||||
# gtest needs ANDROID_DATA/local/tmp for death test output.
|
||||
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
|
||||
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
|
||||
bionic-prepare-run-on-host: $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT)/etc/hosts $(TARGET_OUT_EXECUTABLES)/sh
|
||||
if [ ! -d /system ]; then \
|
||||
echo "Attempting to create /system"; \
|
||||
sudo mkdir -p -m 0777 /system; \
|
||||
fi
|
||||
mkdir -p $(TARGET_OUT_DATA)/local/tmp
|
||||
ln -fs `realpath $(TARGET_OUT)/bin` /system/
|
||||
ln -fs `realpath $(TARGET_OUT)/etc` /system/
|
||||
ln -fs `realpath $(TARGET_OUT)/lib` /system/
|
||||
if [ -d "$(TARGET_OUT)/lib64" ]; then \
|
||||
ln -fs `realpath $(TARGET_OUT)/lib64` /system/; \
|
||||
fi
|
||||
endif
|
||||
endif
|
563
libc/Android.mk
563
libc/Android.mk
File diff suppressed because it is too large
Load Diff
336
libc/NOTICE
336
libc/NOTICE
@@ -1679,6 +1679,35 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1990 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1990 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
@@ -2481,6 +2510,35 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
@@ -2510,6 +2568,33 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1993 Christopher G. Demetriou
|
||||
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 author may not 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(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) 1993 Martin Birgmeier
|
||||
All rights reserved.
|
||||
|
||||
@@ -2629,6 +2714,63 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB
|
||||
|
||||
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.
|
||||
|
||||
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 BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (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) 1997 Mark Brinicombe
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by Mark Brinicombe
|
||||
4. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1997 Mark Brinicombe
|
||||
Copyright (c) 2010 Android Open Source Project.
|
||||
All rights reserved.
|
||||
@@ -2989,6 +3131,38 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1999 Kungliga Tekniska Högskolan
|
||||
(Royal Institute of Technology, Stockholm, Sweden).
|
||||
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 KTH 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 KTH AND ITS 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 KTH OR ITS 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
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2000 Ben Harris.
|
||||
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
All rights reserved.
|
||||
@@ -3252,6 +3426,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
|
||||
|
||||
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 Opsycon AB nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR 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 BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (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) 2002 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
|
||||
@@ -3884,22 +4086,6 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -4236,39 +4422,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
|
||||
Copyright (c) 2009 Ted Unangst
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2011 The Android Open Source Project
|
||||
Copyright (c) 2008 ARM Ltd
|
||||
All rights reserved.
|
||||
@@ -4486,32 +4639,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
Copyright (c) 2013, Linaro Limited
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to The NetBSD Foundation
|
||||
by Christos Zoulas.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
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.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
* Redistributions in binary form must 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
@@ -4697,42 +4853,6 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||
Copyright 2008 Damien Miller <djm@openbsd.org>
|
||||
All rights reserved.
|
||||
|
||||
Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
|
||||
such a mathematical system to generate more random (yet non-repeating)
|
||||
ids to solve the resolver/named problem. But Niels designed the
|
||||
actual system based on the constraints.
|
||||
|
||||
Later modified by Damien Miller to wrap the LCG output in a 15-bit
|
||||
permutation generator based on a Luby-Rackoff block cipher. This
|
||||
ensures the output is non-repeating and preserves the MSB twiddle
|
||||
trick, but makes it more resistant to LCG prediction.
|
||||
|
||||
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.
|
||||
|
||||
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 BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(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 2000 David E. O'Brien, John D. Polstra.
|
||||
All rights reserved.
|
||||
|
||||
|
@@ -101,7 +101,7 @@ int munmap(void*, size_t) all
|
||||
void* mremap(void*, size_t, size_t, unsigned long) all
|
||||
int msync(const void*, size_t, int) all
|
||||
int mprotect(const void*, size_t, int) all
|
||||
int madvise(void*, size_t, int) all
|
||||
int 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
|
||||
@@ -113,7 +113,7 @@ int writev(int, const struct iovec*, int) all
|
||||
int __fcntl64:fcntl64(int, int, void*) arm,mips,x86
|
||||
int fcntl(int, int, void*) arm64,mips64,x86_64
|
||||
int flock(int, int) all
|
||||
int ___fchmod:fchmod(int, mode_t) all
|
||||
int fchmod(int, mode_t) all
|
||||
int dup(int) all
|
||||
int pipe2(int*, int) all
|
||||
int dup3(int, int, int) all
|
||||
@@ -130,11 +130,11 @@ int fremovexattr(int, const char*) all
|
||||
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) arm,arm64,mips,mips64,x86,x86_64
|
||||
|
||||
int __openat:openat(int, const char*, int, mode_t) all
|
||||
int ___faccessat:faccessat(int, const char*, int) all
|
||||
int ___fchmodat:fchmodat(int, const char*, mode_t) all
|
||||
int 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,x86_64
|
||||
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
|
||||
@@ -174,12 +174,12 @@ int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
|
||||
int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
|
||||
|
||||
int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,mips,x86
|
||||
int __fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
|
||||
int fstatfs64|fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
|
||||
int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86
|
||||
int __statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
|
||||
int 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,x86_64
|
||||
int fstat64|fstat:fstat(int, struct stat*) arm64,mips64,x86_64
|
||||
|
||||
# file system
|
||||
int chdir(const char*) all
|
||||
@@ -202,9 +202,9 @@ int swapoff(const char*) all
|
||||
int settimeofday(const struct timeval*, const struct timezone*) all
|
||||
clock_t times(struct tms*) all
|
||||
int nanosleep(const struct timespec*, struct timespec*) all
|
||||
int clock_settime(clockid_t, const struct timespec*) all
|
||||
int clock_getres(clockid_t, struct timespec*) all
|
||||
int __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
|
||||
int 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
|
||||
@@ -223,7 +223,6 @@ int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
|
||||
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
|
||||
int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all
|
||||
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all
|
||||
int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
|
||||
int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all
|
||||
|
||||
# sockets
|
||||
@@ -314,8 +313,6 @@ int __set_tid_address:set_tid_address(int*) all
|
||||
int setfsgid(gid_t) all
|
||||
int setfsuid(uid_t) all
|
||||
|
||||
int sethostname(const char*, size_t) all
|
||||
|
||||
pid_t wait4(pid_t, int*, int, struct rusage*) all
|
||||
int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*) all
|
||||
|
||||
@@ -324,7 +321,7 @@ int __set_tls:__ARM_NR_set_tls(void*) arm
|
||||
int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) arm
|
||||
|
||||
# MIPS-specific
|
||||
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
|
||||
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
|
||||
int __set_tls:set_thread_area(void*) mips,mips64
|
||||
|
||||
# x86-specific
|
||||
|
@@ -1,10 +1,30 @@
|
||||
# 32-bit arm.
|
||||
|
||||
#
|
||||
# Various kinds of LP32 cruft.
|
||||
#
|
||||
|
||||
libc_bionic_src_files_arm += \
|
||||
bionic/mmap.cpp \
|
||||
|
||||
libc_common_src_files_arm += \
|
||||
bionic/legacy_32_bit_support.cpp \
|
||||
bionic/ndk_cruft.cpp \
|
||||
bionic/time64.c \
|
||||
|
||||
libc_netbsd_src_files_arm += \
|
||||
upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/stdio/putw.c \
|
||||
|
||||
#
|
||||
# Default implementations of functions that are commonly optimized.
|
||||
#
|
||||
|
||||
libc_bionic_src_files_arm += \
|
||||
bionic/memchr.c \
|
||||
bionic/memrchr.c \
|
||||
bionic/strchr.cpp \
|
||||
bionic/strnlen.c \
|
||||
bionic/strrchr.cpp \
|
||||
@@ -20,8 +40,7 @@ libc_freebsd_src_files_arm += \
|
||||
upstream-freebsd/lib/libc/string/wmemmove.c \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memchr.c \
|
||||
upstream-openbsd/lib/libc/string/memrchr.c \
|
||||
upstream-openbsd/lib/libc/string/bcopy.c \
|
||||
upstream-openbsd/lib/libc/string/stpncpy.c \
|
||||
upstream-openbsd/lib/libc/string/strlcat.c \
|
||||
upstream-openbsd/lib/libc/string/strlcpy.c \
|
||||
@@ -39,9 +58,11 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/bionic/__bionic_clone.S \
|
||||
arch-arm/bionic/_exit_with_stack_teardown.S \
|
||||
arch-arm/bionic/libgcc_compat.c \
|
||||
arch-arm/bionic/libgcc_protect_unwind.c \
|
||||
arch-arm/bionic/memcmp.S \
|
||||
arch-arm/bionic/__restore.S \
|
||||
arch-arm/bionic/_setjmp.S \
|
||||
arch-arm/bionic/setjmp.S \
|
||||
arch-arm/bionic/sigsetjmp.S \
|
||||
arch-arm/bionic/syscall.S \
|
||||
|
||||
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
|
||||
|
@@ -39,9 +39,6 @@
|
||||
|
||||
extern int __cxa_atexit(void (*)(void*), void*, void*);
|
||||
|
||||
// All of these are weak symbols to avoid multiple definition errors when
|
||||
// linking with libstdc++-v3 or compiler-rt.
|
||||
|
||||
/* The "C++ ABI for ARM" document states that static C++ constructors,
|
||||
* which are called from the .init_array, should manually call
|
||||
* __aeabi_atexit() to register static destructors explicitly.
|
||||
@@ -50,35 +47,35 @@ extern int __cxa_atexit(void (*)(void*), void*, void*);
|
||||
* 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 __attribute__((weak))
|
||||
__aeabi_memcpy8(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memcpy8(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy4(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memcpy4(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memcpy(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove8(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memmove8(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove4(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memmove4(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n) {
|
||||
void __aeabi_memmove(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
@@ -87,27 +84,27 @@ void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n
|
||||
* This allows __aeabi_memclr to tail-call __aeabi_memset
|
||||
*/
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset8(void *dest, size_t n, int c) {
|
||||
void __aeabi_memset8(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset4(void *dest, size_t n, int c) {
|
||||
void __aeabi_memset4(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset(void *dest, size_t n, int c) {
|
||||
void __aeabi_memset(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr8(void *dest, size_t n) {
|
||||
void __aeabi_memclr8(void *dest, size_t n) {
|
||||
__aeabi_memset8(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr4(void *dest, size_t n) {
|
||||
void __aeabi_memclr4(void *dest, size_t n) {
|
||||
__aeabi_memset4(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr(void *dest, size_t n) {
|
||||
void __aeabi_memclr(void *dest, size_t n) {
|
||||
__aeabi_memset(dest, n, 0);
|
||||
}
|
||||
|
@@ -42,14 +42,13 @@ ENTRY(__bionic_clone)
|
||||
# load extra parameters
|
||||
ldmfd ip, {r4, r5, r6}
|
||||
|
||||
# Push 'fn' and 'arg' onto the child stack.
|
||||
stmdb r1!, {r5, r6}
|
||||
# store 'fn' and 'arg' to the child stack
|
||||
str r5, [r1, #-4]
|
||||
str r6, [r1, #-8]
|
||||
|
||||
# Make the system call.
|
||||
# System call
|
||||
ldr r7, =__NR_clone
|
||||
swi #0
|
||||
|
||||
# Are we the child?
|
||||
movs r0, r0
|
||||
beq 1f
|
||||
|
||||
@@ -63,8 +62,8 @@ ENTRY(__bionic_clone)
|
||||
1: # The child.
|
||||
# Setting lr to 0 will make the unwinder stop at __start_thread
|
||||
mov lr, #0
|
||||
# Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
|
||||
pop {r0, r1}
|
||||
ldr r0, [sp, #-4]
|
||||
ldr r1, [sp, #-8]
|
||||
b __start_thread
|
||||
END(__bionic_clone)
|
||||
.hidden __bionic_clone
|
||||
|
113
libc/arch-arm/bionic/_setjmp.S
Normal file
113
libc/arch-arm/bionic/_setjmp.S
Normal file
@@ -0,0 +1,113 @@
|
||||
/* $OpenBSD: _setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
|
||||
/* $NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Mark Brinicombe
|
||||
* Copyright (c) 2010 Android Open Source Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Mark Brinicombe
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
#include <machine/cpu-features.h>
|
||||
|
||||
/*
|
||||
* C library -- _setjmp, _longjmp
|
||||
*
|
||||
* _longjmp(a,v)
|
||||
* will generate a "return(v)" from the last call to
|
||||
* _setjmp(a)
|
||||
* by restoring registers from the stack.
|
||||
* The previous signal state is NOT restored.
|
||||
*
|
||||
* Note: r0 is the return value
|
||||
* r1-r3 are scratch registers in functions
|
||||
*/
|
||||
|
||||
ENTRY(_setjmp)
|
||||
ldr r1, .L_setjmp_magic
|
||||
str r1, [r0, #(_JB_MAGIC * 4)]
|
||||
|
||||
/* Store core registers */
|
||||
add r1, r0, #(_JB_CORE_BASE * 4)
|
||||
stmia r1, {r4-r14}
|
||||
|
||||
#ifdef __ARM_HAVE_VFP
|
||||
/* Store floating-point registers */
|
||||
add r1, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vstmia r1, {d8-d15}
|
||||
/* Store floating-point state */
|
||||
fmrx r1, fpscr
|
||||
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
#endif /* __ARM_HAVE_VFP */
|
||||
|
||||
mov r0, #0x00000000
|
||||
bx lr
|
||||
END(_setjmp)
|
||||
|
||||
.L_setjmp_magic:
|
||||
.word _JB_MAGIC__SETJMP
|
||||
|
||||
ENTRY(_longjmp)
|
||||
ldr r2, .L_setjmp_magic
|
||||
ldr r3, [r0, #(_JB_MAGIC * 4)]
|
||||
teq r2, r3
|
||||
bne botch
|
||||
|
||||
#ifdef __ARM_HAVE_VFP
|
||||
/* Restore floating-point registers */
|
||||
add r2, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vldmia r2, {d8-d15}
|
||||
/* Restore floating-point state */
|
||||
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
fmxr fpscr, r2
|
||||
#endif /* __ARM_HAVE_VFP */
|
||||
|
||||
/* Restore core registers */
|
||||
add r2, r0, #(_JB_CORE_BASE * 4)
|
||||
ldmia r2, {r4-r14}
|
||||
|
||||
/* Validate sp and r14 */
|
||||
teq sp, #0
|
||||
teqne r14, #0
|
||||
beq botch
|
||||
|
||||
/* Set return value */
|
||||
mov r0, r1
|
||||
teq r0, #0x00000000
|
||||
moveq r0, #0x00000001
|
||||
bx lr
|
||||
|
||||
/* validation failed, die die die. */
|
||||
botch:
|
||||
bl PIC_SYM(longjmperror, PLT)
|
||||
bl PIC_SYM(abort, PLT)
|
||||
b . - 8 /* Cannot get here */
|
||||
END(_longjmp)
|
@@ -40,5 +40,5 @@ ENTRY(abort)
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r3, 0
|
||||
.cfi_rel_offset r14, 4
|
||||
bl __libc_android_abort
|
||||
bl PIC_SYM(__libc_android_abort, PLT)
|
||||
END(abort)
|
||||
|
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
// TODO: This file should go away once unwinder migration to libc++.so is complete.
|
||||
|
||||
extern char _Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetCFA __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char _Unwind_Complete __attribute((visibility("protected")));
|
||||
extern char _Unwind_DeleteException __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Get __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Set __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
|
||||
extern char ___Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char _Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char _Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
|
||||
|
||||
void* __bionic_libgcc_unwind_symbols[] = {
|
||||
&_Unwind_Backtrace,
|
||||
&__gnu_Unwind_Find_exidx,
|
||||
&__gnu_Unwind_Restore_VFP_D,
|
||||
&__gnu_Unwind_Restore_VFP,
|
||||
&__gnu_Unwind_Restore_VFP_D_16_to_31,
|
||||
&__gnu_Unwind_Restore_WMMXD,
|
||||
&__gnu_Unwind_Restore_WMMXC,
|
||||
&_Unwind_GetCFA,
|
||||
&__gnu_Unwind_RaiseException,
|
||||
&__gnu_Unwind_ForcedUnwind,
|
||||
&__gnu_Unwind_Resume,
|
||||
&__gnu_Unwind_Resume_or_Rethrow,
|
||||
&_Unwind_Complete,
|
||||
&_Unwind_DeleteException,
|
||||
&_Unwind_VRS_Get,
|
||||
&_Unwind_VRS_Set,
|
||||
&__gnu_Unwind_Backtrace,
|
||||
&_Unwind_VRS_Pop,
|
||||
&__gnu_Unwind_Save_VFP_D,
|
||||
&__gnu_Unwind_Save_VFP,
|
||||
&__gnu_Unwind_Save_VFP_D_16_to_31,
|
||||
&__gnu_Unwind_Save_WMMXD,
|
||||
&__gnu_Unwind_Save_WMMXC,
|
||||
&___Unwind_RaiseException,
|
||||
&_Unwind_RaiseException,
|
||||
&___Unwind_Resume,
|
||||
&_Unwind_Resume,
|
||||
&___Unwind_Resume_or_Rethrow,
|
||||
&_Unwind_Resume_or_Rethrow,
|
||||
&___Unwind_ForcedUnwind,
|
||||
&_Unwind_ForcedUnwind,
|
||||
&___Unwind_Backtrace,
|
||||
&_Unwind_GetRegionStart,
|
||||
&_Unwind_GetLanguageSpecificData,
|
||||
&_Unwind_GetDataRelBase,
|
||||
&_Unwind_GetTextRelBase,
|
||||
};
|
686
libc/arch-arm/bionic/memcpy.S
Normal file
686
libc/arch-arm/bionic/memcpy.S
Normal file
@@ -0,0 +1,686 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
#if defined(__ARM_NEON__) && !defined(ARCH_ARM_USE_NON_NEON_MEMCPY)
|
||||
|
||||
.text
|
||||
.fpu neon
|
||||
|
||||
#ifdef HAVE_32_BYTE_CACHE_LINE
|
||||
/* a prefetch distance of 2 cache-lines */
|
||||
#define CACHE_LINE_SIZE 32
|
||||
#else
|
||||
/* a prefetch distance of 4 cache-lines works best experimentally */
|
||||
#define CACHE_LINE_SIZE 64
|
||||
#endif
|
||||
|
||||
ENTRY(memcpy)
|
||||
.save {r0, lr}
|
||||
/* start preloading as early as possible */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 0)]
|
||||
stmfd sp!, {r0, lr}
|
||||
pld [r1, #(CACHE_LINE_SIZE * 1)]
|
||||
|
||||
/* If Neon supports unaligned access then remove the align code,
|
||||
* unless a size limit has been specified.
|
||||
*/
|
||||
#ifndef NEON_UNALIGNED_ACCESS
|
||||
/* do we have at least 16-bytes to copy (needed for alignment below) */
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
|
||||
/* check if buffers are aligned. If so, run arm-only version */
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
beq 11f
|
||||
|
||||
/* align destination to cache-line for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 2f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
ldrmib lr, [r1], #1
|
||||
strmib lr, [r0], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
2:
|
||||
/* preload immediately the next cache line, which we may need */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 0)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 1)]
|
||||
|
||||
#ifdef HAVE_32_BYTE_CACHE_LINE
|
||||
/* make sure we have at least 32 bytes to copy */
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
/* preload all the cache lines we need.
|
||||
* NOTE: the number of pld below depends on PREFETCH_DISTANCE,
|
||||
* ideally would would increase the distance in the main loop to
|
||||
* avoid the goofy code below. In practice this doesn't seem to make
|
||||
* a big difference.
|
||||
*/
|
||||
pld [r1, #(PREFETCH_DISTANCE)]
|
||||
|
||||
1: /* The main loop copies 32 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
pld [r1, #(PREFETCH_DISTANCE)]
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
bhs 1b
|
||||
#else
|
||||
/* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
/* preload all the cache lines we need. */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
#ifdef HAVE_32_BYTE_CACHE_LINE
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
#else
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
#endif
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
vst1.8 {d4 - d7}, [r0, :128]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
add r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
3: /* 32 bytes at a time. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
bhs 3b
|
||||
#endif
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0, :128]!
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
|
||||
#else /* NEON_UNALIGNED_ACCESS */
|
||||
|
||||
// Check so divider is at least 16 bytes, needed for alignment code.
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
|
||||
#ifdef NEON_MEMCPY_ALIGNMENT_DIVIDER
|
||||
/* Check the upper size limit for Neon unaligned memory access in memcpy */
|
||||
#if NEON_MEMCPY_ALIGNMENT_DIVIDER >= 16
|
||||
cmp r2, #NEON_MEMCPY_ALIGNMENT_DIVIDER
|
||||
blo 3f
|
||||
#endif
|
||||
/* check if buffers are aligned. If so, run arm-only version */
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
beq 11f
|
||||
|
||||
/* align destination to 16 bytes for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 3f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
ldrmib lr, [r1], #1
|
||||
strmib lr, [r0], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
2:
|
||||
/* preload immediately the next cache line, which we may need */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 0)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 1)]
|
||||
3:
|
||||
#endif
|
||||
/* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
/* preload all the cache lines we need */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
#ifdef HAVE_32_BYTE_CACHE_LINE
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
#else
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
#endif
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
vst1.8 {d4 - d7}, [r0]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
add r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
3: /* 32 bytes at a time. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
bhs 3b
|
||||
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0]!
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
#endif /* NEON_UNALIGNED_ACCESS */
|
||||
11:
|
||||
/* Simple arm-only copy loop to handle aligned copy operations */
|
||||
stmfd sp!, {r4, r5, r6, r7, r8}
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
|
||||
/* Check alignment */
|
||||
rsb r3, r1, #0
|
||||
ands r3, #3
|
||||
beq 2f
|
||||
|
||||
/* align source to 32 bits. We need to insert 2 instructions between
|
||||
* a ldr[b|h] and str[b|h] because byte and half-word instructions
|
||||
* stall 2 cycles.
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb r4, [r1], #1
|
||||
ldrcsb r5, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb r4, [r0], #1
|
||||
strcsb r5, [r0], #1
|
||||
2:
|
||||
subs r2, #32
|
||||
blt 5f
|
||||
pld [r1, #(CACHE_LINE_SIZE * 3)]
|
||||
3: /* Main copy loop, copying 32 bytes at a time */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 4)]
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
subs r2, r2, #32
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
bge 3b
|
||||
5: /* Handle any remaining bytes */
|
||||
adds r2, #32
|
||||
beq 6f
|
||||
|
||||
movs r12, r2, lsl #28
|
||||
ldmcsia r1!, {r3, r4, r5, r6} /* 16 bytes */
|
||||
ldmmiia r1!, {r7, r8} /* 8 bytes */
|
||||
stmcsia r0!, {r3, r4, r5, r6}
|
||||
stmmiia r0!, {r7, r8}
|
||||
movs r12, r2, lsl #30
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
ldrmih r4, [r1], #2 /* 2 bytes */
|
||||
strcs r3, [r0], #4
|
||||
strmih r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
ldrneb r3, [r1] /* last byte */
|
||||
strneb r3, [r0]
|
||||
6:
|
||||
ldmfd sp!, {r4, r5, r6, r7, r8}
|
||||
ldmfd sp!, {r0, pc}
|
||||
END(memcpy)
|
||||
|
||||
|
||||
#else /* __ARM_ARCH__ < 7 */
|
||||
|
||||
|
||||
/*
|
||||
* Optimized memcpy() for ARM.
|
||||
*
|
||||
* note that memcpy() always returns the destination pointer,
|
||||
* so we have to preserve R0.
|
||||
*/
|
||||
|
||||
ENTRY(memcpy)
|
||||
/* The stack must always be 64-bits aligned to be compliant with the
|
||||
* ARM ABI. Since we have to save R0, we might as well save R4
|
||||
* which we can use for better pipelining of the reads below
|
||||
*/
|
||||
.save {r0, r4, lr}
|
||||
stmfd sp!, {r0, r4, lr}
|
||||
/* Making room for r5-r11 which will be spilled later */
|
||||
.pad #28
|
||||
sub sp, sp, #28
|
||||
|
||||
// preload the destination because we'll align it to a cache line
|
||||
// with small writes. Also start the source "pump".
|
||||
pld [r0, #0]
|
||||
pld [r1, #0]
|
||||
pld [r1, #32]
|
||||
|
||||
/* it simplifies things to take care of len<4 early */
|
||||
cmp r2, #4
|
||||
blo copy_last_3_and_return
|
||||
|
||||
/* compute the offset to align the source
|
||||
* offset = (4-(src&3))&3 = -src & 3
|
||||
*/
|
||||
rsb r3, r1, #0
|
||||
ands r3, r3, #3
|
||||
beq src_aligned
|
||||
|
||||
/* align source to 32 bits. We need to insert 2 instructions between
|
||||
* a ldr[b|h] and str[b|h] because byte and half-word instructions
|
||||
* stall 2 cycles.
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb r4, [r1], #1
|
||||
ldrcsb r12,[r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb r4, [r0], #1
|
||||
strcsb r12,[r0], #1
|
||||
|
||||
src_aligned:
|
||||
|
||||
/* see if src and dst are aligned together (congruent) */
|
||||
eor r12, r0, r1
|
||||
tst r12, #3
|
||||
bne non_congruent
|
||||
|
||||
/* Use post-incriment mode for stm to spill r5-r11 to reserved stack
|
||||
* frame. Don't update sp.
|
||||
*/
|
||||
stmea sp, {r5-r11}
|
||||
|
||||
/* align the destination to a cache-line */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0x1C
|
||||
beq congruent_aligned32
|
||||
cmp r3, r2
|
||||
andhi r3, r2, #0x1C
|
||||
|
||||
/* conditionnaly copies 0 to 7 words (length in r3) */
|
||||
movs r12, r3, lsl #28
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
tst r3, #0x4
|
||||
ldrne r10,[r1], #4 /* 4 bytes */
|
||||
strne r10,[r0], #4
|
||||
sub r2, r2, r3
|
||||
|
||||
congruent_aligned32:
|
||||
/*
|
||||
* here source is aligned to 32 bytes.
|
||||
*/
|
||||
|
||||
cached_aligned32:
|
||||
subs r2, r2, #32
|
||||
blo less_than_32_left
|
||||
|
||||
/*
|
||||
* We preload a cache-line up to 64 bytes ahead. On the 926, this will
|
||||
* stall only until the requested world is fetched, but the linefill
|
||||
* continues in the the background.
|
||||
* While the linefill is going, we write our previous cache-line
|
||||
* into the write-buffer (which should have some free space).
|
||||
* When the linefill is done, the writebuffer will
|
||||
* start dumping its content into memory
|
||||
*
|
||||
* While all this is going, we then load a full cache line into
|
||||
* 8 registers, this cache line should be in the cache by now
|
||||
* (or partly in the cache).
|
||||
*
|
||||
* This code should work well regardless of the source/dest alignment.
|
||||
*
|
||||
*/
|
||||
|
||||
// Align the preload register to a cache-line because the cpu does
|
||||
// "critical word first" (the first word requested is loaded first).
|
||||
bic r12, r1, #0x1F
|
||||
add r12, r12, #64
|
||||
|
||||
1: ldmia r1!, { r4-r11 }
|
||||
pld [r12, #64]
|
||||
subs r2, r2, #32
|
||||
|
||||
// NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
|
||||
// for ARM9 preload will not be safely guarded by the preceding subs.
|
||||
// When it is safely guarded the only possibility to have SIGSEGV here
|
||||
// is because the caller overstates the length.
|
||||
ldrhi r3, [r12], #32 /* cheap ARM9 preload */
|
||||
stmia r0!, { r4-r11 }
|
||||
bhs 1b
|
||||
|
||||
add r2, r2, #32
|
||||
|
||||
|
||||
|
||||
|
||||
less_than_32_left:
|
||||
/*
|
||||
* less than 32 bytes left at this point (length in r2)
|
||||
*/
|
||||
|
||||
/* skip all this if there is nothing to do, which should
|
||||
* be a common case (if not executed the code below takes
|
||||
* about 16 cycles)
|
||||
*/
|
||||
tst r2, #0x1F
|
||||
beq 1f
|
||||
|
||||
/* conditionnaly copies 0 to 31 bytes */
|
||||
movs r12, r2, lsl #28
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
movs r12, r2, lsl #30
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
ldrmih r4, [r1], #2 /* 2 bytes */
|
||||
strcs r3, [r0], #4
|
||||
strmih r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
ldrneb r3, [r1] /* last byte */
|
||||
strneb r3, [r0]
|
||||
|
||||
/* we're done! restore everything and return */
|
||||
1: ldmfd sp!, {r5-r11}
|
||||
ldmfd sp!, {r0, r4, lr}
|
||||
bx lr
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
non_congruent:
|
||||
/*
|
||||
* here source is aligned to 4 bytes
|
||||
* but destination is not.
|
||||
*
|
||||
* in the code below r2 is the number of bytes read
|
||||
* (the number of bytes written is always smaller, because we have
|
||||
* partial words in the shift queue)
|
||||
*/
|
||||
cmp r2, #4
|
||||
blo copy_last_3_and_return
|
||||
|
||||
/* Use post-incriment mode for stm to spill r5-r11 to reserved stack
|
||||
* frame. Don't update sp.
|
||||
*/
|
||||
stmea sp, {r5-r11}
|
||||
|
||||
/* compute shifts needed to align src to dest */
|
||||
rsb r5, r0, #0
|
||||
and r5, r5, #3 /* r5 = # bytes in partial words */
|
||||
mov r12, r5, lsl #3 /* r12 = right */
|
||||
rsb lr, r12, #32 /* lr = left */
|
||||
|
||||
/* read the first word */
|
||||
ldr r3, [r1], #4
|
||||
sub r2, r2, #4
|
||||
|
||||
/* write a partial word (0 to 3 bytes), such that destination
|
||||
* becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
|
||||
*/
|
||||
movs r5, r5, lsl #31
|
||||
strmib r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
|
||||
cmp r2, #4
|
||||
blo partial_word_tail
|
||||
|
||||
/* Align destination to 32 bytes (cache line boundary) */
|
||||
1: tst r0, #0x1c
|
||||
beq 2f
|
||||
ldr r5, [r1], #4
|
||||
sub r2, r2, #4
|
||||
orr r4, r3, r5, lsl lr
|
||||
mov r3, r5, lsr r12
|
||||
str r4, [r0], #4
|
||||
cmp r2, #4
|
||||
bhs 1b
|
||||
blo partial_word_tail
|
||||
|
||||
/* copy 32 bytes at a time */
|
||||
2: subs r2, r2, #32
|
||||
blo less_than_thirtytwo
|
||||
|
||||
/* Use immediate mode for the shifts, because there is an extra cycle
|
||||
* for register shifts, which could account for up to 50% of
|
||||
* performance hit.
|
||||
*/
|
||||
|
||||
cmp r12, #24
|
||||
beq loop24
|
||||
cmp r12, #8
|
||||
beq loop8
|
||||
|
||||
loop16:
|
||||
ldr r12, [r1], #4
|
||||
1: mov r4, r12
|
||||
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
|
||||
pld [r1, #64]
|
||||
subs r2, r2, #32
|
||||
ldrhs r12, [r1], #4
|
||||
orr r3, r3, r4, lsl #16
|
||||
mov r4, r4, lsr #16
|
||||
orr r4, r4, r5, lsl #16
|
||||
mov r5, r5, lsr #16
|
||||
orr r5, r5, r6, lsl #16
|
||||
mov r6, r6, lsr #16
|
||||
orr r6, r6, r7, lsl #16
|
||||
mov r7, r7, lsr #16
|
||||
orr r7, r7, r8, lsl #16
|
||||
mov r8, r8, lsr #16
|
||||
orr r8, r8, r9, lsl #16
|
||||
mov r9, r9, lsr #16
|
||||
orr r9, r9, r10, lsl #16
|
||||
mov r10, r10, lsr #16
|
||||
orr r10, r10, r11, lsl #16
|
||||
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
|
||||
mov r3, r11, lsr #16
|
||||
bhs 1b
|
||||
b less_than_thirtytwo
|
||||
|
||||
loop8:
|
||||
ldr r12, [r1], #4
|
||||
1: mov r4, r12
|
||||
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
|
||||
pld [r1, #64]
|
||||
subs r2, r2, #32
|
||||
ldrhs r12, [r1], #4
|
||||
orr r3, r3, r4, lsl #24
|
||||
mov r4, r4, lsr #8
|
||||
orr r4, r4, r5, lsl #24
|
||||
mov r5, r5, lsr #8
|
||||
orr r5, r5, r6, lsl #24
|
||||
mov r6, r6, lsr #8
|
||||
orr r6, r6, r7, lsl #24
|
||||
mov r7, r7, lsr #8
|
||||
orr r7, r7, r8, lsl #24
|
||||
mov r8, r8, lsr #8
|
||||
orr r8, r8, r9, lsl #24
|
||||
mov r9, r9, lsr #8
|
||||
orr r9, r9, r10, lsl #24
|
||||
mov r10, r10, lsr #8
|
||||
orr r10, r10, r11, lsl #24
|
||||
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
|
||||
mov r3, r11, lsr #8
|
||||
bhs 1b
|
||||
b less_than_thirtytwo
|
||||
|
||||
loop24:
|
||||
ldr r12, [r1], #4
|
||||
1: mov r4, r12
|
||||
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
|
||||
pld [r1, #64]
|
||||
subs r2, r2, #32
|
||||
ldrhs r12, [r1], #4
|
||||
orr r3, r3, r4, lsl #8
|
||||
mov r4, r4, lsr #24
|
||||
orr r4, r4, r5, lsl #8
|
||||
mov r5, r5, lsr #24
|
||||
orr r5, r5, r6, lsl #8
|
||||
mov r6, r6, lsr #24
|
||||
orr r6, r6, r7, lsl #8
|
||||
mov r7, r7, lsr #24
|
||||
orr r7, r7, r8, lsl #8
|
||||
mov r8, r8, lsr #24
|
||||
orr r8, r8, r9, lsl #8
|
||||
mov r9, r9, lsr #24
|
||||
orr r9, r9, r10, lsl #8
|
||||
mov r10, r10, lsr #24
|
||||
orr r10, r10, r11, lsl #8
|
||||
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
|
||||
mov r3, r11, lsr #24
|
||||
bhs 1b
|
||||
|
||||
|
||||
less_than_thirtytwo:
|
||||
/* copy the last 0 to 31 bytes of the source */
|
||||
rsb r12, lr, #32 /* we corrupted r12, recompute it */
|
||||
add r2, r2, #32
|
||||
cmp r2, #4
|
||||
blo partial_word_tail
|
||||
|
||||
1: ldr r5, [r1], #4
|
||||
sub r2, r2, #4
|
||||
orr r4, r3, r5, lsl lr
|
||||
mov r3, r5, lsr r12
|
||||
str r4, [r0], #4
|
||||
cmp r2, #4
|
||||
bhs 1b
|
||||
|
||||
partial_word_tail:
|
||||
/* we have a partial word in the input buffer */
|
||||
movs r5, lr, lsl #(31-3)
|
||||
strmib r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
|
||||
/* Refill spilled registers from the stack. Don't update sp. */
|
||||
ldmfd sp, {r5-r11}
|
||||
|
||||
copy_last_3_and_return:
|
||||
movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
|
||||
ldrmib r2, [r1], #1
|
||||
ldrcsb r3, [r1], #1
|
||||
ldrcsb r12,[r1]
|
||||
strmib r2, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
strcsb r12,[r0]
|
||||
|
||||
/* we're done! restore sp and spilled registers and return */
|
||||
add sp, sp, #28
|
||||
ldmfd sp!, {r0, r4, lr}
|
||||
bx lr
|
||||
END(memcpy)
|
||||
|
||||
|
||||
#endif /* __ARM_ARCH__ < 7 */
|
614
libc/arch-arm/bionic/memcpy.a9.S
Normal file
614
libc/arch-arm/bionic/memcpy.a9.S
Normal file
@@ -0,0 +1,614 @@
|
||||
/* 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)
|
@@ -1,3 +1,6 @@
|
||||
/* $OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
|
||||
/* $NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Mark Brinicombe
|
||||
* Copyright (c) 2010 Android Open Source Project.
|
||||
@@ -32,142 +35,119 @@
|
||||
*/
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
#include <machine/cpu-features.h>
|
||||
|
||||
// According to the ARM AAPCS document, we only need to save
|
||||
// the following registers:
|
||||
//
|
||||
// Core r4-r14
|
||||
//
|
||||
// VFP d8-d15 (see section 5.1.2.1)
|
||||
//
|
||||
// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
|
||||
// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
|
||||
// (and can be used for passing arguments or returning results in standard
|
||||
// procedure-call variants). Registers d16-d31 (q8-q15), if present, do
|
||||
// not need to be preserved.
|
||||
//
|
||||
// FPSCR saved because glibc does.
|
||||
|
||||
// The internal structure of a jmp_buf is totally private.
|
||||
// Current layout (may change in the future):
|
||||
//
|
||||
// word name description
|
||||
// 0 magic magic number
|
||||
// 1 sigmask signal mask (not used with _setjmp / _longjmp)
|
||||
// 2 float_base base of float registers (d8 to d15)
|
||||
// 18 float_state floating-point status and control register
|
||||
// 19 core_base base of core registers (r4 to r14)
|
||||
// 30 reserved reserved entries (room to grow)
|
||||
// 64
|
||||
//
|
||||
// NOTE: float_base must be at an even word index, since the
|
||||
// FP registers will be loaded/stored with instructions
|
||||
// that expect 8-byte alignment.
|
||||
|
||||
#define _JB_SIGFLAG 0
|
||||
#define _JB_SIGMASK (_JB_SIGFLAG+1)
|
||||
#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
|
||||
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
|
||||
#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
|
||||
/*
|
||||
* C library -- setjmp, longjmp
|
||||
*
|
||||
* longjmp(a,v)
|
||||
* will generate a "return(v)" from the last call to
|
||||
* setjmp(a)
|
||||
* by restoring registers from the stack.
|
||||
* The previous signal state is restored.
|
||||
*/
|
||||
|
||||
ENTRY(setjmp)
|
||||
mov r1, #1
|
||||
b sigsetjmp
|
||||
/* Block all signals and retrieve the old signal mask */
|
||||
stmfd sp!, {r0, r14}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset r14, 4
|
||||
mov r0, #0x00000000
|
||||
|
||||
bl PIC_SYM(sigblock, PLT)
|
||||
mov r1, r0
|
||||
|
||||
ldmfd sp!, {r0, r14}
|
||||
.cfi_def_cfa_offset 0
|
||||
|
||||
/* Store signal mask */
|
||||
str r1, [r0, #(_JB_SIGMASK * 4)]
|
||||
|
||||
ldr r1, .Lsetjmp_magic
|
||||
str r1, [r0, #(_JB_MAGIC * 4)]
|
||||
|
||||
/* Store core registers */
|
||||
add r1, r0, #(_JB_CORE_BASE * 4)
|
||||
stmia r1, {r4-r14}
|
||||
|
||||
#ifdef __ARM_HAVE_VFP
|
||||
/* Store floating-point registers */
|
||||
add r1, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vstmia r1, {d8-d15}
|
||||
/* Store floating-point state */
|
||||
fmrx r1, fpscr
|
||||
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
#endif /* __ARM_HAVE_VFP */
|
||||
|
||||
mov r0, #0x00000000
|
||||
bx lr
|
||||
END(setjmp)
|
||||
|
||||
ENTRY(_setjmp)
|
||||
mov r1, #0
|
||||
b sigsetjmp
|
||||
END(_setjmp)
|
||||
.Lsetjmp_magic:
|
||||
.word _JB_MAGIC_SETJMP
|
||||
|
||||
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
|
||||
ENTRY(sigsetjmp)
|
||||
// Record whether or not we're saving the signal mask.
|
||||
str r1, [r0, #(_JB_SIGFLAG * 4)]
|
||||
|
||||
// Do we need to save the signal mask?
|
||||
teq r1, #0
|
||||
beq 1f
|
||||
ENTRY(longjmp)
|
||||
ldr r2, .Lsetjmp_magic
|
||||
ldr r3, [r0, #(_JB_MAGIC * 4)]
|
||||
teq r2, r3
|
||||
bne botch
|
||||
|
||||
// Get current signal mask.
|
||||
stmfd sp!, {r0, r14}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset r14, 4
|
||||
mov r0, #0
|
||||
bl sigblock
|
||||
mov r1, r0
|
||||
ldmfd sp!, {r0, r14}
|
||||
.cfi_def_cfa_offset 0
|
||||
/* Fetch signal mask */
|
||||
ldr r2, [r0, #(_JB_SIGMASK * 4)]
|
||||
|
||||
// Save the signal mask.
|
||||
str r1, [r0, #(_JB_SIGMASK * 4)]
|
||||
/* Set signal mask */
|
||||
stmfd sp!, {r0, r1, r14}
|
||||
.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
|
||||
|
||||
1:
|
||||
// Save core registers.
|
||||
add r1, r0, #(_JB_CORE_BASE * 4)
|
||||
stmia r1, {r4-r14}
|
||||
mov r0, r2
|
||||
bl PIC_SYM(sigsetmask, PLT)
|
||||
|
||||
// Save floating-point registers.
|
||||
add r1, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vstmia r1, {d8-d15}
|
||||
add sp, sp, #4 /* unalign the stack */
|
||||
.cfi_adjust_cfa_offset -4
|
||||
ldmfd sp!, {r0, r1, r14}
|
||||
.cfi_def_cfa_offset 0
|
||||
|
||||
// Save floating-point state.
|
||||
fmrx r1, fpscr
|
||||
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
#ifdef __ARM_HAVE_VFP
|
||||
/* Restore floating-point registers */
|
||||
add r2, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vldmia r2, {d8-d15}
|
||||
/* Restore floating-point state */
|
||||
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
fmxr fpscr, r2
|
||||
#endif /* __ARM_HAVE_VFP */
|
||||
|
||||
mov r0, #0
|
||||
bx lr
|
||||
END(sigsetjmp)
|
||||
/* Restore core registers */
|
||||
add r2, r0, #(_JB_CORE_BASE * 4)
|
||||
ldmia r2, {r4-r14}
|
||||
|
||||
// void siglongjmp(sigjmp_buf env, int value);
|
||||
ENTRY(siglongjmp)
|
||||
// Do we need to restore the signal mask?
|
||||
ldr r2, [r0, #(_JB_SIGFLAG * 4)]
|
||||
teq r2, #0
|
||||
beq 1f
|
||||
/* Validate sp and r14 */
|
||||
teq sp, #0
|
||||
teqne r14, #0
|
||||
beq botch
|
||||
|
||||
// Restore the signal mask.
|
||||
stmfd sp!, {r0, r1, r14}
|
||||
.cfi_def_cfa_offset 12
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset r1, 4
|
||||
.cfi_rel_offset r14, 8
|
||||
sub sp, sp, #4 // Align the stack.
|
||||
.cfi_adjust_cfa_offset 4
|
||||
/* Set return value */
|
||||
|
||||
ldr r0, [r0, #(_JB_SIGMASK * 4)]
|
||||
bl sigsetmask
|
||||
mov r0, r1
|
||||
teq r0, #0x00000000
|
||||
moveq r0, #0x00000001
|
||||
bx lr
|
||||
#ifdef __ARM_26__
|
||||
mov r15, r14
|
||||
#else
|
||||
mov r15, r14
|
||||
#endif
|
||||
|
||||
add sp, sp, #4 // Unalign the stack.
|
||||
.cfi_adjust_cfa_offset -4
|
||||
ldmfd sp!, {r0, r1, r14}
|
||||
.cfi_def_cfa_offset 0
|
||||
|
||||
1:
|
||||
// Restore floating-point registers.
|
||||
add r2, r0, #(_JB_FLOAT_BASE * 4)
|
||||
vldmia r2, {d8-d15}
|
||||
|
||||
// Restore floating-point state.
|
||||
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
|
||||
fmxr fpscr, r2
|
||||
|
||||
// Restore core registers.
|
||||
add r2, r0, #(_JB_CORE_BASE * 4)
|
||||
ldmia r2, {r4-r14}
|
||||
|
||||
// Validate sp and r14.
|
||||
teq sp, #0
|
||||
teqne r14, #0
|
||||
bleq longjmperror
|
||||
|
||||
// Set return value.
|
||||
mov r0, r1
|
||||
teq r0, #0
|
||||
moveq r0, #1
|
||||
bx lr
|
||||
END(siglongjmp)
|
||||
|
||||
ALIAS_SYMBOL(longjmp, siglongjmp)
|
||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
|
||||
/* validation failed, die die die. */
|
||||
botch:
|
||||
bl PIC_SYM(longjmperror, PLT)
|
||||
bl PIC_SYM(abort, PLT)
|
||||
b . - 8 /* Cannot get here */
|
||||
END(longjmp)
|
||||
|
66
libc/arch-arm/bionic/sigsetjmp.S
Normal file
66
libc/arch-arm/bionic/sigsetjmp.S
Normal file
@@ -0,0 +1,66 @@
|
||||
/* $OpenBSD: sigsetjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
|
||||
/* $NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Mark Brinicombe
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Mark Brinicombe
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _ALIGN_TEXT .align 0
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
|
||||
/*
|
||||
* C library -- sigsetjmp, siglongjmp
|
||||
*
|
||||
* longjmp(a,v)
|
||||
* will generate a "return(v)" from the last call to
|
||||
* setjmp(a, m)
|
||||
* by restoring registers from the stack.
|
||||
* The previous signal state is restored.
|
||||
*/
|
||||
|
||||
ENTRY(sigsetjmp)
|
||||
teq r1, #0
|
||||
beq PIC_SYM(_setjmp, PLT)
|
||||
b PIC_SYM(setjmp, PLT)
|
||||
END(sigsetjmp)
|
||||
|
||||
.L_setjmp_magic:
|
||||
.word _JB_MAGIC__SETJMP
|
||||
|
||||
ENTRY(siglongjmp)
|
||||
ldr r2, .L_setjmp_magic
|
||||
ldr r3, [r0]
|
||||
teq r2, r3
|
||||
beq PIC_SYM(_longjmp, PLT)
|
||||
b PIC_SYM(longjmp, PLT)
|
||||
END(siglongjmp)
|
317
libc/arch-arm/bionic/strcmp.S
Normal file
317
libc/arch-arm/bionic/strcmp.S
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The Android Open Source Project
|
||||
* Copyright (c) 2008 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
.text
|
||||
|
||||
#ifdef __ARMEB__
|
||||
#define SHFT2LSB lsl
|
||||
#define SHFT2LSBEQ lsleq
|
||||
#define SHFT2MSB lsr
|
||||
#define SHFT2MSBEQ lsreq
|
||||
#define MSB 0x000000ff
|
||||
#define LSB 0xff000000
|
||||
#else
|
||||
#define SHFT2LSB lsr
|
||||
#define SHFT2LSBEQ lsreq
|
||||
#define SHFT2MSB lsl
|
||||
#define SHFT2MSBEQ lsleq
|
||||
#define MSB 0xff000000
|
||||
#define LSB 0x000000ff
|
||||
#endif
|
||||
|
||||
#define magic1(REG) REG
|
||||
#define magic2(REG) REG, lsl #7
|
||||
|
||||
ENTRY(strcmp)
|
||||
pld [r0, #0]
|
||||
pld [r1, #0]
|
||||
eor r2, r0, r1
|
||||
tst r2, #3
|
||||
|
||||
/* Strings not at same byte offset from a word boundary. */
|
||||
bne .Lstrcmp_unaligned
|
||||
ands r2, r0, #3
|
||||
bic r0, r0, #3
|
||||
bic r1, r1, #3
|
||||
ldr ip, [r0], #4
|
||||
it eq
|
||||
ldreq r3, [r1], #4
|
||||
beq 1f
|
||||
|
||||
/* Although s1 and s2 have identical initial alignment, they are
|
||||
* not currently word aligned. Rather than comparing bytes,
|
||||
* make sure that any bytes fetched from before the addressed
|
||||
* bytes are forced to 0xff. Then they will always compare
|
||||
* equal.
|
||||
*/
|
||||
eor r2, r2, #3
|
||||
lsl r2, r2, #3
|
||||
mvn r3, #MSB
|
||||
SHFT2LSB r2, r3, r2
|
||||
ldr r3, [r1], #4
|
||||
orr ip, ip, r2
|
||||
orr r3, r3, r2
|
||||
1:
|
||||
/* Load the 'magic' constant 0x01010101. */
|
||||
str r4, [sp, #-4]!
|
||||
mov r4, #1
|
||||
orr r4, r4, r4, lsl #8
|
||||
orr r4, r4, r4, lsl #16
|
||||
.p2align 2
|
||||
4:
|
||||
pld [r0, #8]
|
||||
pld [r1, #8]
|
||||
sub r2, ip, magic1(r4)
|
||||
cmp ip, r3
|
||||
itttt eq
|
||||
|
||||
/* check for any zero bytes in first word */
|
||||
biceq r2, r2, ip
|
||||
tsteq r2, magic2(r4)
|
||||
ldreq ip, [r0], #4
|
||||
ldreq r3, [r1], #4
|
||||
beq 4b
|
||||
2:
|
||||
/* There's a zero or a different byte in the word */
|
||||
SHFT2MSB r0, ip, #24
|
||||
SHFT2LSB ip, ip, #8
|
||||
cmp r0, #1
|
||||
it cs
|
||||
cmpcs r0, r3, SHFT2MSB #24
|
||||
it eq
|
||||
SHFT2LSBEQ r3, r3, #8
|
||||
beq 2b
|
||||
/* On a big-endian machine, r0 contains the desired byte in bits
|
||||
* 0-7; on a little-endian machine they are in bits 24-31. In
|
||||
* both cases the other bits in r0 are all zero. For r3 the
|
||||
* interesting byte is at the other end of the word, but the
|
||||
* other bits are not necessarily zero. We need a signed result
|
||||
* representing the differnece in the unsigned bytes, so for the
|
||||
* little-endian case we can't just shift the interesting bits up.
|
||||
*/
|
||||
#ifdef __ARMEB__
|
||||
sub r0, r0, r3, lsr #24
|
||||
#else
|
||||
and r3, r3, #255
|
||||
/* No RSB instruction in Thumb2 */
|
||||
#ifdef __thumb2__
|
||||
lsr r0, r0, #24
|
||||
sub r0, r0, r3
|
||||
#else
|
||||
rsb r0, r3, r0, lsr #24
|
||||
#endif
|
||||
#endif
|
||||
ldr r4, [sp], #4
|
||||
bx lr
|
||||
|
||||
.Lstrcmp_unaligned:
|
||||
wp1 .req r0
|
||||
wp2 .req r1
|
||||
b1 .req r2
|
||||
w1 .req r4
|
||||
w2 .req r5
|
||||
t1 .req ip
|
||||
@ r3 is scratch
|
||||
|
||||
/* First of all, compare bytes until wp1(sp1) is word-aligned. */
|
||||
1:
|
||||
tst wp1, #3
|
||||
beq 2f
|
||||
ldrb r2, [wp1], #1
|
||||
ldrb r3, [wp2], #1
|
||||
cmp r2, #1
|
||||
it cs
|
||||
cmpcs r2, r3
|
||||
beq 1b
|
||||
sub r0, r2, r3
|
||||
bx lr
|
||||
|
||||
2:
|
||||
str r5, [sp, #-4]!
|
||||
str r4, [sp, #-4]!
|
||||
mov b1, #1
|
||||
orr b1, b1, b1, lsl #8
|
||||
orr b1, b1, b1, lsl #16
|
||||
|
||||
and t1, wp2, #3
|
||||
bic wp2, wp2, #3
|
||||
ldr w1, [wp1], #4
|
||||
ldr w2, [wp2], #4
|
||||
cmp t1, #2
|
||||
beq 2f
|
||||
bhi 3f
|
||||
|
||||
/* Critical inner Loop: Block with 3 bytes initial overlap */
|
||||
.p2align 2
|
||||
1:
|
||||
bic t1, w1, #MSB
|
||||
cmp t1, w2, SHFT2LSB #8
|
||||
sub r3, w1, b1
|
||||
bic r3, r3, w1
|
||||
bne 4f
|
||||
ands r3, r3, b1, lsl #7
|
||||
it eq
|
||||
ldreq w2, [wp2], #4
|
||||
bne 5f
|
||||
eor t1, t1, w1
|
||||
cmp t1, w2, SHFT2MSB #24
|
||||
bne 6f
|
||||
ldr w1, [wp1], #4
|
||||
b 1b
|
||||
4:
|
||||
SHFT2LSB w2, w2, #8
|
||||
b 8f
|
||||
|
||||
5:
|
||||
#ifdef __ARMEB__
|
||||
/* The syndrome value may contain false ones if the string ends
|
||||
* with the bytes 0x01 0x00
|
||||
*/
|
||||
tst w1, #0xff000000
|
||||
itt ne
|
||||
tstne w1, #0x00ff0000
|
||||
tstne w1, #0x0000ff00
|
||||
beq 7f
|
||||
#else
|
||||
bics r3, r3, #0xff000000
|
||||
bne 7f
|
||||
#endif
|
||||
ldrb w2, [wp2]
|
||||
SHFT2LSB t1, w1, #24
|
||||
#ifdef __ARMEB__
|
||||
lsl w2, w2, #24
|
||||
#endif
|
||||
b 8f
|
||||
|
||||
6:
|
||||
SHFT2LSB t1, w1, #24
|
||||
and w2, w2, #LSB
|
||||
b 8f
|
||||
|
||||
/* Critical inner Loop: Block with 2 bytes initial overlap */
|
||||
.p2align 2
|
||||
2:
|
||||
SHFT2MSB t1, w1, #16
|
||||
sub r3, w1, b1
|
||||
SHFT2LSB t1, t1, #16
|
||||
bic r3, r3, w1
|
||||
cmp t1, w2, SHFT2LSB #16
|
||||
bne 4f
|
||||
ands r3, r3, b1, lsl #7
|
||||
it eq
|
||||
ldreq w2, [wp2], #4
|
||||
bne 5f
|
||||
eor t1, t1, w1
|
||||
cmp t1, w2, SHFT2MSB #16
|
||||
bne 6f
|
||||
ldr w1, [wp1], #4
|
||||
b 2b
|
||||
|
||||
5:
|
||||
#ifdef __ARMEB__
|
||||
/* The syndrome value may contain false ones if the string ends
|
||||
* with the bytes 0x01 0x00
|
||||
*/
|
||||
tst w1, #0xff000000
|
||||
it ne
|
||||
tstne w1, #0x00ff0000
|
||||
beq 7f
|
||||
#else
|
||||
lsls r3, r3, #16
|
||||
bne 7f
|
||||
#endif
|
||||
ldrh w2, [wp2]
|
||||
SHFT2LSB t1, w1, #16
|
||||
#ifdef __ARMEB__
|
||||
lsl w2, w2, #16
|
||||
#endif
|
||||
b 8f
|
||||
|
||||
6:
|
||||
SHFT2MSB w2, w2, #16
|
||||
SHFT2LSB t1, w1, #16
|
||||
4:
|
||||
SHFT2LSB w2, w2, #16
|
||||
b 8f
|
||||
|
||||
/* Critical inner Loop: Block with 1 byte initial overlap */
|
||||
.p2align 2
|
||||
3:
|
||||
and t1, w1, #LSB
|
||||
cmp t1, w2, SHFT2LSB #24
|
||||
sub r3, w1, b1
|
||||
bic r3, r3, w1
|
||||
bne 4f
|
||||
ands r3, r3, b1, lsl #7
|
||||
it eq
|
||||
ldreq w2, [wp2], #4
|
||||
bne 5f
|
||||
eor t1, t1, w1
|
||||
cmp t1, w2, SHFT2MSB #8
|
||||
bne 6f
|
||||
ldr w1, [wp1], #4
|
||||
b 3b
|
||||
4:
|
||||
SHFT2LSB w2, w2, #24
|
||||
b 8f
|
||||
5:
|
||||
/* The syndrome value may contain false ones if the string ends
|
||||
* with the bytes 0x01 0x00
|
||||
*/
|
||||
tst w1, #LSB
|
||||
beq 7f
|
||||
ldr w2, [wp2], #4
|
||||
6:
|
||||
SHFT2LSB t1, w1, #8
|
||||
bic w2, w2, #MSB
|
||||
b 8f
|
||||
7:
|
||||
mov r0, #0
|
||||
ldr r4, [sp], #4
|
||||
ldr r5, [sp], #4
|
||||
bx lr
|
||||
|
||||
8:
|
||||
and r2, t1, #LSB
|
||||
and r0, w2, #LSB
|
||||
cmp r0, #1
|
||||
it cs
|
||||
cmpcs r0, r2
|
||||
itt eq
|
||||
SHFT2LSBEQ t1, t1, #8
|
||||
SHFT2LSBEQ w2, w2, #8
|
||||
beq 8b
|
||||
sub r0, r2, r0
|
||||
ldr r4, [sp], #4
|
||||
ldr r5, [sp], #4
|
||||
bx lr
|
||||
END(strcmp)
|
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/cortex-a15/bionic/memcpy.S \
|
||||
arch-arm/cortex-a15/bionic/memset.S \
|
||||
arch-arm/cortex-a15/bionic/stpcpy.S \
|
||||
@@ -9,6 +8,4 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/cortex-a15/bionic/strcpy.S \
|
||||
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
|
||||
arch-arm/cortex-a15/bionic/strlen.S \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
bionic/memmove.c \
|
||||
|
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/cortex-a9/bionic/memcpy.S \
|
||||
arch-arm/cortex-a9/bionic/memset.S \
|
||||
arch-arm/cortex-a9/bionic/stpcpy.S \
|
||||
@@ -9,6 +8,4 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/cortex-a9/bionic/strcpy.S \
|
||||
arch-arm/cortex-a9/bionic/__strcpy_chk.S \
|
||||
arch-arm/cortex-a9/bionic/strlen.S \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
bionic/memmove.c \
|
||||
|
@@ -37,7 +37,6 @@
|
||||
* memset() returns its first argument.
|
||||
*/
|
||||
|
||||
.cpu cortex-a15
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/denver/bionic/memcpy.S \
|
||||
arch-arm/denver/bionic/memmove.S \
|
||||
arch-arm/denver/bionic/memset.S \
|
||||
|
@@ -1,14 +1,11 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/generic/bionic/memcpy.S \
|
||||
arch-arm/generic/bionic/memset.S \
|
||||
arch-arm/generic/bionic/strcmp.S \
|
||||
arch-arm/generic/bionic/strcpy.S \
|
||||
arch-arm/generic/bionic/strlen.c \
|
||||
bionic/memmove.c \
|
||||
bionic/__strcat_chk.cpp \
|
||||
bionic/__strcpy_chk.cpp \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
upstream-openbsd/lib/libc/string/stpcpy.c \
|
||||
upstream-openbsd/lib/libc/string/strcat.c \
|
||||
|
@@ -38,7 +38,9 @@
|
||||
#ifndef _ARM32_ASM_H_
|
||||
#define _ARM32_ASM_H_
|
||||
|
||||
#define __bionic_asm_align 0
|
||||
#ifndef _ALIGN_TEXT
|
||||
# define _ALIGN_TEXT .align 0
|
||||
#endif
|
||||
|
||||
#undef __bionic_asm_custom_entry
|
||||
#undef __bionic_asm_custom_end
|
||||
@@ -48,4 +50,10 @@
|
||||
#undef __bionic_asm_function_type
|
||||
#define __bionic_asm_function_type #function
|
||||
|
||||
#if defined(__ELF__) && defined(PIC)
|
||||
#define PIC_SYM(x,y) x ## ( ## y ## )
|
||||
#else
|
||||
#define PIC_SYM(x,y) x
|
||||
#endif
|
||||
|
||||
#endif /* !_ARM_ASM_H_ */
|
||||
|
@@ -28,6 +28,14 @@
|
||||
#ifndef _ARM_MACHINE_CPU_FEATURES_H
|
||||
#define _ARM_MACHINE_CPU_FEATURES_H
|
||||
|
||||
/* The purpose of this file is to define several macros corresponding
|
||||
* to CPU features that may or may not be available at build time on
|
||||
* on the target CPU.
|
||||
*
|
||||
* This is done to abstract us from the various ARM Architecture
|
||||
* quirks and alphabet soup.
|
||||
*/
|
||||
|
||||
/* __ARM_ARCH__ is a number corresponding to the ARM revision
|
||||
* we're going to support. Our toolchain doesn't define __ARM_ARCH__
|
||||
* so try to guess it.
|
||||
@@ -45,4 +53,31 @@
|
||||
# endif
|
||||
#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
|
||||
|
||||
/* define __ARM_HAVE_LDREXD for ARMv7 architecture
|
||||
* (also present in ARMv6K, but not implemented in ARMv7-M, neither of which
|
||||
* we care about)
|
||||
*/
|
||||
#if __ARM_ARCH__ >= 7
|
||||
# define __ARM_HAVE_LDREXD
|
||||
#endif
|
||||
|
||||
/* define _ARM_HAVE_VFP if we have VFPv3
|
||||
*/
|
||||
#if __ARM_ARCH__ >= 7 && defined __VFP_FP__
|
||||
# define __ARM_HAVE_VFP
|
||||
#endif
|
||||
|
||||
/* define _ARM_HAVE_NEON for ARMv7 architecture if we support the
|
||||
* Neon SIMD instruction set extensions. This also implies
|
||||
* that VFPv3-D32 is supported.
|
||||
*/
|
||||
#if __ARM_ARCH__ >= 7 && defined __ARM_NEON__
|
||||
# define __ARM_HAVE_NEON
|
||||
#endif
|
||||
|
||||
#endif /* _ARM_MACHINE_CPU_FEATURES_H */
|
||||
|
@@ -102,8 +102,6 @@
|
||||
|
||||
/* 112-127 are reserved for private experiments. */
|
||||
|
||||
#define R_ARM_IRELATIVE 160
|
||||
|
||||
#define R_ARM_RXPC25 249
|
||||
#define R_ARM_RSBREL32 250
|
||||
#define R_ARM_THM_RPC22 251
|
||||
|
79
libc/arch-arm/include/machine/endian.h
Normal file
79
libc/arch-arm/include/machine/endian.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* $OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_ENDIAN_H_
|
||||
#define _ARM_ENDIAN_H_
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
/* According to RealView Assembler User's Guide, REV and REV16 are available
|
||||
* in Thumb code and 16-bit instructions when used in Thumb-2 code.
|
||||
*
|
||||
* REV Rd, Rm
|
||||
* Rd and Rm must both be Lo registers.
|
||||
*
|
||||
* REV16 Rd, Rm
|
||||
* Rd and Rm must both be Lo registers.
|
||||
*
|
||||
* The +l constraint takes care of this without constraining us in ARM mode.
|
||||
*/
|
||||
#define __swap16md(x) ({ \
|
||||
register u_int16_t _x = (x); \
|
||||
__asm__ __volatile__("rev16 %0, %0" : "+l" (_x)); \
|
||||
_x; \
|
||||
})
|
||||
|
||||
#define __swap32md(x) ({ \
|
||||
register u_int32_t _x = (x); \
|
||||
__asm__ __volatile__("rev %0, %0" : "+l" (_x)); \
|
||||
_x; \
|
||||
})
|
||||
|
||||
#define __swap64md(x) ({ \
|
||||
u_int64_t _swap64md_x = (x); \
|
||||
(u_int64_t) __swap32md(_swap64md_x >> 32) | \
|
||||
(u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
|
||||
})
|
||||
|
||||
/* Tell sys/endian.h we have MD variants of the swap macros. */
|
||||
#define MD_SWAP
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#if defined(__ARMEB__)
|
||||
#define _BYTE_ORDER _BIG_ENDIAN
|
||||
#else
|
||||
#define _BYTE_ORDER _LITTLE_ENDIAN
|
||||
#endif
|
||||
#define __STRICT_ALIGNMENT
|
||||
#include <sys/types.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#endif /* !_ARM_ENDIAN_H_ */
|
50
libc/arch-arm/include/machine/exec.h
Normal file
50
libc/arch-arm/include/machine/exec.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* $OpenBSD: exec.h,v 1.9 2003/04/17 03:42:14 drahn Exp $ */
|
||||
/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993 Christopher G. Demetriou
|
||||
* 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 author may not 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_EXEC_H_
|
||||
#define _ARM_EXEC_H_
|
||||
|
||||
#define __LDPGSZ 4096
|
||||
|
||||
#define NATIVE_EXEC_ELF
|
||||
|
||||
#define ARCH_ELFSIZE 32
|
||||
|
||||
#define ELF_TARG_CLASS ELFCLASS32
|
||||
#define ELF_TARG_DATA ELFDATA2LSB
|
||||
#define ELF_TARG_MACH EM_ARM
|
||||
|
||||
#define _NLIST_DO_AOUT
|
||||
#define _NLIST_DO_ELF
|
||||
|
||||
#define _KERN_DO_AOUT
|
||||
#define _KERN_DO_ELF
|
||||
|
||||
#endif /* _ARM_EXEC_H_ */
|
@@ -26,6 +26,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* machine/setjmp.h: machine dependent setjmp-related information.
|
||||
*/
|
||||
|
||||
/* _JBLEN is the size of a jmp_buf in longs.
|
||||
* Do not modify this value or you will break the ABI !
|
||||
*
|
||||
@@ -33,3 +37,46 @@
|
||||
* that was replaced by this one.
|
||||
*/
|
||||
#define _JBLEN 64
|
||||
|
||||
/* According to the ARM AAPCS document, we only need to save
|
||||
* the following registers:
|
||||
*
|
||||
* Core r4-r14
|
||||
*
|
||||
* VFP d8-d15 (see section 5.1.2.1)
|
||||
*
|
||||
* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
|
||||
* calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
|
||||
* (and can be used for passing arguments or returning results in standard
|
||||
* procedure-call variants). Registers d16-d31 (q8-q15), if present, do
|
||||
* not need to be preserved.
|
||||
*
|
||||
* FPSCR saved because GLibc does saves it too.
|
||||
*
|
||||
*/
|
||||
|
||||
/* The internal structure of a jmp_buf is totally private.
|
||||
* Current layout (may change in the future):
|
||||
*
|
||||
* word name description
|
||||
* 0 magic magic number
|
||||
* 1 sigmask signal mask (not used with _setjmp / _longjmp)
|
||||
* 2 float_base base of float registers (d8 to d15)
|
||||
* 18 float_state floating-point status and control register
|
||||
* 19 core_base base of core registers (r4 to r14)
|
||||
* 30 reserved reserved entries (room to grow)
|
||||
* 64
|
||||
*
|
||||
* NOTE: float_base must be at an even word index, since the
|
||||
* FP registers will be loaded/stored with instructions
|
||||
* that expect 8-byte alignment.
|
||||
*/
|
||||
|
||||
#define _JB_MAGIC 0
|
||||
#define _JB_SIGMASK (_JB_MAGIC+1)
|
||||
#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
|
||||
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
|
||||
#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
|
||||
|
||||
#define _JB_MAGIC__SETJMP 0x4278f500
|
||||
#define _JB_MAGIC_SETJMP 0x4278f501
|
||||
|
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/krait/bionic/memcpy.S \
|
||||
arch-arm/krait/bionic/memset.S \
|
||||
arch-arm/krait/bionic/strcmp.S \
|
||||
@@ -12,6 +11,4 @@ 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 \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
bionic/memmove.c \
|
||||
|
@@ -1,14 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_rt_sigqueueinfo
|
||||
swi #0
|
||||
mov r7, ip
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(__rt_sigqueueinfo)
|
@@ -13,4 +13,5 @@ ENTRY(_exit)
|
||||
b __set_errno_internal
|
||||
END(_exit)
|
||||
|
||||
ALIAS_SYMBOL(_Exit, _exit)
|
||||
.globl _Exit
|
||||
.equ _Exit, _exit
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__clock_nanosleep)
|
||||
ENTRY(clock_nanosleep)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_clock_nanosleep
|
||||
swi #0
|
||||
@@ -11,4 +11,4 @@ ENTRY(__clock_nanosleep)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(__clock_nanosleep)
|
||||
END(clock_nanosleep)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___faccessat)
|
||||
ENTRY(faccessat)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_faccessat
|
||||
swi #0
|
||||
@@ -11,5 +11,4 @@ ENTRY(___faccessat)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(___faccessat)
|
||||
.hidden ___faccessat
|
||||
END(faccessat)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___fchmod)
|
||||
ENTRY(fchmod)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_fchmod
|
||||
swi #0
|
||||
@@ -11,5 +11,4 @@ ENTRY(___fchmod)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(___fchmod)
|
||||
.hidden ___fchmod
|
||||
END(fchmod)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___fchmodat)
|
||||
ENTRY(fchmodat)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_fchmodat
|
||||
swi #0
|
||||
@@ -11,5 +11,4 @@ ENTRY(___fchmodat)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(___fchmodat)
|
||||
.hidden ___fchmodat
|
||||
END(fchmodat)
|
@@ -13,4 +13,5 @@ ENTRY(fstat64)
|
||||
b __set_errno_internal
|
||||
END(fstat64)
|
||||
|
||||
ALIAS_SYMBOL(fstat, fstat64)
|
||||
.globl fstat
|
||||
.equ fstat, fstat64
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(fstatat64)
|
||||
b __set_errno_internal
|
||||
END(fstatat64)
|
||||
|
||||
ALIAS_SYMBOL(fstatat, fstatat64)
|
||||
.globl fstatat
|
||||
.equ fstatat, fstatat64
|
||||
|
@@ -1,14 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(sethostname)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_sethostname
|
||||
swi #0
|
||||
mov r7, ip
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(sethostname)
|
@@ -8,6 +8,7 @@ libc_bionic_src_files_arm64 += \
|
||||
bionic/__memset_chk.cpp \
|
||||
bionic/__strcpy_chk.cpp \
|
||||
bionic/__strcat_chk.cpp \
|
||||
bionic/memrchr.c \
|
||||
bionic/strrchr.cpp \
|
||||
|
||||
libc_freebsd_src_files_arm64 += \
|
||||
@@ -20,7 +21,6 @@ libc_freebsd_src_files_arm64 += \
|
||||
upstream-freebsd/lib/libc/string/wmemcmp.c \
|
||||
|
||||
libc_openbsd_src_files_arm64 += \
|
||||
upstream-openbsd/lib/libc/string/memrchr.c \
|
||||
upstream-openbsd/lib/libc/string/stpncpy.c \
|
||||
upstream-openbsd/lib/libc/string/strcat.c \
|
||||
upstream-openbsd/lib/libc/string/strlcat.c \
|
||||
@@ -35,13 +35,13 @@ libc_openbsd_src_files_arm64 += \
|
||||
libc_bionic_src_files_arm64 += \
|
||||
arch-arm64/bionic/__bionic_clone.S \
|
||||
arch-arm64/bionic/_exit_with_stack_teardown.S \
|
||||
arch-arm64/bionic/_setjmp.S \
|
||||
arch-arm64/bionic/setjmp.S \
|
||||
arch-arm64/bionic/__set_tls.c \
|
||||
arch-arm64/bionic/sigsetjmp.S \
|
||||
arch-arm64/bionic/syscall.S \
|
||||
arch-arm64/bionic/vfork.S \
|
||||
|
||||
# Work around for http://b/20065774.
|
||||
libc_bionic_src_files_arm64 += arch-arm64/bionic/libgcc_compat.c
|
||||
|
||||
libc_crt_target_cflags_arm64 := \
|
||||
-I$(LOCAL_PATH)/arch-arm64/include
|
||||
@@ -61,6 +61,6 @@ ifeq ($(wildcard $(cpu_variant_mk)),)
|
||||
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. 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)
|
||||
libc_common_additional_dependencies += $(cpu_variank_mk)
|
||||
|
||||
cpu_variant_mk :=
|
||||
|
@@ -31,8 +31,8 @@
|
||||
// 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)
|
||||
# Push 'fn' and 'arg' onto the child stack.
|
||||
stp x5, x6, [x1, #-16]!
|
||||
# Copy 'fn' and 'arg' onto the child stack.
|
||||
stp x5, x6, [x1, #-16]
|
||||
|
||||
# Make the system call.
|
||||
mov x8, __NR_clone
|
||||
@@ -49,12 +49,12 @@ ENTRY(__bionic_clone)
|
||||
ret
|
||||
|
||||
.L_bc_child:
|
||||
# We're in the child now. Set the end of the frame record chain.
|
||||
mov x29, #0
|
||||
# Setting x30 to 0 will make the unwinder stop at __start_thread.
|
||||
mov x30, #0
|
||||
# Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
|
||||
ldp x0, x1, [sp], #16
|
||||
# We're in the child now. Set the end of the frame record chain...
|
||||
mov x29, xzr
|
||||
# Setting x30 to 0 will make the unwinder stop at __start_thread
|
||||
mov x30, xzr
|
||||
# ...and call __start_thread with the 'fn' and 'arg' we stored on the child stack.
|
||||
ldp x0, x1, [sp, #-16]
|
||||
b __start_thread
|
||||
END(__bionic_clone)
|
||||
.hidden __bionic_clone
|
||||
|
111
libc/arch-arm64/bionic/_setjmp.S
Normal file
111
libc/arch-arm64/bionic/_setjmp.S
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 <machine/setjmp.h>
|
||||
|
||||
/*
|
||||
* C library - _setjmp, _longjmp
|
||||
*
|
||||
* _longjmp(jmp_buf state, int value)
|
||||
* will generate a "return(v)" from the last call to _setjmp(state) by restoring
|
||||
* registers from the stack. The previous signal state is NOT restored.
|
||||
*
|
||||
* NOTE: x0 return value
|
||||
* x9-x15 temporary registers
|
||||
*/
|
||||
|
||||
ENTRY(_setjmp)
|
||||
/* store magic number */
|
||||
ldr w9, .L_setjmp_magic
|
||||
str w9, [x0, #(_JB_MAGIC * 4)]
|
||||
|
||||
/* store core registers */
|
||||
mov x10, sp
|
||||
stp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
|
||||
stp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
|
||||
stp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
|
||||
stp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
|
||||
stp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
|
||||
stp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
|
||||
str x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
|
||||
|
||||
/* store floating point registers */
|
||||
stp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
|
||||
stp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
|
||||
stp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
|
||||
stp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
|
||||
|
||||
mov w0, wzr
|
||||
ret
|
||||
END(_setjmp)
|
||||
|
||||
.L_setjmp_magic:
|
||||
.word _JB_MAGIC__SETJMP
|
||||
|
||||
ENTRY(_longjmp)
|
||||
/* check magic */
|
||||
ldr w9, .L_setjmp_magic
|
||||
ldr w10, [x0, #(_JB_MAGIC * 4)]
|
||||
cmp w9, w10
|
||||
b.ne .L_fail
|
||||
|
||||
/* restore core registers */
|
||||
ldp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
|
||||
mov sp, x10
|
||||
ldp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
|
||||
ldp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
|
||||
ldp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
|
||||
ldp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
|
||||
ldp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
|
||||
ldr x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
|
||||
|
||||
/* restore floating point registers */
|
||||
ldp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
|
||||
ldp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
|
||||
ldp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
|
||||
ldp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
|
||||
|
||||
/* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
|
||||
tst x30, #3
|
||||
b.ne .L_fail
|
||||
mov x10, sp
|
||||
tst x10, #15
|
||||
b.ne .L_fail
|
||||
|
||||
/* set return value */
|
||||
cmp w1, wzr
|
||||
csinc w0, w1, wzr, ne
|
||||
ret
|
||||
|
||||
/* validation failed, die die die */
|
||||
.L_fail:
|
||||
bl PIC_SYM(longjmperror, PLT)
|
||||
bl PIC_SYM(abort, PLT)
|
||||
b . - 8 /* Cannot get here */
|
||||
END(_longjmp)
|
@@ -1,15 +0,0 @@
|
||||
/* STOPSHIP: remove this once the flounder blobs have been rebuilt (http://b/20065774). */
|
||||
|
||||
#if !defined(__clang__)
|
||||
|
||||
extern void __clear_cache(char*, char*);
|
||||
extern char _Unwind_Backtrace;
|
||||
extern char _Unwind_GetIP;
|
||||
|
||||
void* __bionic_libgcc_compat_symbols[] = {
|
||||
&__clear_cache,
|
||||
&_Unwind_Backtrace,
|
||||
&_Unwind_GetIP,
|
||||
};
|
||||
|
||||
#endif
|
@@ -27,124 +27,97 @@
|
||||
*/
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
|
||||
// According to AARCH64 PCS document we need to save the following
|
||||
// registers:
|
||||
//
|
||||
// Core x19 - x30, sp (see section 5.1.1)
|
||||
// VFP d8 - d15 (see section 5.1.2)
|
||||
//
|
||||
// NOTE: All the registers saved here will have 64 bit vales.
|
||||
// AAPCS mandates that the higher part of q registers do not need to
|
||||
// be saved by the callee.
|
||||
|
||||
#define _JB_SIGFLAG 0
|
||||
#define _JB_SIGMASK (_JB_SIGFLAG + 1)
|
||||
#define _JB_X30_SP (_JB_SIGMASK + 1)
|
||||
#define _JB_X28_X29 (_JB_X30_SP + 2)
|
||||
#define _JB_X26_X27 (_JB_X28_X29 + 2)
|
||||
#define _JB_X24_X25 (_JB_X26_X27 + 2)
|
||||
#define _JB_X22_X23 (_JB_X24_X25 + 2)
|
||||
#define _JB_X20_X21 (_JB_X22_X23 + 2)
|
||||
#define _JB_X19 (_JB_X20_X21 + 2)
|
||||
#define _JB_D14_D15 (_JB_X19 + 1)
|
||||
#define _JB_D12_D13 (_JB_D14_D15 + 2)
|
||||
#define _JB_D10_D11 (_JB_D12_D13 + 2)
|
||||
#define _JB_D8_D9 (_JB_D10_D11 + 2)
|
||||
/*
|
||||
* C library - _setjmp, _longjmp
|
||||
*
|
||||
* _longjmp(jmp_buf state, int value)
|
||||
* will generate a "return(v)" from the last call to _setjmp(state) by restoring
|
||||
* registers from the stack. The previous signal state is NOT restored.
|
||||
*
|
||||
* NOTE: x0 return value
|
||||
* x9-x15 temporary registers
|
||||
*/
|
||||
|
||||
ENTRY(setjmp)
|
||||
mov w1, #1
|
||||
b sigsetjmp
|
||||
/* block all signals an retrieve signal mask */
|
||||
stp x0, x30, [sp, #-16]!
|
||||
|
||||
mov x0, xzr
|
||||
bl PIC_SYM(sigblock, PLT)
|
||||
mov w1, w0
|
||||
|
||||
ldp x0, x30, [sp], #16
|
||||
|
||||
/* store signal mask */
|
||||
str w1, [x0, #(_JB_SIGMASK *4)]
|
||||
|
||||
/* store magic number */
|
||||
ldr w9, .L_setjmp_magic
|
||||
str w9, [x0, #(_JB_MAGIC * 4)]
|
||||
|
||||
/* store core registers */
|
||||
mov x10, sp
|
||||
stp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
|
||||
stp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
|
||||
stp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
|
||||
stp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
|
||||
stp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
|
||||
stp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
|
||||
str x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
|
||||
|
||||
/* store floating point registers */
|
||||
stp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
|
||||
stp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
|
||||
stp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
|
||||
stp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
|
||||
|
||||
mov w0, wzr
|
||||
ret
|
||||
END(setjmp)
|
||||
|
||||
ENTRY(_setjmp)
|
||||
mov w1, #0
|
||||
b sigsetjmp
|
||||
END(_setjmp)
|
||||
.L_setjmp_magic:
|
||||
.word _JB_MAGIC__SETJMP
|
||||
|
||||
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
|
||||
ENTRY(sigsetjmp)
|
||||
// Record whether or not we're saving the signal mask.
|
||||
str w1, [x0, #(_JB_SIGFLAG * 8)]
|
||||
ENTRY(longjmp)
|
||||
/* check magic */
|
||||
ldr w9, .L_setjmp_magic
|
||||
ldr w10, [x0, #(_JB_MAGIC * 4)]
|
||||
cmp w9, w10
|
||||
b.ne .L_fail
|
||||
|
||||
// Do we need to save the signal mask?
|
||||
cbz w1, 1f
|
||||
/* restore core registers */
|
||||
ldp x30, x10, [x0, #(_JB_CORE_BASE * 4 + 16 * 0)]
|
||||
mov sp, x10
|
||||
ldp x28, x29, [x0, #(_JB_CORE_BASE * 4 + 16 * 1)]
|
||||
ldp x26, x27, [x0, #(_JB_CORE_BASE * 4 + 16 * 2)]
|
||||
ldp x24, x25, [x0, #(_JB_CORE_BASE * 4 + 16 * 3)]
|
||||
ldp x22, x23, [x0, #(_JB_CORE_BASE * 4 + 16 * 4)]
|
||||
ldp x20, x21, [x0, #(_JB_CORE_BASE * 4 + 16 * 5)]
|
||||
ldr x19, [x0, #(_JB_CORE_BASE * 4 + 16 * 6)]
|
||||
|
||||
// Save current signal mask.
|
||||
stp x0, x30, [sp, #-16]!
|
||||
// The 'how' argument is ignored if new_mask is NULL.
|
||||
mov x1, #0 // NULL.
|
||||
add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
|
||||
bl sigprocmask
|
||||
ldp x0, x30, [sp], #16
|
||||
/* restore floating point registers */
|
||||
ldp d14, d15, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 0)]
|
||||
ldp d12, d13, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 1)]
|
||||
ldp d10, d11, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 2)]
|
||||
ldp d8, d9, [x0, #(_JB_FLOAT_BASE * 4 + 16 * 3)]
|
||||
|
||||
1:
|
||||
// Save core registers.
|
||||
mov x10, sp
|
||||
stp x30, x10, [x0, #(_JB_X30_SP * 8)]
|
||||
stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
|
||||
stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
|
||||
stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
|
||||
stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
|
||||
stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
|
||||
str x19, [x0, #(_JB_X19 * 8)]
|
||||
/* validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0) */
|
||||
tst x30, #3
|
||||
b.ne .L_fail
|
||||
mov x10, sp
|
||||
tst x10, #15
|
||||
b.ne .L_fail
|
||||
|
||||
// Save floating point registers.
|
||||
stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
|
||||
stp d12, d13, [x0, #(_JB_D12_D13 * 8)]
|
||||
stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
|
||||
stp d8, d9, [x0, #(_JB_D8_D9 * 8)]
|
||||
/* set return value */
|
||||
cmp w1, wzr
|
||||
csinc w0, w1, wzr, ne
|
||||
ret
|
||||
|
||||
mov w0, #0
|
||||
ret
|
||||
END(sigsetjmp)
|
||||
|
||||
// void siglongjmp(sigjmp_buf env, int value);
|
||||
ENTRY(siglongjmp)
|
||||
// Do we need to restore the signal mask?
|
||||
ldr w9, [x0, #(_JB_SIGFLAG * 8)]
|
||||
cbz w9, 1f
|
||||
|
||||
// Restore signal mask.
|
||||
stp x0, x30, [sp, #-16]!
|
||||
mov x19, x1 // Save 'value'.
|
||||
mov x2, x0
|
||||
mov x0, #2 // SIG_SETMASK
|
||||
add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
|
||||
mov x2, #0 // NULL.
|
||||
bl sigprocmask
|
||||
mov x1, x19 // Restore 'value'.
|
||||
ldp x0, x30, [sp], #16
|
||||
|
||||
1:
|
||||
// Restore core registers.
|
||||
ldp x30, x10, [x0, #(_JB_X30_SP * 8)]
|
||||
mov sp, x10
|
||||
ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
|
||||
ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
|
||||
ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
|
||||
ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
|
||||
ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
|
||||
ldr x19, [x0, #(_JB_X19 * 8)]
|
||||
|
||||
// Restore floating point registers.
|
||||
ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
|
||||
ldp d12, d13, [x0, #(_JB_D12_D13 * 8)]
|
||||
ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
|
||||
ldp d8, d9, [x0, #(_JB_D8_D9 * 8)]
|
||||
|
||||
// Validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0).
|
||||
tst x30, #3
|
||||
b.ne longjmperror
|
||||
mov x10, sp
|
||||
tst x10, #15
|
||||
b.ne longjmperror
|
||||
|
||||
// Set return value.
|
||||
cmp w1, wzr
|
||||
csinc w0, w1, wzr, ne
|
||||
ret
|
||||
END(siglongjmp)
|
||||
|
||||
ALIAS_SYMBOL(longjmp, siglongjmp)
|
||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
|
||||
/* validation failed, die die die */
|
||||
.L_fail:
|
||||
bl PIC_SYM(longjmperror, PLT)
|
||||
bl PIC_SYM(abort, PLT)
|
||||
b . - 8 /* Cannot get here */
|
||||
END(longjmp)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,21 +26,26 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_TIMESPEC_H_
|
||||
#define _MACHINE_TIMESPEC_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
|
||||
/*
|
||||
* This file is used to include timespec definition without introducing the whole
|
||||
* <linux/time.h>, <sys/time.h> or <time.h>.
|
||||
* int sigsetjmp(sigjmp_buf env, int savesigs);
|
||||
* void siglongjmp(sigjmp_buf env, int val);
|
||||
*/
|
||||
#ifndef _STRUCT_TIMESPEC
|
||||
#define _STRUCT_TIMESPEC
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _MACHINE_TIMESPEC_H_ */
|
||||
ENTRY(sigsetjmp)
|
||||
cbz w1, PIC_SYM(_setjmp, PLT)
|
||||
b PIC_SYM(setjmp, PLT)
|
||||
END(sigsetjmp)
|
||||
|
||||
.L_setjmp_magic:
|
||||
.word _JB_MAGIC__SETJMP
|
||||
|
||||
ENTRY(siglongjmp)
|
||||
ldr w2, .L_setjmp_magic
|
||||
ldr w3, [x0]
|
||||
cmp w2, w3
|
||||
b.eq PIC_SYM(_longjmp, PLT)
|
||||
b PIC_SYM(longjmp, PLT)
|
||||
END(siglongjmp)
|
@@ -38,9 +38,17 @@
|
||||
#ifndef _AARCH64_ASM_H_
|
||||
#define _AARCH64_ASM_H_
|
||||
|
||||
#define __bionic_asm_align 0
|
||||
#ifndef _ALIGN_TEXT
|
||||
# define _ALIGN_TEXT .align 0
|
||||
#endif
|
||||
|
||||
#undef __bionic_asm_function_type
|
||||
#define __bionic_asm_function_type %function
|
||||
|
||||
#if defined(__ELF__) && defined(PIC)
|
||||
#define PIC_SYM(x,y) x ## ( ## y ## )
|
||||
#else
|
||||
#define PIC_SYM(x,y) x
|
||||
#endif
|
||||
|
||||
#endif /* _AARCH64_ASM_H_ */
|
||||
|
58
libc/arch-arm64/include/machine/endian.h
Normal file
58
libc/arch-arm64/include/machine/endian.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _AARCH64_ENDIAN_H_
|
||||
#define _AARCH64_ENDIAN_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define __swap16md(x) ({ \
|
||||
register u_int16_t _x = (x); \
|
||||
__asm volatile ("rev16 %0, %0" : "+r" (_x)); \
|
||||
_x; \
|
||||
})
|
||||
|
||||
/* Use GCC builtins */
|
||||
#define __swap32md(x) __builtin_bswap32(x)
|
||||
#define __swap64md(x) __builtin_bswap64(x)
|
||||
|
||||
/* Tell sys/endian.h we have MD variants of the swap macros. */
|
||||
#define MD_SWAP
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#if defined(__AARCH64EB__)
|
||||
#define _BYTE_ORDER _BIG_ENDIAN
|
||||
#else
|
||||
#define _BYTE_ORDER _LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* _AARCH64_ENDIAN_H_ */
|
50
libc/arch-arm64/include/machine/exec.h
Normal file
50
libc/arch-arm64/include/machine/exec.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* $OpenBSD: exec.h,v 1.9 2003/04/17 03:42:14 drahn Exp $ */
|
||||
/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993 Christopher G. Demetriou
|
||||
* 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 author may not 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (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 _AARCH64_EXEC_H_
|
||||
#define _AARCH64_EXEC_H_
|
||||
|
||||
#define __LDPGSZ 4096
|
||||
|
||||
#define NATIVE_EXEC_ELF
|
||||
|
||||
#define ARCH_ELFSIZE 64
|
||||
|
||||
#define ELF_TARG_CLASS ELFCLASS64 /* 64-bit objects */
|
||||
#define ELF_TARG_DATA ELFDATA2LSB
|
||||
#define ELF_TARG_MACH EM_AARCH64
|
||||
|
||||
#define _NLIST_DO_AOUT
|
||||
#define _NLIST_DO_ELF
|
||||
|
||||
#define _KERN_DO_AOUT
|
||||
#define _KERN_DO_ELF64
|
||||
|
||||
#endif /* _AARCH64_EXEC_H_ */
|
@@ -26,5 +26,48 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* _JBLEN is the size of a jmp_buf in longs (64bit on AArch64) */
|
||||
/*
|
||||
* machine/setjmp.h: machine dependent setjmp-related information.
|
||||
*/
|
||||
|
||||
/* _JBLEN is the size of a jmp_buf in longs(64bit on AArch64) */
|
||||
#define _JBLEN 32
|
||||
|
||||
/* According to AARCH64 PCS document we need to save the following
|
||||
* registers:
|
||||
*
|
||||
* Core x19 - x30, sp (see section 5.1.1)
|
||||
* VFP d8 - d15 (see section 5.1.2)
|
||||
*
|
||||
* NOTE: All the registers saved here will have 64bit vales (except FPSR).
|
||||
* AAPCS mandates that the higher part of q registers does not need to
|
||||
* be saveved by the callee.
|
||||
*/
|
||||
|
||||
/* The structure of jmp_buf for AArch64:
|
||||
*
|
||||
* NOTE: _JBLEN is the size of jmp_buf in longs(64bit on AArch64)! The table
|
||||
* below computes the offsets in words(32bit).
|
||||
*
|
||||
* word name description
|
||||
* 0 magic magic number
|
||||
* 1 sigmask signal mask (not used with _setjmp / _longjmp)
|
||||
* 2 core_base base of core registers (x19-x30, sp)
|
||||
* 28 float_base base of float registers (d8-d15)
|
||||
* 44 reserved reserved entries (room to grow)
|
||||
* 64
|
||||
*
|
||||
*
|
||||
* NOTE: The instructions that load/store core/vfp registers expect 8-byte
|
||||
* alignment. Contrary to the previous setjmp header for ARM we do not
|
||||
* need to save status/control registers for VFP (it is not a
|
||||
* requirement for setjmp).
|
||||
*/
|
||||
|
||||
#define _JB_MAGIC 0
|
||||
#define _JB_SIGMASK (_JB_MAGIC+1)
|
||||
#define _JB_CORE_BASE (_JB_SIGMASK+1)
|
||||
#define _JB_FLOAT_BASE (_JB_CORE_BASE + (31-19+1)*2)
|
||||
|
||||
#define _JB_MAGIC__SETJMP 0x53657200
|
||||
#define _JB_MAGIC_SETJMP 0x53657201
|
||||
|
@@ -1,15 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
mov x8, __NR_rt_sigqueueinfo
|
||||
svc #0
|
||||
|
||||
cmn x0, #(MAX_ERRNO + 1)
|
||||
cneg x0, x0, hi
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(__rt_sigqueueinfo)
|
||||
.hidden __rt_sigqueueinfo
|
@@ -13,4 +13,5 @@ ENTRY(_exit)
|
||||
ret
|
||||
END(_exit)
|
||||
|
||||
ALIAS_SYMBOL(_Exit, _exit)
|
||||
.globl _Exit
|
||||
.equ _Exit, _exit
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__clock_nanosleep)
|
||||
ENTRY(clock_nanosleep)
|
||||
mov x8, __NR_clock_nanosleep
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,4 @@ ENTRY(__clock_nanosleep)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(__clock_nanosleep)
|
||||
.hidden __clock_nanosleep
|
||||
END(clock_nanosleep)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___faccessat)
|
||||
ENTRY(faccessat)
|
||||
mov x8, __NR_faccessat
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,4 @@ ENTRY(___faccessat)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(___faccessat)
|
||||
.hidden ___faccessat
|
||||
END(faccessat)
|
@@ -13,4 +13,5 @@ ENTRY(fallocate)
|
||||
ret
|
||||
END(fallocate)
|
||||
|
||||
ALIAS_SYMBOL(fallocate64, fallocate)
|
||||
.globl fallocate64
|
||||
.equ fallocate64, fallocate
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___fchmod)
|
||||
ENTRY(fchmod)
|
||||
mov x8, __NR_fchmod
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,4 @@ ENTRY(___fchmod)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(___fchmod)
|
||||
.hidden ___fchmod
|
||||
END(fchmod)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___fchmodat)
|
||||
ENTRY(fchmodat)
|
||||
mov x8, __NR_fchmodat
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,4 @@ ENTRY(___fchmodat)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(___fchmodat)
|
||||
.hidden ___fchmodat
|
||||
END(fchmodat)
|
@@ -13,4 +13,5 @@ ENTRY(fstat64)
|
||||
ret
|
||||
END(fstat64)
|
||||
|
||||
ALIAS_SYMBOL(fstat, fstat64)
|
||||
.globl fstat
|
||||
.equ fstat, fstat64
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(fstatat64)
|
||||
ret
|
||||
END(fstatat64)
|
||||
|
||||
ALIAS_SYMBOL(fstatat, fstatat64)
|
||||
.globl fstatat
|
||||
.equ fstatat, fstatat64
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__fstatfs)
|
||||
ENTRY(fstatfs64)
|
||||
mov x8, __NR_fstatfs
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,7 @@ ENTRY(__fstatfs)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(__fstatfs)
|
||||
.hidden __fstatfs
|
||||
END(fstatfs64)
|
||||
|
||||
.globl fstatfs
|
||||
.equ fstatfs, fstatfs64
|
@@ -13,4 +13,5 @@ ENTRY(ftruncate)
|
||||
ret
|
||||
END(ftruncate)
|
||||
|
||||
ALIAS_SYMBOL(ftruncate64, ftruncate)
|
||||
.globl ftruncate64
|
||||
.equ ftruncate64, ftruncate
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(getrlimit)
|
||||
ret
|
||||
END(getrlimit)
|
||||
|
||||
ALIAS_SYMBOL(getrlimit64, getrlimit)
|
||||
.globl getrlimit64
|
||||
.equ getrlimit64, getrlimit
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(lseek)
|
||||
ret
|
||||
END(lseek)
|
||||
|
||||
ALIAS_SYMBOL(lseek64, lseek)
|
||||
.globl lseek64
|
||||
.equ lseek64, lseek
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(mmap)
|
||||
ret
|
||||
END(mmap)
|
||||
|
||||
ALIAS_SYMBOL(mmap64, mmap)
|
||||
.globl mmap64
|
||||
.equ mmap64, mmap
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(pread64)
|
||||
ret
|
||||
END(pread64)
|
||||
|
||||
ALIAS_SYMBOL(pread, pread64)
|
||||
.globl pread
|
||||
.equ pread, pread64
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(prlimit64)
|
||||
ret
|
||||
END(prlimit64)
|
||||
|
||||
ALIAS_SYMBOL(prlimit, prlimit64)
|
||||
.globl prlimit
|
||||
.equ prlimit, prlimit64
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(pwrite64)
|
||||
ret
|
||||
END(pwrite64)
|
||||
|
||||
ALIAS_SYMBOL(pwrite, pwrite64)
|
||||
.globl pwrite
|
||||
.equ pwrite, pwrite64
|
||||
|
@@ -13,4 +13,5 @@ ENTRY(sendfile)
|
||||
ret
|
||||
END(sendfile)
|
||||
|
||||
ALIAS_SYMBOL(sendfile64, sendfile)
|
||||
.globl sendfile64
|
||||
.equ sendfile64, sendfile
|
||||
|
@@ -1,14 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(sethostname)
|
||||
mov x8, __NR_sethostname
|
||||
svc #0
|
||||
|
||||
cmn x0, #(MAX_ERRNO + 1)
|
||||
cneg x0, x0, hi
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(sethostname)
|
@@ -13,4 +13,5 @@ ENTRY(setrlimit)
|
||||
ret
|
||||
END(setrlimit)
|
||||
|
||||
ALIAS_SYMBOL(setrlimit64, setrlimit)
|
||||
.globl setrlimit64
|
||||
.equ setrlimit64, setrlimit
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__statfs)
|
||||
ENTRY(statfs64)
|
||||
mov x8, __NR_statfs
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,7 @@ ENTRY(__statfs)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(__statfs)
|
||||
.hidden __statfs
|
||||
END(statfs64)
|
||||
|
||||
.globl statfs
|
||||
.equ statfs, statfs64
|
@@ -13,4 +13,5 @@ ENTRY(truncate)
|
||||
ret
|
||||
END(truncate)
|
||||
|
||||
ALIAS_SYMBOL(truncate64, truncate)
|
||||
.globl truncate64
|
||||
.equ truncate64, truncate
|
||||
|
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 .note.android.ident,"a",%note
|
||||
.align 2
|
||||
.type abitag, %object
|
||||
abitag:
|
||||
.long 2f-1f /* int32_t namesz */
|
||||
.long 3f-2f /* int32_t descsz */
|
||||
.long 1 /* int32_t type */
|
||||
1: .ascii "Android\0" /* char name[] */
|
||||
2: .long PLATFORM_SDK_VERSION /* int32_t android_api */
|
||||
3:
|
||||
.size abitag, .-abitag
|
150
libc/arch-mips/bionic/_setjmp.S
Normal file
150
libc/arch-mips/bionic/_setjmp.S
Normal file
@@ -0,0 +1,150 @@
|
||||
/* $OpenBSD: _setjmp.S,v 1.4 2005/08/07 16:40:15 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
|
||||
*
|
||||
* 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 Opsycon AB nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR 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 BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (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 <machine/regnum.h>
|
||||
#include <machine/signal.h>
|
||||
|
||||
/*
|
||||
* _setjmp, _longjmp (not restoring signal state)
|
||||
*
|
||||
* XXX FPSET should probably be taken from SR setting. hmmm...
|
||||
* GPOFF and FRAMESIZE must be the same for both _setjmp and _longjmp!
|
||||
*
|
||||
*/
|
||||
|
||||
FRAMESZ= MKFSIZ(0,4)
|
||||
GPOFF= FRAMESZ-2*REGSZ
|
||||
|
||||
LEAF(_setjmp, FRAMESZ)
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, _setjmp)
|
||||
SAVE_GP(GPOFF)
|
||||
.set noreorder
|
||||
#if defined(__mips64)
|
||||
dli v0, 0xACEDBADE # sigcontext magic number
|
||||
#else
|
||||
li v0, 0xACEDBADE # sigcontext magic number
|
||||
#endif
|
||||
REG_S v0, SC_REGS+ZERO*REGSZ(a0)
|
||||
REG_S s0, SC_REGS+S0*REGSZ(a0)
|
||||
REG_S s1, SC_REGS+S1*REGSZ(a0)
|
||||
REG_S s2, SC_REGS+S2*REGSZ(a0)
|
||||
REG_S s3, SC_REGS+S3*REGSZ(a0)
|
||||
REG_S s4, SC_REGS+S4*REGSZ(a0)
|
||||
REG_S s5, SC_REGS+S5*REGSZ(a0)
|
||||
REG_S s6, SC_REGS+S6*REGSZ(a0)
|
||||
REG_S s7, SC_REGS+S7*REGSZ(a0)
|
||||
REG_S s8, SC_REGS+S8*REGSZ(a0)
|
||||
REG_L v0, GPOFF(sp)
|
||||
REG_S v0, SC_REGS+GP*REGSZ(a0)
|
||||
PTR_ADDU v0, sp, FRAMESZ
|
||||
REG_S v0, SC_REGS+SP*REGSZ(a0)
|
||||
REG_S ra, SC_PC(a0)
|
||||
|
||||
#if !defined(SOFTFLOAT)
|
||||
li v0, 1 # be nice if we could tell
|
||||
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
|
||||
cfc1 v0, $31
|
||||
s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
|
||||
s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
|
||||
s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
|
||||
s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
|
||||
s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
|
||||
s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
|
||||
#if _MIPS_FPSET == 32
|
||||
s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
|
||||
s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
|
||||
s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
|
||||
s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
|
||||
s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
|
||||
s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
|
||||
#endif
|
||||
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
|
||||
#endif /* !SOFTFLOAT */
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
j ra
|
||||
move v0, zero
|
||||
END(_setjmp)
|
||||
|
||||
LEAF(_longjmp, FRAMESZ)
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, _longjmp)
|
||||
SAVE_GP(GPOFF)
|
||||
.set noreorder
|
||||
REG_L v0, SC_REGS+ZERO*REGSZ(a0)
|
||||
bne v0, 0xACEDBADE, botch # jump if error
|
||||
REG_L ra, SC_PC(a0)
|
||||
REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
|
||||
REG_L s0, SC_REGS+S0*REGSZ(a0)
|
||||
REG_L s1, SC_REGS+S1*REGSZ(a0)
|
||||
REG_L s2, SC_REGS+S2*REGSZ(a0)
|
||||
REG_L s3, SC_REGS+S3*REGSZ(a0)
|
||||
REG_L s4, SC_REGS+S4*REGSZ(a0)
|
||||
REG_L s5, SC_REGS+S5*REGSZ(a0)
|
||||
REG_L s6, SC_REGS+S6*REGSZ(a0)
|
||||
REG_L s7, SC_REGS+S7*REGSZ(a0)
|
||||
REG_L s8, SC_REGS+S8*REGSZ(a0)
|
||||
REG_L gp, SC_REGS+GP*REGSZ(a0)
|
||||
REG_L sp, SC_REGS+SP*REGSZ(a0)
|
||||
#if !defined(SOFTFLOAT)
|
||||
ctc1 v0, $31
|
||||
l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
|
||||
l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
|
||||
l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
|
||||
l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
|
||||
l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
|
||||
l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
|
||||
#if _MIPS_FPSET == 32
|
||||
l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
|
||||
l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
|
||||
l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
|
||||
l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
|
||||
l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
|
||||
l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
|
||||
#endif
|
||||
#endif /* !SOFTFLOAT */
|
||||
bne a1, zero, 1f
|
||||
nop
|
||||
li a1, 1 # never return 0!
|
||||
1:
|
||||
j ra
|
||||
move v0, a1
|
||||
|
||||
botch:
|
||||
jal longjmperror
|
||||
nop
|
||||
jal abort
|
||||
nop
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
END(_longjmp)
|
36
libc/arch-mips/bionic/atexit.h
Normal file
36
libc/arch-mips/bionic/atexit.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern void *__dso_handle;
|
||||
extern int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
|
||||
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
int atexit(void (*func)(void))
|
||||
{
|
||||
return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle));
|
||||
}
|
@@ -91,4 +91,4 @@ __asm__ (
|
||||
);
|
||||
|
||||
#include "../../arch-common/bionic/__dso_handle.h"
|
||||
#include "../../arch-common/bionic/atexit.h"
|
||||
#include "atexit.h"
|
||||
|
38
libc/arch-mips/bionic/crtbegin_so.c
Normal file
38
libc/arch-mips/bionic/crtbegin_so.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern void __cxa_finalize(void *);
|
||||
extern void *__dso_handle;
|
||||
|
||||
__attribute__((visibility("hidden"),destructor))
|
||||
void __on_dlclose() {
|
||||
__cxa_finalize(&__dso_handle);
|
||||
}
|
||||
|
||||
#include "../../arch-common/bionic/__dso_handle_so.h"
|
||||
#include "atexit.h"
|
@@ -1,30 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 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.
|
||||
*/
|
||||
/* $OpenBSD: setjmp.S,v 1.5 2005/08/07 16:40:15 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
|
||||
*
|
||||
@@ -53,122 +28,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1995,
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Havard Eidnes.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)signal.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/setjmp.h>
|
||||
|
||||
/* jmpbuf is declared to users as an array of longs, which is only
|
||||
* 4-byte aligned in 32-bit builds. The Mips jmpbuf begins with a
|
||||
* dynamically-sized 0- or 4-byte unused filler so that double-prec FP regs
|
||||
* are saved to 8-byte-aligned mem cells.
|
||||
* All the following jmpbuf offsets are from the rounded-DOWN base addr.
|
||||
*/
|
||||
|
||||
/* Fields of same size on all MIPS abis: */
|
||||
/* field: byte offset: size: */
|
||||
/* dynam filler (0*4) 0-4 bytes of rounddown filler, DON'T TOUCH!!
|
||||
often overlays user storage!! */
|
||||
#define SC_MAGIC_OFFSET (1*4) /* 4 bytes, identify jmpbuf, first actual field */
|
||||
#define SC_FLAG_OFFSET (2*4) /* 4 bytes, savesigs flag */
|
||||
#define SC_FPSR_OFFSET (3*4) /* 4 bytes, floating point control/status reg */
|
||||
/* following fields are 8-byte aligned */
|
||||
#define SC_MASK_OFFSET (4*4) /* 16 bytes, mips32/mips64 version of sigset_t */
|
||||
#define SC_SPARE_OFFSET (8*4) /* 8 bytes, reserved for future uses */
|
||||
|
||||
/* Registers that are 4-byte on mips32 o32, and 8-byte on mips64 n64 abi */
|
||||
#define SC_REGS_OFFSET (10*4) /* SC_REGS_BYTES */
|
||||
#define SC_REGS_SAVED 12 /*regs*/ /* ra,s0-s8,gp,sp */
|
||||
#define SC_REGS_BYTES (SC_REGS_SAVED*REGSZ)
|
||||
#define SC_REGS SC_REGS_OFFSET
|
||||
|
||||
/* Double floating pt registers are 8-bytes on all abis,
|
||||
* but the number of saved fp regs varies for o32/n32 versus n64 abis:
|
||||
*/
|
||||
|
||||
#ifdef __LP64__
|
||||
#define SC_FPREGS_SAVED 8 /* all fp regs f24,f25,f26,f27,f28,f29,f30,f31 */
|
||||
#else
|
||||
#define SC_FPREGS_SAVED 6 /* even fp regs f20,f22,f24,f26,f28,f30 */
|
||||
#endif
|
||||
|
||||
#define SC_FPREGS_OFFSET (SC_REGS_OFFSET + SC_REGS_BYTES) /* SC_FPREGS_BYTES */
|
||||
#define SC_FPREGS_BYTES (SC_FPREGS_SAVED*REGSZ_FP)
|
||||
#define SC_FPREGS SC_FPREGS_OFFSET
|
||||
|
||||
#define SC_TOTAL_BYTES (SC_FPREGS_OFFSET + SC_FPREGS_BYTES)
|
||||
#define SC_TOTAL_LONGS (SC_TOTAL_BYTES/REGSZ)
|
||||
|
||||
#if SC_TOTAL_LONGS > _JBLEN
|
||||
#error _JBLEN is too small
|
||||
#endif
|
||||
#include <machine/regnum.h>
|
||||
#include <machine/signal.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* GPOFF and FRAMESIZE must be the same for all setjmp/longjmp routines
|
||||
* setjmp, longjmp implementation for libc. this code depends
|
||||
* on the layout of the struct sigcontext in machine/signal.h.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -178,179 +45,130 @@ A0OFF= FRAMESZ-3*REGSZ
|
||||
GPOFF= FRAMESZ-2*REGSZ
|
||||
RAOFF= FRAMESZ-1*REGSZ
|
||||
|
||||
NON_LEAF(sigsetjmp, FRAMESZ, ra)
|
||||
NON_LEAF(setjmp, FRAMESZ, ra)
|
||||
.mask 0x80000000, RAOFF
|
||||
PTR_SUBU sp, FRAMESZ # allocate stack frame
|
||||
SETUP_GP64(GPOFF, sigsetjmp)
|
||||
SETUP_GP64(GPOFF, setjmp)
|
||||
SAVE_GP(GPOFF)
|
||||
.set reorder
|
||||
|
||||
setjmp_common:
|
||||
#ifndef __LP64__
|
||||
li t0, ~7
|
||||
and a0, t0 # round jmpbuf addr DOWN to 8-byte boundary
|
||||
#endif
|
||||
sw a1, SC_FLAG_OFFSET(a0) # save savesigs flag
|
||||
beqz a1, 1f # do saving of signal mask?
|
||||
|
||||
REG_S ra, RAOFF(sp) # spill state
|
||||
REG_S ra, RAOFF(sp) # save state
|
||||
REG_S a0, A0OFF(sp)
|
||||
# call sigprocmask(int how ignored, sigset_t* null, sigset_t* SC_MASK(a0)):
|
||||
LA a2, SC_MASK_OFFSET(a0) # gets current signal mask
|
||||
li a0, 0 # how; ignored when new mask is null
|
||||
li a1, 0 # null new mask
|
||||
jal sigprocmask # get current signal mask
|
||||
REG_L a0, A0OFF(sp)
|
||||
|
||||
move a0, zero # get current signal mask
|
||||
jal sigblock
|
||||
|
||||
REG_L v1, A0OFF(sp) # v1 = jmpbuf
|
||||
REG_S v0, SC_MASK(v1) # save sc_mask = sigblock(0)
|
||||
|
||||
REG_L a0, A0OFF(sp) # restore jmpbuf
|
||||
REG_L ra, RAOFF(sp)
|
||||
1:
|
||||
li v0, 0xACEDBADE # sigcontext magic number
|
||||
sw v0, SC_MAGIC_OFFSET(a0)
|
||||
# callee-saved long-sized regs:
|
||||
REG_S ra, SC_REGS+0*REGSZ(a0)
|
||||
REG_S s0, SC_REGS+1*REGSZ(a0)
|
||||
REG_S s1, SC_REGS+2*REGSZ(a0)
|
||||
REG_S s2, SC_REGS+3*REGSZ(a0)
|
||||
REG_S s3, SC_REGS+4*REGSZ(a0)
|
||||
REG_S s4, SC_REGS+5*REGSZ(a0)
|
||||
REG_S s5, SC_REGS+6*REGSZ(a0)
|
||||
REG_S s6, SC_REGS+7*REGSZ(a0)
|
||||
REG_S s7, SC_REGS+8*REGSZ(a0)
|
||||
REG_S s8, SC_REGS+9*REGSZ(a0)
|
||||
REG_L v0, GPOFF(sp)
|
||||
REG_S v0, SC_REGS+10*REGSZ(a0) # save gp
|
||||
PTR_ADDU v0, sp, FRAMESZ
|
||||
REG_S v0, SC_REGS+11*REGSZ(a0) # save orig sp
|
||||
|
||||
cfc1 v0, $31
|
||||
|
||||
#ifdef __LP64__
|
||||
# callee-saved fp regs on mips n64 ABI are $f24..$f31
|
||||
s.d $f24, SC_FPREGS+0*REGSZ_FP(a0)
|
||||
s.d $f25, SC_FPREGS+1*REGSZ_FP(a0)
|
||||
s.d $f26, SC_FPREGS+2*REGSZ_FP(a0)
|
||||
s.d $f27, SC_FPREGS+3*REGSZ_FP(a0)
|
||||
s.d $f28, SC_FPREGS+4*REGSZ_FP(a0)
|
||||
s.d $f29, SC_FPREGS+5*REGSZ_FP(a0)
|
||||
s.d $f30, SC_FPREGS+6*REGSZ_FP(a0)
|
||||
s.d $f31, SC_FPREGS+7*REGSZ_FP(a0)
|
||||
REG_S ra, SC_PC(a0) # sc_pc = return address
|
||||
#if defined(__mips64)
|
||||
dli v0, 0xACEDBADE # sigcontext magic number
|
||||
#else
|
||||
# callee-saved fp regs on mips o32 ABI are
|
||||
# the even-numbered double fp regs $f20,$f22,...$f30
|
||||
s.d $f20, SC_FPREGS+0*REGSZ_FP(a0)
|
||||
s.d $f22, SC_FPREGS+1*REGSZ_FP(a0)
|
||||
s.d $f24, SC_FPREGS+2*REGSZ_FP(a0)
|
||||
s.d $f26, SC_FPREGS+3*REGSZ_FP(a0)
|
||||
s.d $f28, SC_FPREGS+4*REGSZ_FP(a0)
|
||||
s.d $f30, SC_FPREGS+5*REGSZ_FP(a0)
|
||||
li v0, 0xACEDBADE # sigcontext magic number
|
||||
#endif
|
||||
sw v0, SC_FPSR_OFFSET(a0)
|
||||
REG_S v0, SC_REGS+ZERO*REGSZ(a0)
|
||||
REG_S s0, SC_REGS+S0*REGSZ(a0)
|
||||
REG_S s1, SC_REGS+S1*REGSZ(a0)
|
||||
REG_S s2, SC_REGS+S2*REGSZ(a0)
|
||||
REG_S s3, SC_REGS+S3*REGSZ(a0)
|
||||
REG_S s4, SC_REGS+S4*REGSZ(a0)
|
||||
REG_S s5, SC_REGS+S5*REGSZ(a0)
|
||||
REG_S s6, SC_REGS+S6*REGSZ(a0)
|
||||
REG_S s7, SC_REGS+S7*REGSZ(a0)
|
||||
REG_S s8, SC_REGS+S8*REGSZ(a0)
|
||||
REG_L v0, GPOFF(sp)
|
||||
REG_S v0, SC_REGS+GP*REGSZ(a0)
|
||||
PTR_ADDU v0, sp, FRAMESZ
|
||||
REG_S v0, SC_REGS+SP*REGSZ(a0)
|
||||
|
||||
#if !defined(SOFTFLOAT)
|
||||
li v0, 1 # be nice if we could tell
|
||||
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
|
||||
cfc1 v0, $31
|
||||
s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
|
||||
s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
|
||||
s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
|
||||
s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
|
||||
s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
|
||||
s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
|
||||
#if _MIPS_FPSET == 32
|
||||
s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
|
||||
s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
|
||||
s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
|
||||
s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
|
||||
s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
|
||||
s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
|
||||
#endif
|
||||
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
|
||||
#endif /* !SOFTFLOAT */
|
||||
move v0, zero
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
j ra
|
||||
END(sigsetjmp)
|
||||
|
||||
|
||||
# Alternate entry points:
|
||||
|
||||
NON_LEAF(setjmp, FRAMESZ, ra)
|
||||
.mask 0x80000000, RAOFF
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, setjmp) # can't share sigsetjmp's gp code
|
||||
SAVE_GP(GPOFF)
|
||||
.set reorder
|
||||
|
||||
li a1, 1 # save/restore signals state
|
||||
b setjmp_common # tail call
|
||||
botch:
|
||||
jal longjmperror
|
||||
jal abort
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
END(setjmp)
|
||||
|
||||
|
||||
NON_LEAF(_setjmp, FRAMESZ, ra)
|
||||
.mask 0x80000000, RAOFF
|
||||
LEAF(longjmp, FRAMESZ)
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, _setjmp) # can't share sigsetjmp's gp code
|
||||
SETUP_GP64(GPOFF, longjmp)
|
||||
SAVE_GP(GPOFF)
|
||||
.set reorder
|
||||
sw a1, A1OFF(sp)
|
||||
sw a0, A0OFF(sp)
|
||||
|
||||
li a1, 0 # don't save/restore signals
|
||||
b setjmp_common # tail call
|
||||
END(_setjmp)
|
||||
lw a0, SC_MASK(a0)
|
||||
jal sigsetmask
|
||||
|
||||
lw a0, A0OFF(sp)
|
||||
lw a1, A1OFF(sp)
|
||||
|
||||
NON_LEAF(siglongjmp, FRAMESZ, ra)
|
||||
.mask 0x80000000, RAOFF
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, siglongjmp)
|
||||
SAVE_GP(GPOFF)
|
||||
.set reorder
|
||||
.set noreorder
|
||||
REG_L v0, SC_REGS+ZERO*REGSZ(a0)
|
||||
bne v0, 0xACEDBADE, botch # jump if error
|
||||
REG_L ra, SC_PC(a0)
|
||||
REG_L s0, SC_REGS+S0*REGSZ(a0)
|
||||
REG_L s1, SC_REGS+S1*REGSZ(a0)
|
||||
REG_L s2, SC_REGS+S2*REGSZ(a0)
|
||||
REG_L s3, SC_REGS+S3*REGSZ(a0)
|
||||
REG_L s4, SC_REGS+S4*REGSZ(a0)
|
||||
REG_L s5, SC_REGS+S5*REGSZ(a0)
|
||||
REG_L s6, SC_REGS+S6*REGSZ(a0)
|
||||
REG_L s7, SC_REGS+S7*REGSZ(a0)
|
||||
REG_L s8, SC_REGS+S8*REGSZ(a0)
|
||||
REG_L gp, SC_REGS+GP*REGSZ(a0)
|
||||
REG_L sp, SC_REGS+SP*REGSZ(a0)
|
||||
|
||||
#ifndef __LP64__
|
||||
li t0, ~7
|
||||
and a0, t0 # round jmpbuf addr DOWN to 8-byte boundary
|
||||
#endif
|
||||
lw v0, SC_MAGIC_OFFSET(a0)
|
||||
li t0, 0xACEDBADE
|
||||
bne v0, t0, longjmp_botch # jump if error
|
||||
|
||||
lw t0, SC_FLAG_OFFSET(a0) # get savesigs flag
|
||||
beqz t0, 1f # restore signal mask?
|
||||
|
||||
REG_S a1, A1OFF(sp) # temp spill
|
||||
REG_S a0, A0OFF(sp)
|
||||
# call sigprocmask(int how SIG_SETMASK, sigset_t* SC_MASK(a0), sigset_t* null):
|
||||
LA a1, SC_MASK_OFFSET(a0) # signals being restored
|
||||
li a0, 3 # mips SIG_SETMASK
|
||||
li a2, 0 # null
|
||||
jal sigprocmask # restore signal mask
|
||||
REG_L a0, A0OFF(sp)
|
||||
REG_L a1, A1OFF(sp)
|
||||
1:
|
||||
# callee-saved long-sized regs:
|
||||
REG_L ra, SC_REGS+0*REGSZ(a0)
|
||||
REG_L s0, SC_REGS+1*REGSZ(a0)
|
||||
REG_L s1, SC_REGS+2*REGSZ(a0)
|
||||
REG_L s2, SC_REGS+3*REGSZ(a0)
|
||||
REG_L s3, SC_REGS+4*REGSZ(a0)
|
||||
REG_L s4, SC_REGS+5*REGSZ(a0)
|
||||
REG_L s5, SC_REGS+6*REGSZ(a0)
|
||||
REG_L s6, SC_REGS+7*REGSZ(a0)
|
||||
REG_L s7, SC_REGS+8*REGSZ(a0)
|
||||
REG_L s8, SC_REGS+9*REGSZ(a0)
|
||||
REG_L gp, SC_REGS+10*REGSZ(a0)
|
||||
REG_L sp, SC_REGS+11*REGSZ(a0)
|
||||
|
||||
lw v0, SC_FPSR_OFFSET(a0)
|
||||
ctc1 v0, $31 # restore old fr mode before fp values
|
||||
#ifdef __LP64__
|
||||
# callee-saved fp regs on mips n64 ABI are $f24..$f31
|
||||
l.d $f24, SC_FPREGS+0*REGSZ_FP(a0)
|
||||
l.d $f25, SC_FPREGS+1*REGSZ_FP(a0)
|
||||
l.d $f26, SC_FPREGS+2*REGSZ_FP(a0)
|
||||
l.d $f27, SC_FPREGS+3*REGSZ_FP(a0)
|
||||
l.d $f28, SC_FPREGS+4*REGSZ_FP(a0)
|
||||
l.d $f29, SC_FPREGS+5*REGSZ_FP(a0)
|
||||
l.d $f30, SC_FPREGS+6*REGSZ_FP(a0)
|
||||
l.d $f31, SC_FPREGS+7*REGSZ_FP(a0)
|
||||
#else
|
||||
# callee-saved fp regs on mips o32 ABI are
|
||||
# the even-numbered double fp regs $f20,$f22,...$f30
|
||||
l.d $f20, SC_FPREGS+0*REGSZ_FP(a0)
|
||||
l.d $f22, SC_FPREGS+1*REGSZ_FP(a0)
|
||||
l.d $f24, SC_FPREGS+2*REGSZ_FP(a0)
|
||||
l.d $f26, SC_FPREGS+3*REGSZ_FP(a0)
|
||||
l.d $f28, SC_FPREGS+4*REGSZ_FP(a0)
|
||||
l.d $f30, SC_FPREGS+5*REGSZ_FP(a0)
|
||||
#if !defined(SOFTFLOAT)
|
||||
REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
|
||||
ctc1 v0, $31
|
||||
l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
|
||||
l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
|
||||
l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
|
||||
l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
|
||||
l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
|
||||
l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
|
||||
#if _MIPS_FPSET == 32
|
||||
l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
|
||||
l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
|
||||
l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
|
||||
l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
|
||||
l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
|
||||
l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
|
||||
#endif
|
||||
#endif /* !SOFTFLOAT */
|
||||
bne a1, zero, 1f
|
||||
nop
|
||||
li a1, 1 # never return 0!
|
||||
1:
|
||||
move v0, a1
|
||||
j ra # return to setjmp call site
|
||||
j ra
|
||||
move v0, a1
|
||||
|
||||
longjmp_botch:
|
||||
jal longjmperror
|
||||
jal abort
|
||||
END(siglongjmp)
|
||||
|
||||
ALIAS_SYMBOL(longjmp, siglongjmp)
|
||||
ALIAS_SYMBOL(_longjmp, siglongjmp)
|
||||
END(longjmp)
|
||||
|
@@ -1,8 +1,11 @@
|
||||
/* $OpenBSD: daemon.c,v 1.7 2010/07/27 22:29:09 marco Exp $ */
|
||||
/* $OpenBSD: sigsetjmp.S,v 1.5 2005/08/07 16:40:15 espie Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* Copyright (c) 1991, 1993, 1995,
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Havard Eidnes.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@@ -28,37 +31,47 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <private/bionic_asm.h>
|
||||
#include <machine/regnum.h>
|
||||
#include <machine/setjmp.h>
|
||||
|
||||
int
|
||||
daemon(int nochdir, int noclose)
|
||||
{
|
||||
int fd;
|
||||
/*
|
||||
* trampolines for sigsetjmp and siglongjmp save and restore mask.
|
||||
*
|
||||
*/
|
||||
FRAMESZ= MKFSIZ(1,1)
|
||||
GPOFF= FRAMESZ-2*REGSZ
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
return (-1);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
_exit(0);
|
||||
}
|
||||
LEAF(sigsetjmp, FRAMESZ)
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, sigsetjmp)
|
||||
.set reorder
|
||||
REG_S a1, (_JBLEN*REGSZ)(a0) # save "savemask"
|
||||
bne a1, 0x0, 1f # do saving of signal mask?
|
||||
LA t9, _setjmp
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
jr t9
|
||||
|
||||
if (setsid() == -1)
|
||||
return (-1);
|
||||
1: LA t9, setjmp
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
jr t9
|
||||
END(sigsetjmp)
|
||||
|
||||
if (!nochdir)
|
||||
(void)chdir("/");
|
||||
|
||||
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
(void)dup2(fd, STDIN_FILENO);
|
||||
(void)dup2(fd, STDOUT_FILENO);
|
||||
(void)dup2(fd, STDERR_FILENO);
|
||||
if (fd > 2)
|
||||
(void)close(fd);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LEAF(siglongjmp, FRAMESZ)
|
||||
PTR_SUBU sp, FRAMESZ
|
||||
SETUP_GP64(GPOFF, siglongjmp)
|
||||
.set reorder
|
||||
REG_L t0, (_JBLEN*REGSZ)(a0) # get "savemask"
|
||||
bne t0, 0x0, 1f # restore signal mask?
|
||||
LA t9, _longjmp
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
jr t9
|
||||
1:
|
||||
LA t9, longjmp
|
||||
RESTORE_GP64
|
||||
PTR_ADDU sp, FRAMESZ
|
||||
jr t9
|
||||
END(siglongjmp)
|
@@ -28,7 +28,9 @@
|
||||
#ifndef _MIPS64_ASM_H
|
||||
#define _MIPS64_ASM_H
|
||||
|
||||
#define __bionic_asm_align 4
|
||||
#ifndef _ALIGN_TEXT
|
||||
# define _ALIGN_TEXT .align 4
|
||||
#endif
|
||||
|
||||
#undef __bionic_asm_custom_entry
|
||||
#undef __bionic_asm_custom_end
|
||||
|
@@ -121,7 +121,6 @@
|
||||
#define DT_MIPS_GOTSYM 0x70000013 /* first dynamic sym in got */
|
||||
#define DT_MIPS_HIPAGENO 0x70000014
|
||||
#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */
|
||||
#define DT_MIPS_RLD_MAP2 0x70000035 /* offset of loader map, used for PIE */
|
||||
|
||||
/*
|
||||
* ELF Flags
|
||||
|
70
libc/arch-mips/include/machine/endian.h
Normal file
70
libc/arch-mips/include/machine/endian.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* $OpenBSD: endian.h,v 1.5 2006/02/27 23:35:59 miod Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (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 _MIPS64_ENDIAN_H_
|
||||
#define _MIPS64_ENDIAN_H_
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
|
||||
#define __swap16md(x) ({ \
|
||||
register uint16_t _x = (x); \
|
||||
register uint16_t _r; \
|
||||
__asm volatile ("wsbh %0, %1" : "=r" (_r) : "r" (_x)); \
|
||||
_r; \
|
||||
})
|
||||
|
||||
#define __swap32md(x) ({ \
|
||||
register uint32_t _x = (x); \
|
||||
register uint32_t _r; \
|
||||
__asm volatile ("wsbh %0, %1; rotr %0, %0, 16" : "=r" (_r) : "r" (_x)); \
|
||||
_r; \
|
||||
})
|
||||
|
||||
#define __swap64md(x) ({ \
|
||||
uint64_t _swap64md_x = (x); \
|
||||
(uint64_t) __swap32md(_swap64md_x >> 32) | \
|
||||
(uint64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
|
||||
})
|
||||
|
||||
/* Tell sys/endian.h we have MD variants of the swap macros. */
|
||||
#define MD_SWAP
|
||||
|
||||
#endif /* __mips32r2__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#if defined(__MIPSEB__)
|
||||
#define _BYTE_ORDER _BIG_ENDIAN
|
||||
#else
|
||||
#define _BYTE_ORDER _LITTLE_ENDIAN
|
||||
#endif
|
||||
#define __STRICT_ALIGNMENT
|
||||
#include <sys/types.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
#endif /* _MIPS64_ENDIAN_H_ */
|
188
libc/arch-mips/include/machine/exec.h
Normal file
188
libc/arch-mips/include/machine/exec.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/* $OpenBSD: exec.h,v 1.1 2004/10/18 19:05:36 grange Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (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 _MIPS64_EXEC_H_
|
||||
#define _MIPS64_EXEC_H_
|
||||
|
||||
#define __LDPGSZ 4096
|
||||
|
||||
/*
|
||||
* Define what exec "formats" we should handle.
|
||||
*/
|
||||
#define NATIVE_EXEC_ELF
|
||||
#define NATIVE_ELFSIZE 64
|
||||
#define EXEC_SCRIPT
|
||||
|
||||
/*
|
||||
* If included from sys/exec.h define kernels ELF format.
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
#define ARCH_ELFSIZE 64
|
||||
#define DB_ELFSIZE 64
|
||||
#define ELF_TARG_CLASS ELFCLASS64
|
||||
#else
|
||||
#define ARCH_ELFSIZE 32
|
||||
#define DB_ELFSIZE 32
|
||||
#define ELF_TARG_CLASS ELFCLASS32
|
||||
#endif
|
||||
|
||||
#if defined(__MIPSEB__)
|
||||
#define ELF_TARG_DATA ELFDATA2MSB
|
||||
#else
|
||||
#define ELF_TARG_DATA ELFDATA2LSB
|
||||
#endif
|
||||
#define ELF_TARG_MACH EM_MIPS
|
||||
|
||||
#define _NLIST_DO_ELF
|
||||
|
||||
#if defined(_LP64)
|
||||
#define _KERN_DO_ELF64
|
||||
#if defined(COMPAT_O32)
|
||||
#define _KERN_DO_ELF
|
||||
#endif
|
||||
#else
|
||||
#define _KERN_DO_ELF
|
||||
#endif
|
||||
|
||||
/* Information taken from MIPS ABI supplemental */
|
||||
|
||||
/* Architecture dependent Segment types - p_type */
|
||||
#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
|
||||
|
||||
/* Architecture dependent d_tag field for Elf32_Dyn. */
|
||||
#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime Linker Interface ID */
|
||||
#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
|
||||
#define DT_MIPS_ICHECKSUM 0x70000003 /* Cksum of ext. str. and com. sizes */
|
||||
#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
|
||||
#define DT_MIPS_FLAGS 0x70000005 /* Flags */
|
||||
#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Segment base address */
|
||||
#define DT_MIPS_CONFLICT 0x70000008 /* Adr of .conflict section */
|
||||
#define DT_MIPS_LIBLIST 0x70000009 /* Address of .liblist section */
|
||||
#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local .GOT entries */
|
||||
#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of .conflict entries */
|
||||
#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of .liblist entries */
|
||||
#define DT_MIPS_SYMTABNO 0x70000011 /* Number of .dynsym entries */
|
||||
#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
|
||||
#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in .dynsym */
|
||||
#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
|
||||
#define DT_MIPS_RLD_MAP 0x70000016 /* Address of debug map pointer */
|
||||
|
||||
#define DT_PROCNUM (DT_MIPS_RLD_MAP - DT_LOPROC + 1)
|
||||
|
||||
/*
|
||||
* Legal values for e_flags field of Elf32_Ehdr.
|
||||
*/
|
||||
#define EF_MIPS_NOREORDER 0x00000001 /* .noreorder was used */
|
||||
#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
|
||||
#define EF_MIPS_CPIC 0x00000004 /* Uses PIC calling sequence */
|
||||
#define EF_MIPS_ABI2 0x00000020 /* -n32 on Irix 6 */
|
||||
#define EF_MIPS_32BITMODE 0x00000100 /* 64 bit in 32 bit mode... */
|
||||
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
|
||||
#define E_MIPS_ARCH_1 0x00000000
|
||||
#define E_MIPS_ARCH_2 0x10000000
|
||||
#define E_MIPS_ARCH_3 0x20000000
|
||||
#define E_MIPS_ARCH_4 0x30000000
|
||||
#define EF_MIPS_ABI 0x0000f000 /* ABI level */
|
||||
#define E_MIPS_ABI_NONE 0x00000000 /* ABI level not set */
|
||||
#define E_MIPS_ABI_O32 0x00001000
|
||||
#define E_MIPS_ABI_O64 0x00002000
|
||||
#define E_MIPS_ABI_EABI32 0x00004000
|
||||
#define E_MIPS_ABI_EABI64 0x00004000
|
||||
|
||||
/*
|
||||
* Mips special sections.
|
||||
*/
|
||||
#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
|
||||
#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
|
||||
#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
|
||||
|
||||
/*
|
||||
* Legal values for sh_type field of Elf32_Shdr.
|
||||
*/
|
||||
#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
|
||||
#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
|
||||
#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
|
||||
#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
|
||||
#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information */
|
||||
#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
|
||||
|
||||
/*
|
||||
* Legal values for sh_flags field of Elf32_Shdr.
|
||||
*/
|
||||
#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Entries found in sections of type SHT_MIPS_GPTAB.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
Elf32_Word gt_current_g_value; /* -G val used in compilation */
|
||||
Elf32_Word gt_unused; /* Not used */
|
||||
} gt_header; /* First entry in section */
|
||||
struct {
|
||||
Elf32_Word gt_g_value; /* If this val were used for -G */
|
||||
Elf32_Word gt_bytes; /* This many bytes would be used */
|
||||
} gt_entry; /* Subsequent entries in section */
|
||||
} Elf32_gptab;
|
||||
|
||||
/*
|
||||
* Entry found in sections of type SHT_MIPS_REGINFO.
|
||||
*/
|
||||
typedef struct {
|
||||
Elf32_Word ri_gprmask; /* General registers used */
|
||||
Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
|
||||
Elf32_Sword ri_gp_value; /* $gp register value */
|
||||
} Elf32_RegInfo;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Mips relocations.
|
||||
*/
|
||||
|
||||
#define R_MIPS_NONE 0 /* No reloc */
|
||||
#define R_MIPS_16 1 /* Direct 16 bit */
|
||||
#define R_MIPS_32 2 /* Direct 32 bit */
|
||||
#define R_MIPS_REL32 3 /* PC relative 32 bit */
|
||||
#define R_MIPS_26 4 /* Direct 26 bit shifted */
|
||||
#define R_MIPS_HI16 5 /* High 16 bit */
|
||||
#define R_MIPS_LO16 6 /* Low 16 bit */
|
||||
#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
|
||||
#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
|
||||
#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
|
||||
#define R_MIPS_PC16 10 /* PC relative 16 bit */
|
||||
#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
|
||||
#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
|
||||
|
||||
#define R_MIPS_64 18
|
||||
|
||||
#define R_MIPS_REL32_64 ((R_MIPS_64 << 8) | R_MIPS_REL32)
|
||||
|
||||
|
||||
#endif /* !_MIPS64_EXEC_H_ */
|
@@ -37,13 +37,6 @@
|
||||
#ifndef _MIPS_REGDEF_H_
|
||||
#define _MIPS_REGDEF_H_
|
||||
|
||||
#if (_MIPS_SIM == _ABI64) && !defined(__mips_n64)
|
||||
#define __mips_n64 1
|
||||
#endif
|
||||
#if (_MIPS_SIM == _ABIN32) && !defined(__mips_n32)
|
||||
#define __mips_n32 1
|
||||
#endif
|
||||
|
||||
#define zero $0 /* always zero */
|
||||
#define AT $at /* assembler temp */
|
||||
#define v0 $2 /* return value */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user