Merge Android R

Bug: 168057903
Merged-In: I88f6774ca9985fb50f015756b8f8508d4691dc62
Change-Id: Iefe2872d29836b77344479ad2552a9c03d81bdcb
This commit is contained in:
Xin Li 2020-09-09 20:21:27 -07:00
commit e1ebeab9c5
130 changed files with 1703 additions and 30000 deletions

View File

@ -754,6 +754,8 @@ cc_test {
"mdns_test.cpp",
],
test_config: "adb_test.xml",
shared_libs: [
"liblog",
],

37
adb/adb_test.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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.
-->
<!-- This test config file is auto-generated. -->
<configuration description="Runs adbd_test.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="adbd_test->/data/local/tmp/adbd_test" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="adbd_test" />
</test>
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
<option name="mainline-module-package-name" value="com.google.android.adbd" />
</object>
</configuration>

View File

@ -1,4 +1,4 @@
{
"name": "com.android.adbd",
"version": 1
"version": 300000000
}

View File

@ -305,6 +305,7 @@ static std::pair<ZipArchiveHandle, std::unique_ptr<android::base::MappedFile>> o
static std::vector<int32_t> InstallationPriorityBlocks(borrowed_fd fd, Size fileSize) {
static constexpr std::array<std::string_view, 3> additional_matches = {
"resources.arsc"sv, "AndroidManifest.xml"sv, "classes.dex"sv};
auto [zip, _] = openZipArchive(fd, fileSize);
if (!zip) {
return {};
@ -358,7 +359,7 @@ static std::vector<int32_t> InstallationPriorityBlocks(borrowed_fd fd, Size file
std::vector<int32_t> PriorityBlocksForFile(const std::string& filepath, borrowed_fd fd,
Size fileSize) {
if (!android::base::EndsWithIgnoreCase(filepath, ".apk"sv)) {
if (!android::base::EndsWithIgnoreCase(filepath, ".apk")) {
return {};
}
off64_t signerOffset = SignerBlockOffset(fd, fileSize);

View File

@ -42,7 +42,8 @@ static struct adisconnect adb_disconnect = {adb_disconnected, nullptr};
static void adb_disconnected(void* unused, atransport* t) {
LOG(INFO) << "ADB wifi device disconnected";
adbd_auth_tls_device_disconnected(auth_ctx, kAdbTransportTypeWifi, t->auth_id);
CHECK(t->auth_id.has_value());
adbd_auth_tls_device_disconnected(auth_ctx, kAdbTransportTypeWifi, t->auth_id.value());
}
// TODO(b/31559095): need bionic host so that we can use 'prop_info' returned

View File

@ -207,15 +207,27 @@ void adbd_cloexec_auth_socket() {
}
static void adbd_auth_key_authorized(void* arg, uint64_t id) {
LOG(INFO) << "adb client authorized";
LOG(INFO) << "adb client " << id << " authorized";
fdevent_run_on_main_thread([=]() {
LOG(INFO) << "arg = " << reinterpret_cast<uintptr_t>(arg);
auto* transport = transport_from_callback_arg(arg);
if (!transport) {
LOG(ERROR) << "authorization received for deleted transport, ignoring";
LOG(ERROR) << "authorization received for deleted transport (" << id << "), ignoring";
return;
}
transport->auth_id = id;
if (transport->auth_id.has_value()) {
if (transport->auth_id.value() != id) {
LOG(ERROR)
<< "authorization received, but auth id doesn't match, ignoring (expected "
<< transport->auth_id.value() << ", got " << id << ")";
return;
}
} else {
// Older versions (i.e. dogfood/beta builds) of libadbd_auth didn't pass the initial
// auth id to us, so we'll just have to trust it until R ships and we can retcon this.
transport->auth_id = id;
}
adbd_auth_verified(transport);
});
}
@ -265,14 +277,20 @@ void adbd_auth_verified(atransport* t) {
static void adb_disconnected(void* unused, atransport* t) {
LOG(INFO) << "ADB disconnect";
adbd_auth_notify_disconnect(auth_ctx, t->auth_id);
CHECK(t->auth_id.has_value());
adbd_auth_notify_disconnect(auth_ctx, t->auth_id.value());
}
void adbd_auth_confirm_key(atransport* t) {
LOG(INFO) << "prompting user to authorize key";
t->AddDisconnect(&adb_disconnect);
adbd_auth_prompt_user(auth_ctx, t->auth_key.data(), t->auth_key.size(),
transport_to_callback_arg(t));
if (adbd_auth_prompt_user_with_id) {
t->auth_id = adbd_auth_prompt_user_with_id(auth_ctx, t->auth_key.data(), t->auth_key.size(),
transport_to_callback_arg(t));
} else {
adbd_auth_prompt_user(auth_ctx, t->auth_key.data(), t->auth_key.size(),
transport_to_callback_arg(t));
}
}
void adbd_notify_framework_connected_key(atransport* t) {

View File

@ -27,6 +27,7 @@
#include <list>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <thread>
@ -320,7 +321,7 @@ class atransport : public enable_weak_from_this<atransport> {
#if !ADB_HOST
// Used to provide the key to the framework.
std::string auth_key;
uint64_t auth_id;
std::optional<uint64_t> auth_id;
#endif
bool IsTcpDevice() const { return type == kTransportLocal; }

View File

@ -69,4 +69,4 @@ class BootEventRecordStore {
DISALLOW_COPY_AND_ASSIGN(BootEventRecordStore);
};
#endif // BOOT_EVENT_RECORD_STORE_H_
#endif // BOOT_EVENT_RECORD_STORE_H_

View File

@ -740,15 +740,33 @@ static int __mount(const std::string& source, const std::string& target, const F
unsigned long mountflags = entry.flags;
int ret = 0;
int save_errno = 0;
int gc_allowance = 0;
std::string opts;
bool try_f2fs_gc_allowance = is_f2fs(entry.fs_type) && entry.fs_checkpoint_opts.length() > 0;
Timer t;
do {
if (save_errno == EINVAL && try_f2fs_gc_allowance) {
PINFO << "Kernel does not support checkpoint=disable:[n]%, trying without.";
try_f2fs_gc_allowance = false;
}
if (try_f2fs_gc_allowance) {
opts = entry.fs_options + entry.fs_checkpoint_opts + ":" +
std::to_string(gc_allowance) + "%";
} else {
opts = entry.fs_options;
}
if (save_errno == EAGAIN) {
PINFO << "Retrying mount (source=" << source << ",target=" << target
<< ",type=" << entry.fs_type << ")=" << ret << "(" << save_errno << ")";
<< ",type=" << entry.fs_type << ", gc_allowance=" << gc_allowance << "%)=" << ret
<< "(" << save_errno << ")";
}
ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
entry.fs_options.c_str());
opts.c_str());
save_errno = errno;
} while (ret && save_errno == EAGAIN);
if (try_f2fs_gc_allowance) gc_allowance += 10;
} while ((ret && save_errno == EAGAIN && gc_allowance <= 100) ||
(ret && save_errno == EINVAL && try_f2fs_gc_allowance));
const char* target_missing = "";
const char* source_missing = "";
if (save_errno == ENOENT) {
@ -764,6 +782,8 @@ static int __mount(const std::string& source, const std::string& target, const F
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
fs_mgr_set_blk_ro(source);
}
android::base::SetProperty("ro.boottime.init.mount." + Basename(target),
std::to_string(t.duration().count()));
errno = save_errno;
return ret;
}
@ -1092,7 +1112,7 @@ class CheckpointManager {
bool UpdateCheckpointPartition(FstabEntry* entry, const std::string& block_device) {
if (entry->fs_mgr_flags.checkpoint_fs) {
if (is_f2fs(entry->fs_type)) {
entry->fs_options += ",checkpoint=disable";
entry->fs_checkpoint_opts = ",checkpoint=disable";
} else {
LERROR << entry->fs_type << " does not implement checkpoints.";
}
@ -1952,21 +1972,19 @@ static bool InstallZramDevice(const std::string& device) {
return true;
}
static bool PrepareZramDevice(const std::string& loop, off64_t size, const std::string& bdev) {
if (loop.empty() && bdev.empty()) return true;
static bool PrepareZramBackingDevice(off64_t size) {
if (bdev.length()) {
return InstallZramDevice(bdev);
}
constexpr const char* file_path = "/data/per_boot/zram_swap";
if (size == 0) return true;
// Prepare target path
unique_fd target_fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600)));
unique_fd target_fd(TEMP_FAILURE_RETRY(open(file_path, O_RDWR | O_CREAT | O_CLOEXEC, 0600)));
if (target_fd.get() == -1) {
PERROR << "Cannot open target path: " << loop;
PERROR << "Cannot open target path: " << file_path;
return false;
}
if (fallocate(target_fd.get(), 0, 0, size) < 0) {
PERROR << "Cannot truncate target path: " << loop;
PERROR << "Cannot truncate target path: " << file_path;
return false;
}
@ -1998,11 +2016,10 @@ bool fs_mgr_swapon_all(const Fstab& fstab) {
continue;
}
if (!PrepareZramDevice(entry.zram_loopback_path, entry.zram_loopback_size, entry.zram_backing_dev_path)) {
LERROR << "Skipping losetup for '" << entry.blk_device << "'";
}
if (entry.zram_size > 0) {
if (!PrepareZramBackingDevice(entry.zram_backingdev_size)) {
LERROR << "Failure of zram backing device file for '" << entry.blk_device << "'";
}
// A zram_size was specified, so we need to configure the
// device. There is no point in having multiple zram devices
// on a system (all the memory comes from the same pool) so

View File

@ -286,15 +286,10 @@ void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
} else if (StartsWith(flag, "sysfs_path=")) {
// The path to trigger device gc by idle-maint of vold.
entry->sysfs_path = arg;
} else if (StartsWith(flag, "zram_loopback_path=")) {
// The path to use loopback for zram.
entry->zram_loopback_path = arg;
} else if (StartsWith(flag, "zram_loopback_size=")) {
if (!ParseByteCount(arg, &entry->zram_loopback_size)) {
LWARNING << "Warning: zram_loopback_size= flag malformed: " << arg;
} else if (StartsWith(flag, "zram_backingdev_size=")) {
if (!ParseByteCount(arg, &entry->zram_backingdev_size)) {
LWARNING << "Warning: zram_backingdev_size= flag malformed: " << arg;
}
} else if (StartsWith(flag, "zram_backing_dev_path=")) {
entry->zram_backing_dev_path = arg;
} else {
LWARNING << "Warning: unknown flag: " << flag;
}

View File

@ -36,6 +36,7 @@ struct FstabEntry {
std::string fs_type;
unsigned long flags = 0;
std::string fs_options;
std::string fs_checkpoint_opts;
std::string key_loc;
std::string metadata_key_dir;
std::string metadata_encryption;
@ -51,9 +52,7 @@ struct FstabEntry {
off64_t logical_blk_size = 0;
std::string sysfs_path;
std::string vbmeta_partition;
std::string zram_loopback_path;
uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default;
std::string zram_backing_dev_path;
uint64_t zram_backingdev_size = 0;
std::string avb_keys;
struct FsMgrFlags {

View File

@ -394,9 +394,9 @@ TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_AllBad) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
std::string fstab_contents = R"fs(
source none0 swap defaults encryptable,forceencrypt,fileencryption,forcefdeorfbe,keydirectory,length,swapprio,zramsize,max_comp_streams,reservedsize,eraseblk,logicalblk,sysfs_path,zram_loopback_path,zram_loopback_size,zram_backing_dev_path
source none0 swap defaults encryptable,forceencrypt,fileencryption,forcefdeorfbe,keydirectory,length,swapprio,zramsize,max_comp_streams,reservedsize,eraseblk,logicalblk,sysfs_path,zram_backingdev_size
source none1 swap defaults encryptable=,forceencrypt=,fileencryption=,keydirectory=,length=,swapprio=,zramsize=,max_comp_streams=,avb=,reservedsize=,eraseblk=,logicalblk=,sysfs_path=,zram_loopback_path=,zram_loopback_size=,zram_backing_dev_path=
source none1 swap defaults encryptable=,forceencrypt=,fileencryption=,keydirectory=,length=,swapprio=,zramsize=,max_comp_streams=,avb=,reservedsize=,eraseblk=,logicalblk=,sysfs_path=,zram_backingdev_size=
source none2 swap defaults forcefdeorfbe=
@ -426,9 +426,7 @@ source none2 swap defaults forcefdeorfbe=
EXPECT_EQ(0, entry->erase_blk_size);
EXPECT_EQ(0, entry->logical_blk_size);
EXPECT_EQ("", entry->sysfs_path);
EXPECT_EQ("", entry->zram_loopback_path);
EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
EXPECT_EQ("", entry->zram_backing_dev_path);
EXPECT_EQ(0U, entry->zram_backingdev_size);
entry++;
EXPECT_EQ("none1", entry->mount_point);
@ -453,9 +451,7 @@ source none2 swap defaults forcefdeorfbe=
EXPECT_EQ(0, entry->erase_blk_size);
EXPECT_EQ(0, entry->logical_blk_size);
EXPECT_EQ("", entry->sysfs_path);
EXPECT_EQ("", entry->zram_loopback_path);
EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
EXPECT_EQ("", entry->zram_backing_dev_path);
EXPECT_EQ(0U, entry->zram_backingdev_size);
entry++;
// forcefdeorfbe has its own encryption_options defaults, so test it separately.
@ -960,14 +956,10 @@ TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Zram) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
std::string fstab_contents = R"fs(
source none0 swap defaults zram_loopback_path=/dev/path
source none1 swap defaults zram_loopback_size=blah
source none2 swap defaults zram_loopback_size=2
source none3 swap defaults zram_loopback_size=1K
source none4 swap defaults zram_loopback_size=2m
source none5 swap defaults zram_backing_dev_path=/dev/path2
source none1 swap defaults zram_backingdev_size=blah
source none2 swap defaults zram_backingdev_size=2
source none3 swap defaults zram_backingdev_size=1K
source none4 swap defaults zram_backingdev_size=2m
)fs";
@ -975,31 +967,25 @@ source none5 swap defaults zram_backing_dev_path=/dev/path2
Fstab fstab;
EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
ASSERT_EQ(6U, fstab.size());
ASSERT_EQ(4U, fstab.size());
auto entry = fstab.begin();
EXPECT_EQ("none0", entry->mount_point);
EXPECT_EQ("/dev/path", entry->zram_loopback_path);
entry++;
EXPECT_EQ("none1", entry->mount_point);
EXPECT_EQ(512U * 1024U * 1024U, entry->zram_loopback_size);
EXPECT_EQ(0U, entry->zram_backingdev_size);
entry++;
EXPECT_EQ("none2", entry->mount_point);
EXPECT_EQ(2U, entry->zram_loopback_size);
EXPECT_EQ(2U, entry->zram_backingdev_size);
entry++;
EXPECT_EQ("none3", entry->mount_point);
EXPECT_EQ(1024U, entry->zram_loopback_size);
EXPECT_EQ(1024U, entry->zram_backingdev_size);
entry++;
EXPECT_EQ("none4", entry->mount_point);
EXPECT_EQ(2U * 1024U * 1024U, entry->zram_loopback_size);
EXPECT_EQ(2U * 1024U * 1024U, entry->zram_backingdev_size);
entry++;
EXPECT_EQ("none5", entry->mount_point);
EXPECT_EQ("/dev/path2", entry->zram_backing_dev_path);
}
TEST(fs_mgr, DefaultFstabContainsUserdata) {

View File

@ -690,9 +690,12 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
// Reap subcontext pids.
ReapAnyOutstandingChildren();
// 3. send volume shutdown to vold
// 3. send volume abort_fuse and volume shutdown to vold
Service* vold_service = ServiceList::GetInstance().FindService("vold");
if (vold_service != nullptr && vold_service->IsRunning()) {
// Manually abort FUSE connections, since the FUSE daemon is already dead
// at this point, and unmounting it might hang.
CallVdc("volume", "abort_fuse");
CallVdc("volume", "shutdown");
vold_service->Stop();
} else {

View File

@ -195,23 +195,17 @@ cc_library {
},
android_arm: {
srcs: ["arch-arm/memset32.S"],
sanitize: {
misc_undefined: ["integer"],
},
},
android_arm64: {
srcs: ["arch-arm64/android_memset.S"],
sanitize: {
misc_undefined: ["integer"],
},
},
android_x86: {
srcs: [
"arch-x86/android_memset16.S",
"arch-x86/android_memset32.S",
],
// TODO: This is to work around b/29412086.
// Remove once __mulodi4 is available and move the "sanitize" block
// to the android target.
@ -221,10 +215,6 @@ cc_library {
},
android_x86_64: {
srcs: [
"arch-x86_64/android_memset16.S",
"arch-x86_64/android_memset32.S",
],
sanitize: {
misc_undefined: ["integer"],
},
@ -279,7 +269,6 @@ cc_defaults {
"android_get_control_socket_test.cpp",
"ashmem_test.cpp",
"fs_config_test.cpp",
"memset_test.cpp",
"multiuser_test.cpp",
"sched_policy_test.cpp",
"str_parms_test.cpp",

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2006 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.
*/
/*
* memset32.S
*
*/
.syntax unified
.text
.align
.global android_memset32
.type android_memset32, %function
.global android_memset16
.type android_memset16, %function
/*
* Optimized memset32 and memset16 for ARM.
*
* void android_memset16(uint16_t* dst, uint16_t value, size_t size);
* void android_memset32(uint32_t* dst, uint32_t value, size_t size);
*
*/
android_memset16:
.fnstart
cmp r2, #1
bxle lr
/* expand the data to 32 bits */
mov r1, r1, lsl #16
orr r1, r1, r1, lsr #16
/* align to 32 bits */
tst r0, #2
strhne r1, [r0], #2
subne r2, r2, #2
.fnend
android_memset32:
.fnstart
.cfi_startproc
str lr, [sp, #-4]!
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
/* align the destination to a cache-line */
mov r12, r1
mov lr, r1
rsb r3, r0, #0
ands r3, r3, #0x1C
beq .Laligned32
cmp r3, r2
andhi r3, r2, #0x1C
sub r2, r2, r3
/* conditionally writes 0 to 7 words (length in r3) */
movs r3, r3, lsl #28
stmiacs r0!, {r1, lr}
stmiacs r0!, {r1, lr}
stmiami r0!, {r1, lr}
movs r3, r3, lsl #2
strcs r1, [r0], #4
.Laligned32:
mov r3, r1
1: subs r2, r2, #32
stmiahs r0!, {r1,r3,r12,lr}
stmiahs r0!, {r1,r3,r12,lr}
bhs 1b
add r2, r2, #32
/* conditionally stores 0 to 30 bytes */
movs r2, r2, lsl #28
stmiacs r0!, {r1,r3,r12,lr}
stmiami r0!, {r1,lr}
movs r2, r2, lsl #2
strcs r1, [r0], #4
strhmi lr, [r0], #2
ldr lr, [sp], #4
.cfi_def_cfa_offset 0
.cfi_restore lr
bx lr
.cfi_endproc
.fnend

View File

@ -1,211 +0,0 @@
/* Copyright (c) 2012, 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 the Linaro 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.
*/
/* Assumptions:
*
* ARMv8-a, AArch64
* Unaligned accesses
*
*/
/* By default we assume that the DC instruction can be used to zero
data blocks more efficiently. In some circumstances this might be
unsafe, for example in an asymmetric multiprocessor environment with
different DC clear lengths (neither the upper nor lower lengths are
safe to use). */
#define dst x0
#define count x2
#define tmp1 x3
#define tmp1w w3
#define tmp2 x4
#define tmp2w w4
#define zva_len_x x5
#define zva_len w5
#define zva_bits_x x6
#define A_l x1
#define A_lw w1
#define tmp3w w9
#define ENTRY(f) \
.text; \
.globl f; \
.align 0; \
.type f, %function; \
f: \
.cfi_startproc \
#define END(f) \
.cfi_endproc; \
.size f, .-f; \
ENTRY(android_memset16)
ands A_lw, A_lw, #0xffff
b.eq .Lzero_mem
orr A_lw, A_lw, A_lw, lsl #16
b .Lexpand_to_64
END(android_memset16)
ENTRY(android_memset32)
cmp A_lw, #0
b.eq .Lzero_mem
.Lexpand_to_64:
orr A_l, A_l, A_l, lsl #32
.Ltail_maybe_long:
cmp count, #64
b.ge .Lnot_short
.Ltail_maybe_tiny:
cmp count, #15
b.le .Ltail15tiny
.Ltail63:
ands tmp1, count, #0x30
b.eq .Ltail15
add dst, dst, tmp1
cmp tmp1w, #0x20
b.eq 1f
b.lt 2f
stp A_l, A_l, [dst, #-48]
1:
stp A_l, A_l, [dst, #-32]
2:
stp A_l, A_l, [dst, #-16]
.Ltail15:
and count, count, #15
add dst, dst, count
stp A_l, A_l, [dst, #-16] /* Repeat some/all of last store. */
ret
.Ltail15tiny:
/* Set up to 15 bytes. Does not assume earlier memory
being set. */
tbz count, #3, 1f
str A_l, [dst], #8
1:
tbz count, #2, 1f
str A_lw, [dst], #4
1:
tbz count, #1, 1f
strh A_lw, [dst], #2
1:
ret
/* Critical loop. Start at a new cache line boundary. Assuming
* 64 bytes per line, this ensures the entire loop is in one line. */
.p2align 6
.Lnot_short:
neg tmp2, dst
ands tmp2, tmp2, #15
b.eq 2f
/* Bring DST to 128-bit (16-byte) alignment. We know that there's
* more than that to set, so we simply store 16 bytes and advance by
* the amount required to reach alignment. */
sub count, count, tmp2
stp A_l, A_l, [dst]
add dst, dst, tmp2
/* There may be less than 63 bytes to go now. */
cmp count, #63
b.le .Ltail63
2:
sub dst, dst, #16 /* Pre-bias. */
sub count, count, #64
1:
stp A_l, A_l, [dst, #16]
stp A_l, A_l, [dst, #32]
stp A_l, A_l, [dst, #48]
stp A_l, A_l, [dst, #64]!
subs count, count, #64
b.ge 1b
tst count, #0x3f
add dst, dst, #16
b.ne .Ltail63
ret
/* For zeroing memory, check to see if we can use the ZVA feature to
* zero entire 'cache' lines. */
.Lzero_mem:
mov A_l, #0
cmp count, #63
b.le .Ltail_maybe_tiny
neg tmp2, dst
ands tmp2, tmp2, #15
b.eq 1f
sub count, count, tmp2
stp A_l, A_l, [dst]
add dst, dst, tmp2
cmp count, #63
b.le .Ltail63
1:
/* For zeroing small amounts of memory, it's not worth setting up
* the line-clear code. */
cmp count, #128
b.lt .Lnot_short
mrs tmp1, dczid_el0
tbnz tmp1, #4, .Lnot_short
mov tmp3w, #4
and zva_len, tmp1w, #15 /* Safety: other bits reserved. */
lsl zva_len, tmp3w, zva_len
.Lzero_by_line:
/* Compute how far we need to go to become suitably aligned. We're
* already at quad-word alignment. */
cmp count, zva_len_x
b.lt .Lnot_short /* Not enough to reach alignment. */
sub zva_bits_x, zva_len_x, #1
neg tmp2, dst
ands tmp2, tmp2, zva_bits_x
b.eq 1f /* Already aligned. */
/* Not aligned, check that there's enough to copy after alignment. */
sub tmp1, count, tmp2
cmp tmp1, #64
ccmp tmp1, zva_len_x, #8, ge /* NZCV=0b1000 */
b.lt .Lnot_short
/* We know that there's at least 64 bytes to zero and that it's safe
* to overrun by 64 bytes. */
mov count, tmp1
2:
stp A_l, A_l, [dst]
stp A_l, A_l, [dst, #16]
stp A_l, A_l, [dst, #32]
subs tmp2, tmp2, #64
stp A_l, A_l, [dst, #48]
add dst, dst, #64
b.ge 2b
/* We've overrun a bit, so adjust dst downwards. */
add dst, dst, tmp2
1:
sub count, count, zva_len_x
3:
dc zva, dst
add dst, dst, zva_len_x
subs count, count, zva_len_x
b.ge 3b
ands count, count, zva_bits_x
b.ne .Ltail_maybe_long
ret
END(android_memset32)

View File

@ -1,721 +0,0 @@
/*
* Copyright (C) 2010 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 "cache.h"
#ifndef MEMSET
# define MEMSET android_memset16
#endif
#ifndef L
# define L(label) .L##label
#endif
#ifndef ALIGN
# define ALIGN(n) .p2align n
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#ifdef USE_AS_BZERO16
# define DEST PARMS
# define LEN DEST+4
# define SETRTNVAL
#else
# define DEST PARMS
# define CHR DEST+4
# define LEN CHR+4
# define SETRTNVAL movl DEST(%esp), %eax
#endif
#if (defined SHARED || defined __PIC__)
# define ENTRANCE PUSH (%ebx);
# define RETURN_END POP (%ebx); ret
# define RETURN RETURN_END; CFI_PUSH (%ebx)
# define PARMS 8 /* Preserve EBX. */
# define JMPTBL(I, B) I - B
/* Load an entry in a jump table into EBX and branch to it. TABLE is a
jump table with relative offsets. */
# define BRANCH_TO_JMPTBL_ENTRY(TABLE) \
/* We first load PC into EBX. */ \
call __x86.get_pc_thunk.bx; \
/* Get the address of the jump table. */ \
add $(TABLE - .), %ebx; \
/* Get the entry and convert the relative offset to the \
absolute address. */ \
add (%ebx,%ecx,4), %ebx; \
/* We loaded the jump table and adjuested EDX. Go. */ \
jmp *%ebx
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
.globl __x86.get_pc_thunk.bx
.hidden __x86.get_pc_thunk.bx
ALIGN (4)
.type __x86.get_pc_thunk.bx,@function
__x86.get_pc_thunk.bx:
cfi_startproc
movl (%esp), %ebx
ret
cfi_endproc
#else
# define ENTRANCE
# define RETURN_END ret
# define RETURN RETURN_END
# define PARMS 4
# define JMPTBL(I, B) I
/* Branch to an entry in a jump table. TABLE is a jump table with
absolute offsets. */
# define BRANCH_TO_JMPTBL_ENTRY(TABLE) \
jmp *TABLE(,%ecx,4)
#endif
.section .text.sse2,"ax",@progbits
ALIGN (4)
ENTRY (MEMSET)
ENTRANCE
movl LEN(%esp), %ecx
shr $1, %ecx
#ifdef USE_AS_BZERO16
xor %eax, %eax
#else
movzwl CHR(%esp), %eax
mov %eax, %edx
shl $16, %eax
or %edx, %eax
#endif
movl DEST(%esp), %edx
cmp $32, %ecx
jae L(32wordsormore)
L(write_less32words):
lea (%edx, %ecx, 2), %edx
BRANCH_TO_JMPTBL_ENTRY (L(table_less32words))
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_less32words):
.int JMPTBL (L(write_0words), L(table_less32words))
.int JMPTBL (L(write_1words), L(table_less32words))
.int JMPTBL (L(write_2words), L(table_less32words))
.int JMPTBL (L(write_3words), L(table_less32words))
.int JMPTBL (L(write_4words), L(table_less32words))
.int JMPTBL (L(write_5words), L(table_less32words))
.int JMPTBL (L(write_6words), L(table_less32words))
.int JMPTBL (L(write_7words), L(table_less32words))
.int JMPTBL (L(write_8words), L(table_less32words))
.int JMPTBL (L(write_9words), L(table_less32words))
.int JMPTBL (L(write_10words), L(table_less32words))
.int JMPTBL (L(write_11words), L(table_less32words))
.int JMPTBL (L(write_12words), L(table_less32words))
.int JMPTBL (L(write_13words), L(table_less32words))
.int JMPTBL (L(write_14words), L(table_less32words))
.int JMPTBL (L(write_15words), L(table_less32words))
.int JMPTBL (L(write_16words), L(table_less32words))
.int JMPTBL (L(write_17words), L(table_less32words))
.int JMPTBL (L(write_18words), L(table_less32words))
.int JMPTBL (L(write_19words), L(table_less32words))
.int JMPTBL (L(write_20words), L(table_less32words))
.int JMPTBL (L(write_21words), L(table_less32words))
.int JMPTBL (L(write_22words), L(table_less32words))
.int JMPTBL (L(write_23words), L(table_less32words))
.int JMPTBL (L(write_24words), L(table_less32words))
.int JMPTBL (L(write_25words), L(table_less32words))
.int JMPTBL (L(write_26words), L(table_less32words))
.int JMPTBL (L(write_27words), L(table_less32words))
.int JMPTBL (L(write_28words), L(table_less32words))
.int JMPTBL (L(write_29words), L(table_less32words))
.int JMPTBL (L(write_30words), L(table_less32words))
.int JMPTBL (L(write_31words), L(table_less32words))
.popsection
ALIGN (4)
L(write_28words):
movl %eax, -56(%edx)
movl %eax, -52(%edx)
L(write_24words):
movl %eax, -48(%edx)
movl %eax, -44(%edx)
L(write_20words):
movl %eax, -40(%edx)
movl %eax, -36(%edx)
L(write_16words):
movl %eax, -32(%edx)
movl %eax, -28(%edx)
L(write_12words):
movl %eax, -24(%edx)
movl %eax, -20(%edx)
L(write_8words):
movl %eax, -16(%edx)
movl %eax, -12(%edx)
L(write_4words):
movl %eax, -8(%edx)
movl %eax, -4(%edx)
L(write_0words):
SETRTNVAL
RETURN
ALIGN (4)
L(write_29words):
movl %eax, -58(%edx)
movl %eax, -54(%edx)
L(write_25words):
movl %eax, -50(%edx)
movl %eax, -46(%edx)
L(write_21words):
movl %eax, -42(%edx)
movl %eax, -38(%edx)
L(write_17words):
movl %eax, -34(%edx)
movl %eax, -30(%edx)
L(write_13words):
movl %eax, -26(%edx)
movl %eax, -22(%edx)
L(write_9words):
movl %eax, -18(%edx)
movl %eax, -14(%edx)
L(write_5words):
movl %eax, -10(%edx)
movl %eax, -6(%edx)
L(write_1words):
mov %ax, -2(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(write_30words):
movl %eax, -60(%edx)
movl %eax, -56(%edx)
L(write_26words):
movl %eax, -52(%edx)
movl %eax, -48(%edx)
L(write_22words):
movl %eax, -44(%edx)
movl %eax, -40(%edx)
L(write_18words):
movl %eax, -36(%edx)
movl %eax, -32(%edx)
L(write_14words):
movl %eax, -28(%edx)
movl %eax, -24(%edx)
L(write_10words):
movl %eax, -20(%edx)
movl %eax, -16(%edx)
L(write_6words):
movl %eax, -12(%edx)
movl %eax, -8(%edx)
L(write_2words):
movl %eax, -4(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(write_31words):
movl %eax, -62(%edx)
movl %eax, -58(%edx)
L(write_27words):
movl %eax, -54(%edx)
movl %eax, -50(%edx)
L(write_23words):
movl %eax, -46(%edx)
movl %eax, -42(%edx)
L(write_19words):
movl %eax, -38(%edx)
movl %eax, -34(%edx)
L(write_15words):
movl %eax, -30(%edx)
movl %eax, -26(%edx)
L(write_11words):
movl %eax, -22(%edx)
movl %eax, -18(%edx)
L(write_7words):
movl %eax, -14(%edx)
movl %eax, -10(%edx)
L(write_3words):
movl %eax, -6(%edx)
movw %ax, -2(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(32wordsormore):
shl $1, %ecx
test $0x01, %edx
jz L(aligned2bytes)
mov %eax, (%edx)
mov %eax, -4(%edx, %ecx)
sub $2, %ecx
add $1, %edx
rol $8, %eax
L(aligned2bytes):
#ifdef USE_AS_BZERO16
pxor %xmm0, %xmm0
#else
movd %eax, %xmm0
pshufd $0, %xmm0, %xmm0
#endif
testl $0xf, %edx
jz L(aligned_16)
/* ECX > 32 and EDX is not 16 byte aligned. */
L(not_aligned_16):
movdqu %xmm0, (%edx)
movl %edx, %eax
and $-16, %edx
add $16, %edx
sub %edx, %eax
add %eax, %ecx
movd %xmm0, %eax
ALIGN (4)
L(aligned_16):
cmp $128, %ecx
jae L(128bytesormore)
L(aligned_16_less128bytes):
add %ecx, %edx
shr $1, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
ALIGN (4)
L(128bytesormore):
#ifdef SHARED_CACHE_SIZE
PUSH (%ebx)
mov $SHARED_CACHE_SIZE, %ebx
#else
# if (defined SHARED || defined __PIC__)
call __x86.get_pc_thunk.bx
add $_GLOBAL_OFFSET_TABLE_, %ebx
mov __x86_shared_cache_size@GOTOFF(%ebx), %ebx
# else
PUSH (%ebx)
mov __x86_shared_cache_size, %ebx
# endif
#endif
cmp %ebx, %ecx
jae L(128bytesormore_nt_start)
#ifdef DATA_CACHE_SIZE
POP (%ebx)
# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
cmp $DATA_CACHE_SIZE, %ecx
#else
# if (defined SHARED || defined __PIC__)
# define RESTORE_EBX_STATE
call __x86.get_pc_thunk.bx
add $_GLOBAL_OFFSET_TABLE_, %ebx
cmp __x86_data_cache_size@GOTOFF(%ebx), %ecx
# else
POP (%ebx)
# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
cmp __x86_data_cache_size, %ecx
# endif
#endif
jae L(128bytes_L2_normal)
subl $128, %ecx
L(128bytesormore_normal):
sub $128, %ecx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
lea 128(%edx), %edx
jb L(128bytesless_normal)
sub $128, %ecx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
lea 128(%edx), %edx
jae L(128bytesormore_normal)
L(128bytesless_normal):
lea 128(%ecx), %ecx
add %ecx, %edx
shr $1, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
ALIGN (4)
L(128bytes_L2_normal):
prefetcht0 0x380(%edx)
prefetcht0 0x3c0(%edx)
sub $128, %ecx
movdqa %xmm0, (%edx)
movaps %xmm0, 0x10(%edx)
movaps %xmm0, 0x20(%edx)
movaps %xmm0, 0x30(%edx)
movaps %xmm0, 0x40(%edx)
movaps %xmm0, 0x50(%edx)
movaps %xmm0, 0x60(%edx)
movaps %xmm0, 0x70(%edx)
add $128, %edx
cmp $128, %ecx
jae L(128bytes_L2_normal)
L(128bytesless_L2_normal):
add %ecx, %edx
shr $1, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
RESTORE_EBX_STATE
L(128bytesormore_nt_start):
sub %ebx, %ecx
mov %ebx, %eax
and $0x7f, %eax
add %eax, %ecx
movd %xmm0, %eax
ALIGN (4)
L(128bytesormore_shared_cache_loop):
prefetcht0 0x3c0(%edx)
prefetcht0 0x380(%edx)
sub $0x80, %ebx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
add $0x80, %edx
cmp $0x80, %ebx
jae L(128bytesormore_shared_cache_loop)
cmp $0x80, %ecx
jb L(shared_cache_loop_end)
ALIGN (4)
L(128bytesormore_nt):
sub $0x80, %ecx
movntdq %xmm0, (%edx)
movntdq %xmm0, 0x10(%edx)
movntdq %xmm0, 0x20(%edx)
movntdq %xmm0, 0x30(%edx)
movntdq %xmm0, 0x40(%edx)
movntdq %xmm0, 0x50(%edx)
movntdq %xmm0, 0x60(%edx)
movntdq %xmm0, 0x70(%edx)
add $0x80, %edx
cmp $0x80, %ecx
jae L(128bytesormore_nt)
sfence
L(shared_cache_loop_end):
#if defined DATA_CACHE_SIZE || !(defined SHARED || defined __PIC__)
POP (%ebx)
#endif
add %ecx, %edx
shr $1, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_16_128bytes):
.int JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_2bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_6bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_10bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_14bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_18bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_22bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_26bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_30bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_34bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_38bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_42bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_46bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_50bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_54bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_58bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_62bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_66bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_70bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_74bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_78bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_82bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_86bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_90bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_94bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_98bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_102bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_106bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_110bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_114bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_118bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_122bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_126bytes), L(table_16_128bytes))
.popsection
ALIGN (4)
L(aligned_16_112bytes):
movdqa %xmm0, -112(%edx)
L(aligned_16_96bytes):
movdqa %xmm0, -96(%edx)
L(aligned_16_80bytes):
movdqa %xmm0, -80(%edx)
L(aligned_16_64bytes):
movdqa %xmm0, -64(%edx)
L(aligned_16_48bytes):
movdqa %xmm0, -48(%edx)
L(aligned_16_32bytes):
movdqa %xmm0, -32(%edx)
L(aligned_16_16bytes):
movdqa %xmm0, -16(%edx)
L(aligned_16_0bytes):
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_114bytes):
movdqa %xmm0, -114(%edx)
L(aligned_16_98bytes):
movdqa %xmm0, -98(%edx)
L(aligned_16_82bytes):
movdqa %xmm0, -82(%edx)
L(aligned_16_66bytes):
movdqa %xmm0, -66(%edx)
L(aligned_16_50bytes):
movdqa %xmm0, -50(%edx)
L(aligned_16_34bytes):
movdqa %xmm0, -34(%edx)
L(aligned_16_18bytes):
movdqa %xmm0, -18(%edx)
L(aligned_16_2bytes):
movw %ax, -2(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_116bytes):
movdqa %xmm0, -116(%edx)
L(aligned_16_100bytes):
movdqa %xmm0, -100(%edx)
L(aligned_16_84bytes):
movdqa %xmm0, -84(%edx)
L(aligned_16_68bytes):
movdqa %xmm0, -68(%edx)
L(aligned_16_52bytes):
movdqa %xmm0, -52(%edx)
L(aligned_16_36bytes):
movdqa %xmm0, -36(%edx)
L(aligned_16_20bytes):
movdqa %xmm0, -20(%edx)
L(aligned_16_4bytes):
movl %eax, -4(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_118bytes):
movdqa %xmm0, -118(%edx)
L(aligned_16_102bytes):
movdqa %xmm0, -102(%edx)
L(aligned_16_86bytes):
movdqa %xmm0, -86(%edx)
L(aligned_16_70bytes):
movdqa %xmm0, -70(%edx)
L(aligned_16_54bytes):
movdqa %xmm0, -54(%edx)
L(aligned_16_38bytes):
movdqa %xmm0, -38(%edx)
L(aligned_16_22bytes):
movdqa %xmm0, -22(%edx)
L(aligned_16_6bytes):
movl %eax, -6(%edx)
movw %ax, -2(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_120bytes):
movdqa %xmm0, -120(%edx)
L(aligned_16_104bytes):
movdqa %xmm0, -104(%edx)
L(aligned_16_88bytes):
movdqa %xmm0, -88(%edx)
L(aligned_16_72bytes):
movdqa %xmm0, -72(%edx)
L(aligned_16_56bytes):
movdqa %xmm0, -56(%edx)
L(aligned_16_40bytes):
movdqa %xmm0, -40(%edx)
L(aligned_16_24bytes):
movdqa %xmm0, -24(%edx)
L(aligned_16_8bytes):
movq %xmm0, -8(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_122bytes):
movdqa %xmm0, -122(%edx)
L(aligned_16_106bytes):
movdqa %xmm0, -106(%edx)
L(aligned_16_90bytes):
movdqa %xmm0, -90(%edx)
L(aligned_16_74bytes):
movdqa %xmm0, -74(%edx)
L(aligned_16_58bytes):
movdqa %xmm0, -58(%edx)
L(aligned_16_42bytes):
movdqa %xmm0, -42(%edx)
L(aligned_16_26bytes):
movdqa %xmm0, -26(%edx)
L(aligned_16_10bytes):
movq %xmm0, -10(%edx)
movw %ax, -2(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_124bytes):
movdqa %xmm0, -124(%edx)
L(aligned_16_108bytes):
movdqa %xmm0, -108(%edx)
L(aligned_16_92bytes):
movdqa %xmm0, -92(%edx)
L(aligned_16_76bytes):
movdqa %xmm0, -76(%edx)
L(aligned_16_60bytes):
movdqa %xmm0, -60(%edx)
L(aligned_16_44bytes):
movdqa %xmm0, -44(%edx)
L(aligned_16_28bytes):
movdqa %xmm0, -28(%edx)
L(aligned_16_12bytes):
movq %xmm0, -12(%edx)
movl %eax, -4(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_126bytes):
movdqa %xmm0, -126(%edx)
L(aligned_16_110bytes):
movdqa %xmm0, -110(%edx)
L(aligned_16_94bytes):
movdqa %xmm0, -94(%edx)
L(aligned_16_78bytes):
movdqa %xmm0, -78(%edx)
L(aligned_16_62bytes):
movdqa %xmm0, -62(%edx)
L(aligned_16_46bytes):
movdqa %xmm0, -46(%edx)
L(aligned_16_30bytes):
movdqa %xmm0, -30(%edx)
L(aligned_16_14bytes):
movq %xmm0, -14(%edx)
movl %eax, -6(%edx)
movw %ax, -2(%edx)
SETRTNVAL
RETURN
END (MEMSET)

View File

@ -1,512 +0,0 @@
/*
* Copyright (C) 2010 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 "cache.h"
#ifndef MEMSET
# define MEMSET android_memset32
#endif
#ifndef L
# define L(label) .L##label
#endif
#ifndef ALIGN
# define ALIGN(n) .p2align n
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef cfi_rel_offset
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
#endif
#ifndef cfi_restore
# define cfi_restore(reg) .cfi_restore reg
#endif
#ifndef cfi_adjust_cfa_offset
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define CFI_PUSH(REG) \
cfi_adjust_cfa_offset (4); \
cfi_rel_offset (REG, 0)
#define CFI_POP(REG) \
cfi_adjust_cfa_offset (-4); \
cfi_restore (REG)
#define PUSH(REG) pushl REG; CFI_PUSH (REG)
#define POP(REG) popl REG; CFI_POP (REG)
#ifdef USE_AS_BZERO32
# define DEST PARMS
# define LEN DEST+4
# define SETRTNVAL
#else
# define DEST PARMS
# define DWDS DEST+4
# define LEN DWDS+4
# define SETRTNVAL movl DEST(%esp), %eax
#endif
#if (defined SHARED || defined __PIC__)
# define ENTRANCE PUSH (%ebx);
# define RETURN_END POP (%ebx); ret
# define RETURN RETURN_END; CFI_PUSH (%ebx)
# define PARMS 8 /* Preserve EBX. */
# define JMPTBL(I, B) I - B
/* Load an entry in a jump table into EBX and branch to it. TABLE is a
jump table with relative offsets. */
# define BRANCH_TO_JMPTBL_ENTRY(TABLE) \
/* We first load PC into EBX. */ \
call __x86.get_pc_thunk.bx; \
/* Get the address of the jump table. */ \
add $(TABLE - .), %ebx; \
/* Get the entry and convert the relative offset to the \
absolute address. */ \
add (%ebx,%ecx,4), %ebx; \
/* We loaded the jump table and adjuested EDX. Go. */ \
jmp *%ebx
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
.globl __x86.get_pc_thunk.bx
.hidden __x86.get_pc_thunk.bx
ALIGN (4)
.type __x86.get_pc_thunk.bx,@function
__x86.get_pc_thunk.bx:
cfi_startproc
movl (%esp), %ebx
ret
cfi_endproc
#else
# define ENTRANCE
# define RETURN_END ret
# define RETURN RETURN_END
# define PARMS 4
# define JMPTBL(I, B) I
/* Branch to an entry in a jump table. TABLE is a jump table with
absolute offsets. */
# define BRANCH_TO_JMPTBL_ENTRY(TABLE) \
jmp *TABLE(,%ecx,4)
#endif
.section .text.sse2,"ax",@progbits
ALIGN (4)
ENTRY (MEMSET)
ENTRANCE
movl LEN(%esp), %ecx
shr $2, %ecx
#ifdef USE_AS_BZERO32
xor %eax, %eax
#else
mov DWDS(%esp), %eax
mov %eax, %edx
#endif
movl DEST(%esp), %edx
cmp $16, %ecx
jae L(16dbwordsormore)
L(write_less16dbwords):
lea (%edx, %ecx, 4), %edx
BRANCH_TO_JMPTBL_ENTRY (L(table_less16dbwords))
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_less16dbwords):
.int JMPTBL (L(write_0dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_1dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_2dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_3dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_4dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_5dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_6dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_7dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_8dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_9dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_10dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_11dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_12dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_13dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_14dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_15dbwords), L(table_less16dbwords))
.popsection
ALIGN (4)
L(write_15dbwords):
movl %eax, -60(%edx)
L(write_14dbwords):
movl %eax, -56(%edx)
L(write_13dbwords):
movl %eax, -52(%edx)
L(write_12dbwords):
movl %eax, -48(%edx)
L(write_11dbwords):
movl %eax, -44(%edx)
L(write_10dbwords):
movl %eax, -40(%edx)
L(write_9dbwords):
movl %eax, -36(%edx)
L(write_8dbwords):
movl %eax, -32(%edx)
L(write_7dbwords):
movl %eax, -28(%edx)
L(write_6dbwords):
movl %eax, -24(%edx)
L(write_5dbwords):
movl %eax, -20(%edx)
L(write_4dbwords):
movl %eax, -16(%edx)
L(write_3dbwords):
movl %eax, -12(%edx)
L(write_2dbwords):
movl %eax, -8(%edx)
L(write_1dbwords):
movl %eax, -4(%edx)
L(write_0dbwords):
SETRTNVAL
RETURN
ALIGN (4)
L(16dbwordsormore):
test $3, %edx
jz L(aligned4bytes)
mov %eax, (%edx)
mov %eax, -4(%edx, %ecx, 4)
sub $1, %ecx
rol $24, %eax
add $1, %edx
test $3, %edx
jz L(aligned4bytes)
ror $8, %eax
add $1, %edx
test $3, %edx
jz L(aligned4bytes)
ror $8, %eax
add $1, %edx
L(aligned4bytes):
shl $2, %ecx
#ifdef USE_AS_BZERO32
pxor %xmm0, %xmm0
#else
movd %eax, %xmm0
pshufd $0, %xmm0, %xmm0
#endif
testl $0xf, %edx
jz L(aligned_16)
/* ECX > 32 and EDX is not 16 byte aligned. */
L(not_aligned_16):
movdqu %xmm0, (%edx)
movl %edx, %eax
and $-16, %edx
add $16, %edx
sub %edx, %eax
add %eax, %ecx
movd %xmm0, %eax
ALIGN (4)
L(aligned_16):
cmp $128, %ecx
jae L(128bytesormore)
L(aligned_16_less128bytes):
add %ecx, %edx
shr $2, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
ALIGN (4)
L(128bytesormore):
#ifdef SHARED_CACHE_SIZE
PUSH (%ebx)
mov $SHARED_CACHE_SIZE, %ebx
#else
# if (defined SHARED || defined __PIC__)
call __x86.get_pc_thunk.bx
add $_GLOBAL_OFFSET_TABLE_, %ebx
mov __x86_shared_cache_size@GOTOFF(%ebx), %ebx
# else
PUSH (%ebx)
mov __x86_shared_cache_size, %ebx
# endif
#endif
cmp %ebx, %ecx
jae L(128bytesormore_nt_start)
#ifdef DATA_CACHE_SIZE
POP (%ebx)
# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
cmp $DATA_CACHE_SIZE, %ecx
#else
# if (defined SHARED || defined __PIC__)
# define RESTORE_EBX_STATE
call __x86.get_pc_thunk.bx
add $_GLOBAL_OFFSET_TABLE_, %ebx
cmp __x86_data_cache_size@GOTOFF(%ebx), %ecx
# else
POP (%ebx)
# define RESTORE_EBX_STATE CFI_PUSH (%ebx)
cmp __x86_data_cache_size, %ecx
# endif
#endif
jae L(128bytes_L2_normal)
subl $128, %ecx
L(128bytesormore_normal):
sub $128, %ecx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
lea 128(%edx), %edx
jb L(128bytesless_normal)
sub $128, %ecx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
lea 128(%edx), %edx
jae L(128bytesormore_normal)
L(128bytesless_normal):
lea 128(%ecx), %ecx
add %ecx, %edx
shr $2, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
ALIGN (4)
L(128bytes_L2_normal):
prefetcht0 0x380(%edx)
prefetcht0 0x3c0(%edx)
sub $128, %ecx
movdqa %xmm0, (%edx)
movaps %xmm0, 0x10(%edx)
movaps %xmm0, 0x20(%edx)
movaps %xmm0, 0x30(%edx)
movaps %xmm0, 0x40(%edx)
movaps %xmm0, 0x50(%edx)
movaps %xmm0, 0x60(%edx)
movaps %xmm0, 0x70(%edx)
add $128, %edx
cmp $128, %ecx
jae L(128bytes_L2_normal)
L(128bytesless_L2_normal):
add %ecx, %edx
shr $2, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
RESTORE_EBX_STATE
L(128bytesormore_nt_start):
sub %ebx, %ecx
mov %ebx, %eax
and $0x7f, %eax
add %eax, %ecx
movd %xmm0, %eax
ALIGN (4)
L(128bytesormore_shared_cache_loop):
prefetcht0 0x3c0(%edx)
prefetcht0 0x380(%edx)
sub $0x80, %ebx
movdqa %xmm0, (%edx)
movdqa %xmm0, 0x10(%edx)
movdqa %xmm0, 0x20(%edx)
movdqa %xmm0, 0x30(%edx)
movdqa %xmm0, 0x40(%edx)
movdqa %xmm0, 0x50(%edx)
movdqa %xmm0, 0x60(%edx)
movdqa %xmm0, 0x70(%edx)
add $0x80, %edx
cmp $0x80, %ebx
jae L(128bytesormore_shared_cache_loop)
cmp $0x80, %ecx
jb L(shared_cache_loop_end)
ALIGN (4)
L(128bytesormore_nt):
sub $0x80, %ecx
movntdq %xmm0, (%edx)
movntdq %xmm0, 0x10(%edx)
movntdq %xmm0, 0x20(%edx)
movntdq %xmm0, 0x30(%edx)
movntdq %xmm0, 0x40(%edx)
movntdq %xmm0, 0x50(%edx)
movntdq %xmm0, 0x60(%edx)
movntdq %xmm0, 0x70(%edx)
add $0x80, %edx
cmp $0x80, %ecx
jae L(128bytesormore_nt)
sfence
L(shared_cache_loop_end):
#if defined DATA_CACHE_SIZE || !(defined SHARED || defined __PIC__)
POP (%ebx)
#endif
add %ecx, %edx
shr $2, %ecx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes))
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_16_128bytes):
.int JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
.popsection
ALIGN (4)
L(aligned_16_112bytes):
movdqa %xmm0, -112(%edx)
L(aligned_16_96bytes):
movdqa %xmm0, -96(%edx)
L(aligned_16_80bytes):
movdqa %xmm0, -80(%edx)
L(aligned_16_64bytes):
movdqa %xmm0, -64(%edx)
L(aligned_16_48bytes):
movdqa %xmm0, -48(%edx)
L(aligned_16_32bytes):
movdqa %xmm0, -32(%edx)
L(aligned_16_16bytes):
movdqa %xmm0, -16(%edx)
L(aligned_16_0bytes):
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_116bytes):
movdqa %xmm0, -116(%edx)
L(aligned_16_100bytes):
movdqa %xmm0, -100(%edx)
L(aligned_16_84bytes):
movdqa %xmm0, -84(%edx)
L(aligned_16_68bytes):
movdqa %xmm0, -68(%edx)
L(aligned_16_52bytes):
movdqa %xmm0, -52(%edx)
L(aligned_16_36bytes):
movdqa %xmm0, -36(%edx)
L(aligned_16_20bytes):
movdqa %xmm0, -20(%edx)
L(aligned_16_4bytes):
movl %eax, -4(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_120bytes):
movdqa %xmm0, -120(%edx)
L(aligned_16_104bytes):
movdqa %xmm0, -104(%edx)
L(aligned_16_88bytes):
movdqa %xmm0, -88(%edx)
L(aligned_16_72bytes):
movdqa %xmm0, -72(%edx)
L(aligned_16_56bytes):
movdqa %xmm0, -56(%edx)
L(aligned_16_40bytes):
movdqa %xmm0, -40(%edx)
L(aligned_16_24bytes):
movdqa %xmm0, -24(%edx)
L(aligned_16_8bytes):
movq %xmm0, -8(%edx)
SETRTNVAL
RETURN
ALIGN (4)
L(aligned_16_124bytes):
movdqa %xmm0, -124(%edx)
L(aligned_16_108bytes):
movdqa %xmm0, -108(%edx)
L(aligned_16_92bytes):
movdqa %xmm0, -92(%edx)
L(aligned_16_76bytes):
movdqa %xmm0, -76(%edx)
L(aligned_16_60bytes):
movdqa %xmm0, -60(%edx)
L(aligned_16_44bytes):
movdqa %xmm0, -44(%edx)
L(aligned_16_28bytes):
movdqa %xmm0, -28(%edx)
L(aligned_16_12bytes):
movq %xmm0, -12(%edx)
movl %eax, -4(%edx)
SETRTNVAL
RETURN
END (MEMSET)

View File

@ -1,565 +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 "cache.h"
#ifndef MEMSET
# define MEMSET android_memset16
#endif
#ifndef L
# define L(label) .L##label
#endif
#ifndef ALIGN
# define ALIGN(n) .p2align n
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define JMPTBL(I, B) I - B
/* Branch to an entry in a jump table. TABLE is a jump table with
relative offsets. INDEX is a register contains the index into the
jump table. SCALE is the scale of INDEX. */
#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
lea TABLE(%rip), %r11; \
movslq (%r11, INDEX, SCALE), INDEX; \
lea (%r11, INDEX), INDEX; \
jmp *INDEX
.section .text.sse2,"ax",@progbits
ALIGN (4)
ENTRY (MEMSET) // Address in rdi
shr $1, %rdx // Count in rdx
movzwl %si, %ecx
/* Fill the whole ECX with pattern. */
shl $16, %esi
or %esi, %ecx // Pattern in ecx
cmp $32, %rdx
jae L(32wordsormore)
L(write_less32words):
lea (%rdi, %rdx, 2), %rdi
BRANCH_TO_JMPTBL_ENTRY (L(table_less32words), %rdx, 4)
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_less32words):
.int JMPTBL (L(write_0words), L(table_less32words))
.int JMPTBL (L(write_1words), L(table_less32words))
.int JMPTBL (L(write_2words), L(table_less32words))
.int JMPTBL (L(write_3words), L(table_less32words))
.int JMPTBL (L(write_4words), L(table_less32words))
.int JMPTBL (L(write_5words), L(table_less32words))
.int JMPTBL (L(write_6words), L(table_less32words))
.int JMPTBL (L(write_7words), L(table_less32words))
.int JMPTBL (L(write_8words), L(table_less32words))
.int JMPTBL (L(write_9words), L(table_less32words))
.int JMPTBL (L(write_10words), L(table_less32words))
.int JMPTBL (L(write_11words), L(table_less32words))
.int JMPTBL (L(write_12words), L(table_less32words))
.int JMPTBL (L(write_13words), L(table_less32words))
.int JMPTBL (L(write_14words), L(table_less32words))
.int JMPTBL (L(write_15words), L(table_less32words))
.int JMPTBL (L(write_16words), L(table_less32words))
.int JMPTBL (L(write_17words), L(table_less32words))
.int JMPTBL (L(write_18words), L(table_less32words))
.int JMPTBL (L(write_19words), L(table_less32words))
.int JMPTBL (L(write_20words), L(table_less32words))
.int JMPTBL (L(write_21words), L(table_less32words))
.int JMPTBL (L(write_22words), L(table_less32words))
.int JMPTBL (L(write_23words), L(table_less32words))
.int JMPTBL (L(write_24words), L(table_less32words))
.int JMPTBL (L(write_25words), L(table_less32words))
.int JMPTBL (L(write_26words), L(table_less32words))
.int JMPTBL (L(write_27words), L(table_less32words))
.int JMPTBL (L(write_28words), L(table_less32words))
.int JMPTBL (L(write_29words), L(table_less32words))
.int JMPTBL (L(write_30words), L(table_less32words))
.int JMPTBL (L(write_31words), L(table_less32words))
.popsection
ALIGN (4)
L(write_28words):
movl %ecx, -56(%rdi)
movl %ecx, -52(%rdi)
L(write_24words):
movl %ecx, -48(%rdi)
movl %ecx, -44(%rdi)
L(write_20words):
movl %ecx, -40(%rdi)
movl %ecx, -36(%rdi)
L(write_16words):
movl %ecx, -32(%rdi)
movl %ecx, -28(%rdi)
L(write_12words):
movl %ecx, -24(%rdi)
movl %ecx, -20(%rdi)
L(write_8words):
movl %ecx, -16(%rdi)
movl %ecx, -12(%rdi)
L(write_4words):
movl %ecx, -8(%rdi)
movl %ecx, -4(%rdi)
L(write_0words):
ret
ALIGN (4)
L(write_29words):
movl %ecx, -58(%rdi)
movl %ecx, -54(%rdi)
L(write_25words):
movl %ecx, -50(%rdi)
movl %ecx, -46(%rdi)
L(write_21words):
movl %ecx, -42(%rdi)
movl %ecx, -38(%rdi)
L(write_17words):
movl %ecx, -34(%rdi)
movl %ecx, -30(%rdi)
L(write_13words):
movl %ecx, -26(%rdi)
movl %ecx, -22(%rdi)
L(write_9words):
movl %ecx, -18(%rdi)
movl %ecx, -14(%rdi)
L(write_5words):
movl %ecx, -10(%rdi)
movl %ecx, -6(%rdi)
L(write_1words):
mov %cx, -2(%rdi)
ret
ALIGN (4)
L(write_30words):
movl %ecx, -60(%rdi)
movl %ecx, -56(%rdi)
L(write_26words):
movl %ecx, -52(%rdi)
movl %ecx, -48(%rdi)
L(write_22words):
movl %ecx, -44(%rdi)
movl %ecx, -40(%rdi)
L(write_18words):
movl %ecx, -36(%rdi)
movl %ecx, -32(%rdi)
L(write_14words):
movl %ecx, -28(%rdi)
movl %ecx, -24(%rdi)
L(write_10words):
movl %ecx, -20(%rdi)
movl %ecx, -16(%rdi)
L(write_6words):
movl %ecx, -12(%rdi)
movl %ecx, -8(%rdi)
L(write_2words):
movl %ecx, -4(%rdi)
ret
ALIGN (4)
L(write_31words):
movl %ecx, -62(%rdi)
movl %ecx, -58(%rdi)
L(write_27words):
movl %ecx, -54(%rdi)
movl %ecx, -50(%rdi)
L(write_23words):
movl %ecx, -46(%rdi)
movl %ecx, -42(%rdi)
L(write_19words):
movl %ecx, -38(%rdi)
movl %ecx, -34(%rdi)
L(write_15words):
movl %ecx, -30(%rdi)
movl %ecx, -26(%rdi)
L(write_11words):
movl %ecx, -22(%rdi)
movl %ecx, -18(%rdi)
L(write_7words):
movl %ecx, -14(%rdi)
movl %ecx, -10(%rdi)
L(write_3words):
movl %ecx, -6(%rdi)
movw %cx, -2(%rdi)
ret
ALIGN (4)
L(32wordsormore):
shl $1, %rdx
test $0x01, %edi
jz L(aligned2bytes)
mov %ecx, (%rdi)
mov %ecx, -4(%rdi, %rdx)
sub $2, %rdx
add $1, %rdi
rol $8, %ecx
L(aligned2bytes):
/* Fill xmm0 with the pattern. */
movd %ecx, %xmm0
pshufd $0, %xmm0, %xmm0
testl $0xf, %edi
jz L(aligned_16)
/* RDX > 32 and RDI is not 16 byte aligned. */
movdqu %xmm0, (%rdi)
mov %rdi, %rsi
and $-16, %rdi
add $16, %rdi
sub %rdi, %rsi
add %rsi, %rdx
ALIGN (4)
L(aligned_16):
cmp $128, %rdx
jge L(128bytesormore)
L(aligned_16_less128bytes):
add %rdx, %rdi
shr $1, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
ALIGN (4)
L(128bytesormore):
cmp $SHARED_CACHE_SIZE, %rdx
jg L(128bytesormore_nt)
L(128bytesormore_normal):
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jge L(128bytesormore_normal)
L(128bytesless_normal):
add %rdx, %rdi
shr $1, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
ALIGN (4)
L(128bytesormore_nt):
sub $128, %rdx
movntdq %xmm0, (%rdi)
movntdq %xmm0, 0x10(%rdi)
movntdq %xmm0, 0x20(%rdi)
movntdq %xmm0, 0x30(%rdi)
movntdq %xmm0, 0x40(%rdi)
movntdq %xmm0, 0x50(%rdi)
movntdq %xmm0, 0x60(%rdi)
movntdq %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jge L(128bytesormore_nt)
sfence
add %rdx, %rdi
shr $1, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_16_128bytes):
.int JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_2bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_6bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_10bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_14bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_18bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_22bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_26bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_30bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_34bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_38bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_42bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_46bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_50bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_54bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_58bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_62bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_66bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_70bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_74bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_78bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_82bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_86bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_90bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_94bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_98bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_102bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_106bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_110bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_114bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_118bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_122bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_126bytes), L(table_16_128bytes))
.popsection
ALIGN (4)
L(aligned_16_112bytes):
movdqa %xmm0, -112(%rdi)
L(aligned_16_96bytes):
movdqa %xmm0, -96(%rdi)
L(aligned_16_80bytes):
movdqa %xmm0, -80(%rdi)
L(aligned_16_64bytes):
movdqa %xmm0, -64(%rdi)
L(aligned_16_48bytes):
movdqa %xmm0, -48(%rdi)
L(aligned_16_32bytes):
movdqa %xmm0, -32(%rdi)
L(aligned_16_16bytes):
movdqa %xmm0, -16(%rdi)
L(aligned_16_0bytes):
ret
ALIGN (4)
L(aligned_16_114bytes):
movdqa %xmm0, -114(%rdi)
L(aligned_16_98bytes):
movdqa %xmm0, -98(%rdi)
L(aligned_16_82bytes):
movdqa %xmm0, -82(%rdi)
L(aligned_16_66bytes):
movdqa %xmm0, -66(%rdi)
L(aligned_16_50bytes):
movdqa %xmm0, -50(%rdi)
L(aligned_16_34bytes):
movdqa %xmm0, -34(%rdi)
L(aligned_16_18bytes):
movdqa %xmm0, -18(%rdi)
L(aligned_16_2bytes):
movw %cx, -2(%rdi)
ret
ALIGN (4)
L(aligned_16_116bytes):
movdqa %xmm0, -116(%rdi)
L(aligned_16_100bytes):
movdqa %xmm0, -100(%rdi)
L(aligned_16_84bytes):
movdqa %xmm0, -84(%rdi)
L(aligned_16_68bytes):
movdqa %xmm0, -68(%rdi)
L(aligned_16_52bytes):
movdqa %xmm0, -52(%rdi)
L(aligned_16_36bytes):
movdqa %xmm0, -36(%rdi)
L(aligned_16_20bytes):
movdqa %xmm0, -20(%rdi)
L(aligned_16_4bytes):
movl %ecx, -4(%rdi)
ret
ALIGN (4)
L(aligned_16_118bytes):
movdqa %xmm0, -118(%rdi)
L(aligned_16_102bytes):
movdqa %xmm0, -102(%rdi)
L(aligned_16_86bytes):
movdqa %xmm0, -86(%rdi)
L(aligned_16_70bytes):
movdqa %xmm0, -70(%rdi)
L(aligned_16_54bytes):
movdqa %xmm0, -54(%rdi)
L(aligned_16_38bytes):
movdqa %xmm0, -38(%rdi)
L(aligned_16_22bytes):
movdqa %xmm0, -22(%rdi)
L(aligned_16_6bytes):
movl %ecx, -6(%rdi)
movw %cx, -2(%rdi)
ret
ALIGN (4)
L(aligned_16_120bytes):
movdqa %xmm0, -120(%rdi)
L(aligned_16_104bytes):
movdqa %xmm0, -104(%rdi)
L(aligned_16_88bytes):
movdqa %xmm0, -88(%rdi)
L(aligned_16_72bytes):
movdqa %xmm0, -72(%rdi)
L(aligned_16_56bytes):
movdqa %xmm0, -56(%rdi)
L(aligned_16_40bytes):
movdqa %xmm0, -40(%rdi)
L(aligned_16_24bytes):
movdqa %xmm0, -24(%rdi)
L(aligned_16_8bytes):
movq %xmm0, -8(%rdi)
ret
ALIGN (4)
L(aligned_16_122bytes):
movdqa %xmm0, -122(%rdi)
L(aligned_16_106bytes):
movdqa %xmm0, -106(%rdi)
L(aligned_16_90bytes):
movdqa %xmm0, -90(%rdi)
L(aligned_16_74bytes):
movdqa %xmm0, -74(%rdi)
L(aligned_16_58bytes):
movdqa %xmm0, -58(%rdi)
L(aligned_16_42bytes):
movdqa %xmm0, -42(%rdi)
L(aligned_16_26bytes):
movdqa %xmm0, -26(%rdi)
L(aligned_16_10bytes):
movq %xmm0, -10(%rdi)
movw %cx, -2(%rdi)
ret
ALIGN (4)
L(aligned_16_124bytes):
movdqa %xmm0, -124(%rdi)
L(aligned_16_108bytes):
movdqa %xmm0, -108(%rdi)
L(aligned_16_92bytes):
movdqa %xmm0, -92(%rdi)
L(aligned_16_76bytes):
movdqa %xmm0, -76(%rdi)
L(aligned_16_60bytes):
movdqa %xmm0, -60(%rdi)
L(aligned_16_44bytes):
movdqa %xmm0, -44(%rdi)
L(aligned_16_28bytes):
movdqa %xmm0, -28(%rdi)
L(aligned_16_12bytes):
movq %xmm0, -12(%rdi)
movl %ecx, -4(%rdi)
ret
ALIGN (4)
L(aligned_16_126bytes):
movdqa %xmm0, -126(%rdi)
L(aligned_16_110bytes):
movdqa %xmm0, -110(%rdi)
L(aligned_16_94bytes):
movdqa %xmm0, -94(%rdi)
L(aligned_16_78bytes):
movdqa %xmm0, -78(%rdi)
L(aligned_16_62bytes):
movdqa %xmm0, -62(%rdi)
L(aligned_16_46bytes):
movdqa %xmm0, -46(%rdi)
L(aligned_16_30bytes):
movdqa %xmm0, -30(%rdi)
L(aligned_16_14bytes):
movq %xmm0, -14(%rdi)
movl %ecx, -6(%rdi)
movw %cx, -2(%rdi)
ret
END (MEMSET)

View File

@ -1,373 +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 "cache.h"
#ifndef MEMSET
# define MEMSET android_memset32
#endif
#ifndef L
# define L(label) .L##label
#endif
#ifndef ALIGN
# define ALIGN(n) .p2align n
#endif
#ifndef cfi_startproc
# define cfi_startproc .cfi_startproc
#endif
#ifndef cfi_endproc
# define cfi_endproc .cfi_endproc
#endif
#ifndef ENTRY
# define ENTRY(name) \
.type name, @function; \
.globl name; \
.p2align 4; \
name: \
cfi_startproc
#endif
#ifndef END
# define END(name) \
cfi_endproc; \
.size name, .-name
#endif
#define JMPTBL(I, B) I - B
/* Branch to an entry in a jump table. TABLE is a jump table with
relative offsets. INDEX is a register contains the index into the
jump table. SCALE is the scale of INDEX. */
#define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE) \
lea TABLE(%rip), %r11; \
movslq (%r11, INDEX, SCALE), INDEX; \
lea (%r11, INDEX), INDEX; \
jmp *INDEX
.section .text.sse2,"ax",@progbits
ALIGN (4)
ENTRY (MEMSET) // Address in rdi
shr $2, %rdx // Count in rdx
movl %esi, %ecx // Pattern in ecx
cmp $16, %rdx
jae L(16dbwordsormore)
L(write_less16dbwords):
lea (%rdi, %rdx, 4), %rdi
BRANCH_TO_JMPTBL_ENTRY (L(table_less16dbwords), %rdx, 4)
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_less16dbwords):
.int JMPTBL (L(write_0dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_1dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_2dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_3dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_4dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_5dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_6dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_7dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_8dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_9dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_10dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_11dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_12dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_13dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_14dbwords), L(table_less16dbwords))
.int JMPTBL (L(write_15dbwords), L(table_less16dbwords))
.popsection
ALIGN (4)
L(write_15dbwords):
movl %ecx, -60(%rdi)
L(write_14dbwords):
movl %ecx, -56(%rdi)
L(write_13dbwords):
movl %ecx, -52(%rdi)
L(write_12dbwords):
movl %ecx, -48(%rdi)
L(write_11dbwords):
movl %ecx, -44(%rdi)
L(write_10dbwords):
movl %ecx, -40(%rdi)
L(write_9dbwords):
movl %ecx, -36(%rdi)
L(write_8dbwords):
movl %ecx, -32(%rdi)
L(write_7dbwords):
movl %ecx, -28(%rdi)
L(write_6dbwords):
movl %ecx, -24(%rdi)
L(write_5dbwords):
movl %ecx, -20(%rdi)
L(write_4dbwords):
movl %ecx, -16(%rdi)
L(write_3dbwords):
movl %ecx, -12(%rdi)
L(write_2dbwords):
movl %ecx, -8(%rdi)
L(write_1dbwords):
movl %ecx, -4(%rdi)
L(write_0dbwords):
ret
ALIGN (4)
L(16dbwordsormore):
test $3, %edi
jz L(aligned4bytes)
mov %ecx, (%rdi)
mov %ecx, -4(%rdi, %rdx, 4)
sub $1, %rdx
rol $24, %ecx
add $1, %rdi
test $3, %edi
jz L(aligned4bytes)
ror $8, %ecx
add $1, %rdi
test $3, %edi
jz L(aligned4bytes)
ror $8, %ecx
add $1, %rdi
L(aligned4bytes):
shl $2, %rdx
/* Fill xmm0 with the pattern. */
movd %ecx, %xmm0
pshufd $0, %xmm0, %xmm0
testl $0xf, %edi
jz L(aligned_16)
/* RDX > 32 and RDI is not 16 byte aligned. */
movdqu %xmm0, (%rdi)
mov %rdi, %rsi
and $-16, %rdi
add $16, %rdi
sub %rdi, %rsi
add %rsi, %rdx
ALIGN (4)
L(aligned_16):
cmp $128, %rdx
jge L(128bytesormore)
L(aligned_16_less128bytes):
add %rdx, %rdi
shr $2, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
ALIGN (4)
L(128bytesormore):
cmp $SHARED_CACHE_SIZE, %rdx
jg L(128bytesormore_nt)
L(128bytesormore_normal):
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jl L(128bytesless_normal)
sub $128, %rdx
movdqa %xmm0, (%rdi)
movdqa %xmm0, 0x10(%rdi)
movdqa %xmm0, 0x20(%rdi)
movdqa %xmm0, 0x30(%rdi)
movdqa %xmm0, 0x40(%rdi)
movdqa %xmm0, 0x50(%rdi)
movdqa %xmm0, 0x60(%rdi)
movdqa %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jge L(128bytesormore_normal)
L(128bytesless_normal):
add %rdx, %rdi
shr $2, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
ALIGN (4)
L(128bytesormore_nt):
sub $128, %rdx
movntdq %xmm0, (%rdi)
movntdq %xmm0, 0x10(%rdi)
movntdq %xmm0, 0x20(%rdi)
movntdq %xmm0, 0x30(%rdi)
movntdq %xmm0, 0x40(%rdi)
movntdq %xmm0, 0x50(%rdi)
movntdq %xmm0, 0x60(%rdi)
movntdq %xmm0, 0x70(%rdi)
lea 128(%rdi), %rdi
cmp $128, %rdx
jge L(128bytesormore_nt)
sfence
add %rdx, %rdi
shr $2, %rdx
BRANCH_TO_JMPTBL_ENTRY (L(table_16_128bytes), %rdx, 4)
.pushsection .rodata.sse2,"a",@progbits
ALIGN (2)
L(table_16_128bytes):
.int JMPTBL (L(aligned_16_0bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_4bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_8bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_12bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_16bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_20bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_24bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_28bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_32bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_36bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_40bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_44bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_48bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_52bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_56bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_60bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_64bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_68bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_72bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_76bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_80bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_84bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_88bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_92bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_96bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_100bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_104bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_108bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_112bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_116bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_120bytes), L(table_16_128bytes))
.int JMPTBL (L(aligned_16_124bytes), L(table_16_128bytes))
.popsection
ALIGN (4)
L(aligned_16_112bytes):
movdqa %xmm0, -112(%rdi)
L(aligned_16_96bytes):
movdqa %xmm0, -96(%rdi)
L(aligned_16_80bytes):
movdqa %xmm0, -80(%rdi)
L(aligned_16_64bytes):
movdqa %xmm0, -64(%rdi)
L(aligned_16_48bytes):
movdqa %xmm0, -48(%rdi)
L(aligned_16_32bytes):
movdqa %xmm0, -32(%rdi)
L(aligned_16_16bytes):
movdqa %xmm0, -16(%rdi)
L(aligned_16_0bytes):
ret
ALIGN (4)
L(aligned_16_116bytes):
movdqa %xmm0, -116(%rdi)
L(aligned_16_100bytes):
movdqa %xmm0, -100(%rdi)
L(aligned_16_84bytes):
movdqa %xmm0, -84(%rdi)
L(aligned_16_68bytes):
movdqa %xmm0, -68(%rdi)
L(aligned_16_52bytes):
movdqa %xmm0, -52(%rdi)
L(aligned_16_36bytes):
movdqa %xmm0, -36(%rdi)
L(aligned_16_20bytes):
movdqa %xmm0, -20(%rdi)
L(aligned_16_4bytes):
movl %ecx, -4(%rdi)
ret
ALIGN (4)
L(aligned_16_120bytes):
movdqa %xmm0, -120(%rdi)
L(aligned_16_104bytes):
movdqa %xmm0, -104(%rdi)
L(aligned_16_88bytes):
movdqa %xmm0, -88(%rdi)
L(aligned_16_72bytes):
movdqa %xmm0, -72(%rdi)
L(aligned_16_56bytes):
movdqa %xmm0, -56(%rdi)
L(aligned_16_40bytes):
movdqa %xmm0, -40(%rdi)
L(aligned_16_24bytes):
movdqa %xmm0, -24(%rdi)
L(aligned_16_8bytes):
movq %xmm0, -8(%rdi)
ret
ALIGN (4)
L(aligned_16_124bytes):
movdqa %xmm0, -124(%rdi)
L(aligned_16_108bytes):
movdqa %xmm0, -108(%rdi)
L(aligned_16_92bytes):
movdqa %xmm0, -92(%rdi)
L(aligned_16_76bytes):
movdqa %xmm0, -76(%rdi)
L(aligned_16_60bytes):
movdqa %xmm0, -60(%rdi)
L(aligned_16_44bytes):
movdqa %xmm0, -44(%rdi)
L(aligned_16_28bytes):
movdqa %xmm0, -28(%rdi)
L(aligned_16_12bytes):
movq %xmm0, -12(%rdi)
movl %ecx, -4(%rdi)
ret
END (MEMSET)

View File

@ -14,8 +14,7 @@
* limitations under the License.
*/
#ifndef ANDROID_CUTILS_MEMORY_H
#define ANDROID_CUTILS_MEMORY_H
#pragma once
#include <stdint.h>
#include <sys/types.h>
@ -24,12 +23,6 @@
extern "C" {
#endif
/* size is given in bytes and must be multiple of 2 */
void android_memset16(uint16_t* dst, uint16_t value, size_t size);
/* size is given in bytes and must be multiple of 4 */
void android_memset32(uint32_t* dst, uint32_t value, size_t size);
#if defined(__GLIBC__) || defined(_WIN32)
/* Declaration of strlcpy() for platforms that don't already have it. */
size_t strlcpy(char *dst, const char *src, size_t size);
@ -38,5 +31,3 @@ size_t strlcpy(char *dst, const char *src, size_t size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ANDROID_CUTILS_MEMORY_H

View File

@ -1,181 +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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <memory>
#include <cutils/memory.h>
#include <gtest/gtest.h>
#define FENCEPOST_LENGTH 8
#define MAX_TEST_SIZE (64*1024)
// Choose values that have no repeating byte values.
#define MEMSET16_PATTERN 0xb139
#define MEMSET32_PATTERN 0x48193a27
enum test_e {
MEMSET16 = 0,
MEMSET32,
};
static int g_memset16_aligns[][2] = {
{ 2, 0 },
{ 4, 0 },
{ 8, 0 },
{ 16, 0 },
{ 32, 0 },
{ 64, 0 },
{ 128, 0 },
{ 4, 2 },
{ 8, 2 },
{ 8, 4 },
{ 8, 6 },
{ 128, 2 },
{ 128, 4 },
{ 128, 6 },
{ 128, 8 },
{ 128, 10 },
{ 128, 12 },
{ 128, 14 },
{ 128, 16 },
};
static int g_memset32_aligns[][2] = {
{ 4, 0 },
{ 8, 0 },
{ 16, 0 },
{ 32, 0 },
{ 64, 0 },
{ 128, 0 },
{ 8, 4 },
{ 128, 4 },
{ 128, 8 },
{ 128, 12 },
{ 128, 16 },
};
static size_t GetIncrement(size_t len, size_t min_incr) {
if (len >= 4096) {
return 1024;
} else if (len >= 1024) {
return 256;
}
return min_incr;
}
// Return a pointer into the current buffer with the specified alignment.
static void *GetAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
if (alignment > 0) {
// When setting the alignment, set it to exactly the alignment chosen.
// The pointer returned will be guaranteed not to be aligned to anything
// more than that.
ptr += alignment - (ptr & (alignment - 1));
ptr |= alignment | or_mask;
}
return reinterpret_cast<void*>(ptr);
}
static void SetFencepost(uint8_t *buffer) {
for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
buffer[i] = 0xde;
buffer[i+1] = 0xad;
}
}
static void VerifyFencepost(uint8_t *buffer) {
for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
uint8_t expected_value;
if (buffer[i] == 0xde) {
i++;
expected_value = 0xad;
} else {
expected_value = 0xde;
}
ASSERT_EQ(expected_value, buffer[i]);
}
}
}
void RunMemsetTests(test_e test_type, uint32_t value, int align[][2], size_t num_aligns) {
size_t min_incr = 4;
if (test_type == MEMSET16) {
min_incr = 2;
value |= value << 16;
}
std::unique_ptr<uint32_t[]> expected_buf(new uint32_t[MAX_TEST_SIZE/sizeof(uint32_t)]);
for (size_t i = 0; i < MAX_TEST_SIZE/sizeof(uint32_t); i++) {
expected_buf[i] = value;
}
// Allocate one large buffer with lots of extra space so that we can
// guarantee that all possible alignments will fit.
std::unique_ptr<uint8_t[]> buf(new uint8_t[3*MAX_TEST_SIZE]);
uint8_t *buf_align;
for (size_t i = 0; i < num_aligns; i++) {
size_t incr = min_incr;
for (size_t len = incr; len <= MAX_TEST_SIZE; len += incr) {
incr = GetIncrement(len, min_incr);
buf_align = reinterpret_cast<uint8_t*>(GetAlignedPtr(
buf.get()+FENCEPOST_LENGTH, align[i][0], align[i][1]));
SetFencepost(&buf_align[-FENCEPOST_LENGTH]);
SetFencepost(&buf_align[len]);
memset(buf_align, 0xff, len);
if (test_type == MEMSET16) {
android_memset16(reinterpret_cast<uint16_t*>(buf_align), value, len);
} else {
android_memset32(reinterpret_cast<uint32_t*>(buf_align), value, len);
}
ASSERT_EQ(0, memcmp(expected_buf.get(), buf_align, len))
<< "Failed size " << len << " align " << align[i][0] << " " << align[i][1] << "\n";
VerifyFencepost(&buf_align[-FENCEPOST_LENGTH]);
VerifyFencepost(&buf_align[len]);
}
}
}
TEST(libcutils, android_memset16_non_zero) {
RunMemsetTests(MEMSET16, MEMSET16_PATTERN, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset16_zero) {
RunMemsetTests(MEMSET16, 0, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset32_non_zero) {
RunMemsetTests(MEMSET32, MEMSET32_PATTERN, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset32_zero) {
RunMemsetTests(MEMSET32, 0, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
}

View File

@ -198,7 +198,7 @@ void atrace_update_tags()
}
#define WRITE_MSG(format_begin, format_end, name, value) { \
char buf[ATRACE_MESSAGE_LENGTH]; \
char buf[ATRACE_MESSAGE_LENGTH] __attribute__((uninitialized)); \
int pid = getpid(); \
int len = snprintf(buf, sizeof(buf), format_begin "%s" format_end, pid, \
name, value); \

View File

@ -1,97 +0,0 @@
cc_defaults {
name: "pixelflinger_defaults",
cflags: [
"-fstrict-aliasing",
"-fomit-frame-pointer",
"-Wall",
"-Werror",
"-Wno-unused-function",
],
export_include_dirs: ["include"],
header_libs: ["libbase_headers"],
shared_libs: [
"libcutils",
"liblog",
"libutils",
],
arch: {
arm: {
neon: {
cflags: ["-D__ARM_HAVE_NEON"],
},
},
},
}
cc_library_static {
name: "libpixelflinger-arm",
defaults: ["pixelflinger_defaults"],
srcs: [
"fixed.cpp",
"picker.cpp",
"pixelflinger.cpp",
"trap.cpp",
"scanline.cpp",
],
arch: {
arm: {
instruction_set: "arm",
},
},
}
// For the tests to use
cc_library_headers {
name: "libpixelflinger_internal",
export_include_dirs: [
"include",
".",
],
}
cc_library {
name: "libpixelflinger",
defaults: ["pixelflinger_defaults"],
srcs: [
"codeflinger/ARMAssemblerInterface.cpp",
"codeflinger/ARMAssemblerProxy.cpp",
"codeflinger/CodeCache.cpp",
"codeflinger/GGLAssembler.cpp",
"codeflinger/load_store.cpp",
"codeflinger/blending.cpp",
"codeflinger/texturing.cpp",
"format.cpp",
"clear.cpp",
"raster.cpp",
"buffer.cpp",
],
whole_static_libs: ["libpixelflinger-arm"],
arch: {
arm: {
srcs: [
"codeflinger/ARMAssembler.cpp",
"codeflinger/disassem.c",
"col32cb16blend.S",
"t32cb16blend.S",
],
neon: {
srcs: ["col32cb16blend_neon.S"],
},
},
arm64: {
srcs: [
"codeflinger/Arm64Assembler.cpp",
"codeflinger/Arm64Disassembler.cpp",
"arch-arm64/col32cb16blend.S",
"arch-arm64/t32cb16blend.S",
],
},
},
}

View File

@ -1,190 +0,0 @@
Copyright (c) 2005-2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,87 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
.text
.balign 0
.global scanline_col32cb16blend_arm64
//
// This function alpha blends a fixed color into a destination scanline, using
// the formula:
//
// d = s + (((a + (a >> 7)) * d) >> 8)
//
// where d is the destination pixel,
// s is the source color,
// a is the alpha channel of the source color.
//
// x0 = destination buffer pointer
// w1 = color value
// w2 = count
scanline_col32cb16blend_arm64:
lsr w5, w1, #24 // shift down alpha
mov w9, #0xff // create mask
add w5, w5, w5, lsr #7 // add in top bit
mov w4, #256 // create #0x100
sub w5, w4, w5 // invert alpha
and w10, w1, #0xff // extract red
and w12, w9, w1, lsr #8 // extract green
and w4, w9, w1, lsr #16 // extract blue
lsl w10, w10, #5 // prescale red
lsl w12, w12, #6 // prescale green
lsl w4, w4, #5 // prescale blue
lsr w9, w9, #2 // create dest green mask
1:
ldrh w8, [x0] // load dest pixel
subs w2, w2, #1 // decrement loop counter
lsr w6, w8, #11 // extract dest red
and w7, w9, w8, lsr #5 // extract dest green
and w8, w8, #0x1f // extract dest blue
madd w6, w6, w5, w10 // dest red * alpha + src red
madd w7, w7, w5, w12 // dest green * alpha + src green
madd w8, w8, w5, w4 // dest blue * alpha + src blue
lsr w6, w6, #8 // shift down red
lsr w7, w7, #8 // shift down green
lsl w6, w6, #11 // shift red into 565
orr w6, w6, w7, lsl #5 // shift green into 565
orr w6, w6, w8, lsr #8 // shift blue into 565
strh w6, [x0], #2 // store pixel to dest, update ptr
b.ne 1b // if count != 0, loop
ret

View File

@ -1,213 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
.text
.balign 0
.global scanline_t32cb16blend_arm64
/*
* .macro pixel
*
* This macro alpha blends RGB565 original pixel located in either
* top or bottom 16 bits of DREG register with SRC 32 bit pixel value
* and writes the result to FB register
*
* \DREG is a 32-bit register containing *two* original destination RGB565
* pixels, with the even one in the low-16 bits, and the odd one in the
* high 16 bits.
*
* \SRC is a 32-bit 0xAABBGGRR pixel value, with pre-multiplied colors.
*
* \FB is a target register that will contain the blended pixel values.
*
* \ODD is either 0 or 1 and indicates if we're blending the lower or
* upper 16-bit pixels in DREG into FB
*
*
* clobbered: w6, w7, w15, w16, w17
*
*/
.macro pixel, DREG, SRC, FB, ODD
// SRC = 0xAABBGGRR
lsr w7, \SRC, #24 // sA
add w7, w7, w7, lsr #7 // sA + (sA >> 7)
mov w6, #0x100
sub w7, w6, w7 // sA = 0x100 - (sA+(sA>>7))
1:
.if \ODD //Blending odd pixel present in top 16 bits of DREG register
// red
lsr w16, \DREG, #(16 + 11)
mul w16, w7, w16
lsr w6, \SRC, #3
and w6, w6, #0x1F
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #(0x1F<<(16 + 11))
orr w15, \FB, w16, lsl #(16 + 11)
csel \FB, w17, w15, hi
// green
and w6, \DREG, #(0x3F<<(16 + 5))
lsr w17,w6,#(16+5)
mul w6, w7, w17
lsr w16, \SRC, #(8+2)
and w16, w16, #0x3F
add w6, w16, w6, lsr #8
cmp w6, #0x3F
orr w17, \FB, #(0x3F<<(16 + 5))
orr w15, \FB, w6, lsl #(16 + 5)
csel \FB, w17, w15, hi
// blue
and w16, \DREG, #(0x1F << 16)
lsr w17,w16,#16
mul w16, w7, w17
lsr w6, \SRC, #(8+8+3)
and w6, w6, #0x1F
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #(0x1F << 16)
orr w15, \FB, w16, lsl #16
csel \FB, w17, w15, hi
.else //Blending even pixel present in bottom 16 bits of DREG register
// red
lsr w16, \DREG, #11
and w16, w16, #0x1F
mul w16, w7, w16
lsr w6, \SRC, #3
and w6, w6, #0x1F
add w16, w6, w16, lsr #8
cmp w16, #0x1F
mov w17, #(0x1F<<11)
lsl w15, w16, #11
csel \FB, w17, w15, hi
// green
and w6, \DREG, #(0x3F<<5)
mul w6, w7, w6
lsr w16, \SRC, #(8+2)
and w16, w16, #0x3F
add w6, w16, w6, lsr #(5+8)
cmp w6, #0x3F
orr w17, \FB, #(0x3F<<5)
orr w15, \FB, w6, lsl #5
csel \FB, w17, w15, hi
// blue
and w16, \DREG, #0x1F
mul w16, w7, w16
lsr w6, \SRC, #(8+8+3)
and w6, w6, #0x1F
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #0x1F
orr w15, \FB, w16
csel \FB, w17, w15, hi
.endif // End of blending even pixel
.endm // End of pixel macro
// x0: dst ptr
// x1: src ptr
// w2: count
// w3: d
// w4: s0
// w5: s1
// w6: pixel
// w7: pixel
// w8: free
// w9: free
// w10: free
// w11: free
// w12: scratch
// w14: pixel
scanline_t32cb16blend_arm64:
// align DST to 32 bits
tst x0, #0x3
b.eq aligned
subs w2, w2, #1
b.lo return
last:
ldr w4, [x1], #4
ldrh w3, [x0]
pixel w3, w4, w12, 0
strh w12, [x0], #2
aligned:
subs w2, w2, #2
b.lo 9f
// The main loop is unrolled twice and processes 4 pixels
8:
ldp w4,w5, [x1], #8
add x0, x0, #4
// it's all zero, skip this pixel
orr w3, w4, w5
cbz w3, 7f
// load the destination
ldr w3, [x0, #-4]
// stream the destination
pixel w3, w4, w12, 0
pixel w3, w5, w12, 1
str w12, [x0, #-4]
// 2nd iteration of the loop, don't stream anything
subs w2, w2, #2
csel w4, w5, w4, lt
blt 9f
ldp w4,w5, [x1], #8
add x0, x0, #4
orr w3, w4, w5
cbz w3, 7f
ldr w3, [x0, #-4]
pixel w3, w4, w12, 0
pixel w3, w5, w12, 1
str w12, [x0, #-4]
7: subs w2, w2, #2
bhs 8b
mov w4, w5
9: adds w2, w2, #1
b.lo return
b last
return:
ret

View File

@ -1,389 +0,0 @@
/* libs/pixelflinger/buffer.cpp
**
** Copyright 2006, 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 <assert.h>
#include <android-base/macros.h>
#include "buffer.h"
namespace android {
// ----------------------------------------------------------------------------
static void read_pixel(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, pixel_t* pixel);
static void write_pixel(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, const pixel_t* pixel);
static void readRGB565(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, pixel_t* pixel);
static void readABGR8888(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, pixel_t* pixel);
static uint32_t logic_op(int op, uint32_t s, uint32_t d);
static uint32_t extract(uint32_t v, int h, int l, int bits);
static uint32_t expand(uint32_t v, int sbits, int dbits);
static uint32_t downshift_component(uint32_t in, uint32_t v,
int sh, int sl, int dh, int dl, int ch, int cl, int dither);
// ----------------------------------------------------------------------------
void ggl_init_texture(context_t* c)
{
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
texture_t& t = c->state.texture[i];
t.s_coord = GGL_ONE_TO_ONE;
t.t_coord = GGL_ONE_TO_ONE;
t.s_wrap = GGL_REPEAT;
t.t_wrap = GGL_REPEAT;
t.min_filter = GGL_NEAREST;
t.mag_filter = GGL_NEAREST;
t.env = GGL_MODULATE;
}
c->activeTMU = &(c->state.texture[0]);
}
void ggl_set_surface(context_t* c, surface_t* dst, const GGLSurface* src)
{
dst->width = src->width;
dst->height = src->height;
dst->stride = src->stride;
dst->data = src->data;
dst->format = src->format;
dst->dirty = 1;
if (__builtin_expect(dst->stride < 0, false)) {
const GGLFormat& pixelFormat(c->formats[dst->format]);
const int32_t bpr = -dst->stride * pixelFormat.size;
dst->data += bpr * (dst->height-1);
}
}
static void pick_read_write(surface_t* s)
{
// Choose best reader/writers.
switch (s->format) {
case GGL_PIXEL_FORMAT_RGBA_8888: s->read = readABGR8888; break;
case GGL_PIXEL_FORMAT_RGB_565: s->read = readRGB565; break;
default: s->read = read_pixel; break;
}
s->write = write_pixel;
}
void ggl_pick_texture(context_t* c)
{
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) {
surface_t& s = c->state.texture[i].surface;
if ((!c->state.texture[i].enable) || (!s.dirty))
continue;
s.dirty = 0;
pick_read_write(&s);
generated_tex_vars_t& gen = c->generated_vars.texture[i];
gen.width = s.width;
gen.height = s.height;
gen.stride = s.stride;
gen.data = uintptr_t(s.data);
}
}
void ggl_pick_cb(context_t* c)
{
surface_t& s = c->state.buffers.color;
if (s.dirty) {
s.dirty = 0;
pick_read_write(&s);
}
}
// ----------------------------------------------------------------------------
void read_pixel(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, pixel_t* pixel)
{
assert((x < s->width) && (y < s->height));
const GGLFormat* f = &(c->formats[s->format]);
int32_t index = x + (s->stride * y);
uint8_t* const data = s->data + index * f->size;
uint32_t v = 0;
switch (f->size) {
case 1: v = *data; break;
case 2: v = *(uint16_t*)data; break;
case 3: v = (data[2]<<16)|(data[1]<<8)|data[0]; break;
case 4: v = GGL_RGBA_TO_HOST(*(uint32_t*)data); break;
}
for (int i=0 ; i<4 ; i++) {
pixel->s[i] = f->c[i].h - f->c[i].l;
if (pixel->s[i])
pixel->c[i] = extract(v, f->c[i].h, f->c[i].l, f->size*8);
}
}
void readRGB565(const surface_t* s, context_t* /*c*/,
uint32_t x, uint32_t y, pixel_t* pixel)
{
uint16_t v = *(reinterpret_cast<uint16_t*>(s->data) + (x + (s->stride * y)));
pixel->c[0] = 0;
pixel->c[1] = v>>11;
pixel->c[2] = (v>>5)&0x3F;
pixel->c[3] = v&0x1F;
pixel->s[0] = 0;
pixel->s[1] = 5;
pixel->s[2] = 6;
pixel->s[3] = 5;
}
void readABGR8888(const surface_t* s, context_t* /*c*/,
uint32_t x, uint32_t y, pixel_t* pixel)
{
uint32_t v = *(reinterpret_cast<uint32_t*>(s->data) + (x + (s->stride * y)));
v = GGL_RGBA_TO_HOST(v);
pixel->c[0] = v>>24; // A
pixel->c[1] = v&0xFF; // R
pixel->c[2] = (v>>8)&0xFF; // G
pixel->c[3] = (v>>16)&0xFF; // B
pixel->s[0] =
pixel->s[1] =
pixel->s[2] =
pixel->s[3] = 8;
}
void write_pixel(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, const pixel_t* pixel)
{
assert((x < s->width) && (y < s->height));
int dither = -1;
if (c->state.enables & GGL_ENABLE_DITHER) {
dither = c->ditherMatrix[ (x & GGL_DITHER_MASK) +
((y & GGL_DITHER_MASK)<<GGL_DITHER_ORDER_SHIFT) ];
}
const GGLFormat* f = &(c->formats[s->format]);
int32_t index = x + (s->stride * y);
uint8_t* const data = s->data + index * f->size;
uint32_t mask = 0;
uint32_t v = 0;
for (int i=0 ; i<4 ; i++) {
const int component_mask = 1 << i;
if (f->components>=GGL_LUMINANCE &&
(i==GGLFormat::GREEN || i==GGLFormat::BLUE)) {
// destinations L formats don't have G or B
continue;
}
const int l = f->c[i].l;
const int h = f->c[i].h;
if (h && (c->state.mask.color & component_mask)) {
mask |= (((1<<(h-l))-1)<<l);
uint32_t u = pixel->c[i];
int32_t pixelSize = pixel->s[i];
if (pixelSize < (h-l)) {
u = expand(u, pixelSize, h-l);
pixelSize = h-l;
}
v = downshift_component(v, u, pixelSize, 0, h, l, 0, 0, dither);
}
}
if ((c->state.mask.color != 0xF) ||
(c->state.enables & GGL_ENABLE_LOGIC_OP)) {
uint32_t d = 0;
switch (f->size) {
case 1: d = *data; break;
case 2: d = *(uint16_t*)data; break;
case 3: d = (data[2]<<16)|(data[1]<<8)|data[0]; break;
case 4: d = GGL_RGBA_TO_HOST(*(uint32_t*)data); break;
}
if (c->state.enables & GGL_ENABLE_LOGIC_OP) {
v = logic_op(c->state.logic_op.opcode, v, d);
v &= mask;
}
v |= (d & ~mask);
}
switch (f->size) {
case 1: *data = v; break;
case 2: *(uint16_t*)data = v; break;
case 3:
data[0] = v;
data[1] = v>>8;
data[2] = v>>16;
break;
case 4: *(uint32_t*)data = GGL_HOST_TO_RGBA(v); break;
}
}
static uint32_t logic_op(int op, uint32_t s, uint32_t d)
{
switch(op) {
case GGL_CLEAR: return 0;
case GGL_AND: return s & d;
case GGL_AND_REVERSE: return s & ~d;
case GGL_COPY: return s;
case GGL_AND_INVERTED: return ~s & d;
case GGL_NOOP: return d;
case GGL_XOR: return s ^ d;
case GGL_OR: return s | d;
case GGL_NOR: return ~(s | d);
case GGL_EQUIV: return ~(s ^ d);
case GGL_INVERT: return ~d;
case GGL_OR_REVERSE: return s | ~d;
case GGL_COPY_INVERTED: return ~s;
case GGL_OR_INVERTED: return ~s | d;
case GGL_NAND: return ~(s & d);
case GGL_SET: return ~0;
};
return s;
}
uint32_t ggl_expand(uint32_t v, int sbits, int dbits)
{
return expand(v, sbits, dbits);
}
uint32_t ggl_pack_color(context_t* c, int32_t format,
GGLcolor r, GGLcolor g, GGLcolor b, GGLcolor a)
{
const GGLFormat* f = &(c->formats[format]);
uint32_t p = 0;
const int32_t hbits = GGL_COLOR_BITS;
const int32_t lbits = GGL_COLOR_BITS - 8;
p = downshift_component(p, r, hbits, lbits, f->rh, f->rl, 0, 1, -1);
p = downshift_component(p, g, hbits, lbits, f->gh, f->gl, 0, 1, -1);
p = downshift_component(p, b, hbits, lbits, f->bh, f->bl, 0, 1, -1);
p = downshift_component(p, a, hbits, lbits, f->ah, f->al, 0, 1, -1);
switch (f->size) {
case 1:
p |= p << 8;
FALLTHROUGH_INTENDED;
case 2:
p |= p << 16;
}
return p;
}
// ----------------------------------------------------------------------------
// extract a component from a word
uint32_t extract(uint32_t v, int h, int l, int bits)
{
assert(h);
if (l) {
v >>= l;
}
if (h != bits) {
v &= (1<<(h-l))-1;
}
return v;
}
// expand a component from sbits to dbits
uint32_t expand(uint32_t v, int sbits, int dbits)
{
if (dbits > sbits) {
assert(sbits);
if (sbits==1) {
v = (v<<dbits) - v;
} else {
if (dbits % sbits) {
v <<= (dbits-sbits);
dbits -= sbits;
do {
v |= v>>sbits;
dbits -= sbits;
sbits *= 2;
} while (dbits>0);
} else {
dbits -= sbits;
do {
v |= v<<sbits;
dbits -= sbits;
if (sbits*2 < dbits) {
sbits *= 2;
}
} while (dbits > 0);
}
}
}
return v;
}
// downsample a component from sbits to dbits
// and shift / construct the pixel
uint32_t downshift_component( uint32_t in, uint32_t v,
int sh, int sl, // src
int dh, int dl, // dst
int ch, int cl, // clear
int dither)
{
const int sbits = sh-sl;
const int dbits = dh-dl;
assert(sbits>=dbits);
if (sbits>dbits) {
if (dither>=0) {
v -= (v>>dbits); // fix up
const int shift = (GGL_DITHER_BITS - (sbits-dbits));
if (shift >= 0) v += (dither >> shift) << sl;
else v += (dither << (-shift)) << sl;
} else {
// don't do that right now, so we can reproduce the same
// artifacts we get on ARM (Where we don't do this)
// -> this is not really needed if we don't dither
//if (dBits > 1) { // result already OK if dBits==1
// v -= (v>>dbits); // fix up
// v += 1 << ((sbits-dbits)-1); // rounding
//}
}
}
// we need to clear the high bits of the source
if (ch) {
v <<= 32-sh;
sl += 32-sh;
sh = 32;
}
if (dl) {
if (cl || (sbits>dbits)) {
v >>= sh-dbits;
sl = 0;
sh = dbits;
in |= v<<dl;
} else {
// sbits==dbits and we don't need to clean the lower bits
// so we just have to shift the component to the right location
int shift = dh-sh;
in |= v<<shift;
}
} else {
// destination starts at bit 0
// ie: sh-dh == sh-dbits
int shift = sh-dh;
if (shift > 0) in |= v>>shift;
else if (shift < 0) in |= v<<shift;
else in |= v;
}
return in;
}
// ----------------------------------------------------------------------------
}; // namespace android

View File

@ -1,39 +0,0 @@
/* libs/pixelflinger/buffer.h
**
** Copyright 2006, 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 ANDROID_GGL_TEXTURE_H
#define ANDROID_GGL_TEXTURE_H
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_texture(context_t* c);
void ggl_set_surface(context_t* c, surface_t* dst, const GGLSurface* src);
void ggl_pick_texture(context_t* c);
void ggl_pick_cb(context_t* c);
uint32_t ggl_expand(uint32_t v, int sbits, int dbits);
uint32_t ggl_pack_color(context_t* c, int32_t format,
GGLcolor r, GGLcolor g, GGLcolor b, GGLcolor a);
}; // namespace android
#endif // ANDROID_GGL_TEXTURE_H

View File

@ -1,171 +0,0 @@
/* libs/pixelflinger/clear.cpp
**
** Copyright 2006, 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 <cutils/memory.h>
#include "clear.h"
#include "buffer.h"
namespace android {
// ----------------------------------------------------------------------------
static void ggl_clear(void* c, GGLbitfield mask);
static void ggl_clearColorx(void* c,
GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a);
static void ggl_clearDepthx(void* c, GGLclampx depth);
static void ggl_clearStencil(void* c, GGLint s);
// ----------------------------------------------------------------------------
void ggl_init_clear(context_t* c)
{
GGLContext& procs = *(GGLContext*)c;
GGL_INIT_PROC(procs, clear);
GGL_INIT_PROC(procs, clearColorx);
GGL_INIT_PROC(procs, clearDepthx);
GGL_INIT_PROC(procs, clearStencil);
c->state.clear.dirty = GGL_STENCIL_BUFFER_BIT |
GGL_COLOR_BUFFER_BIT |
GGL_DEPTH_BUFFER_BIT;
c->state.clear.depth = FIXED_ONE;
}
// ----------------------------------------------------------------------------
static void memset2d(context_t* c, const surface_t& s, uint32_t packed,
uint32_t l, uint32_t t, uint32_t w, uint32_t h)
{
const uint32_t size = c->formats[s.format].size;
const int32_t stride = s.stride * size;
uint8_t* dst = (uint8_t*)s.data + (l + t*s.stride)*size;
w *= size;
if (ggl_likely(int32_t(w) == stride)) {
// clear the whole thing in one call
w *= h;
h = 1;
}
switch (size) {
case 1:
do {
memset(dst, packed, w);
dst += stride;
} while(--h);
break;
case 2:
do {
android_memset16((uint16_t*)dst, packed, w);
dst += stride;
} while(--h);
break;
case 3: // XXX: 24-bit clear.
break;
case 4:
do {
android_memset32((uint32_t*)dst, packed, w);
dst += stride;
} while(--h);
break;
}
}
static inline GGLfixed fixedToZ(GGLfixed z) {
return GGLfixed(((int64_t(z) << 16) - z) >> 16);
}
static void ggl_clear(void* con, GGLbitfield mask)
{
GGL_CONTEXT(c, con);
// XXX: rgba-dithering, rgba-masking
// XXX: handle all formats of Z and S
const uint32_t l = c->state.scissor.left;
const uint32_t t = c->state.scissor.top;
uint32_t w = c->state.scissor.right - l;
uint32_t h = c->state.scissor.bottom - t;
if (!w || !h)
return;
// unexsiting buffers have no effect...
if (c->state.buffers.color.format == 0)
mask &= ~GGL_COLOR_BUFFER_BIT;
if (c->state.buffers.depth.format == 0)
mask &= ~GGL_DEPTH_BUFFER_BIT;
if (c->state.buffers.stencil.format == 0)
mask &= ~GGL_STENCIL_BUFFER_BIT;
if (mask & GGL_COLOR_BUFFER_BIT) {
if (c->state.clear.dirty & GGL_COLOR_BUFFER_BIT) {
c->state.clear.dirty &= ~GGL_COLOR_BUFFER_BIT;
uint32_t colorPacked = ggl_pack_color(c,
c->state.buffers.color.format,
gglFixedToIteratedColor(c->state.clear.r),
gglFixedToIteratedColor(c->state.clear.g),
gglFixedToIteratedColor(c->state.clear.b),
gglFixedToIteratedColor(c->state.clear.a));
c->state.clear.colorPacked = GGL_HOST_TO_RGBA(colorPacked);
}
const uint32_t packed = c->state.clear.colorPacked;
memset2d(c, c->state.buffers.color, packed, l, t, w, h);
}
if (mask & GGL_DEPTH_BUFFER_BIT) {
if (c->state.clear.dirty & GGL_DEPTH_BUFFER_BIT) {
c->state.clear.dirty &= ~GGL_DEPTH_BUFFER_BIT;
uint32_t depth = fixedToZ(c->state.clear.depth);
c->state.clear.depthPacked = (depth<<16)|depth;
}
const uint32_t packed = c->state.clear.depthPacked;
memset2d(c, c->state.buffers.depth, packed, l, t, w, h);
}
// XXX: do stencil buffer
}
static void ggl_clearColorx(void* con,
GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a)
{
GGL_CONTEXT(c, con);
c->state.clear.r = gglClampx(r);
c->state.clear.g = gglClampx(g);
c->state.clear.b = gglClampx(b);
c->state.clear.a = gglClampx(a);
c->state.clear.dirty |= GGL_COLOR_BUFFER_BIT;
}
static void ggl_clearDepthx(void* con, GGLclampx depth)
{
GGL_CONTEXT(c, con);
c->state.clear.depth = gglClampx(depth);
c->state.clear.dirty |= GGL_DEPTH_BUFFER_BIT;
}
static void ggl_clearStencil(void* con, GGLint s)
{
GGL_CONTEXT(c, con);
c->state.clear.stencil = s;
c->state.clear.dirty |= GGL_STENCIL_BUFFER_BIT;
}
}; // namespace android

View File

@ -1,30 +0,0 @@
/* libs/pixelflinger/clear.h
**
** Copyright 2006, 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 ANDROID_GGL_CLEAR_H
#define ANDROID_GGL_CLEAR_H
#include <pixelflinger/pixelflinger.h>
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_clear(context_t* c);
}; // namespace android
#endif // ANDROID_GGL_CLEAR_H

View File

@ -1,579 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssembler.cpp
**
** Copyright 2006, 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.
*/
#define LOG_TAG "ARMAssembler"
#include <stdio.h>
#include <stdlib.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <private/pixelflinger/ggl_context.h>
#include "ARMAssembler.h"
#include "CodeCache.h"
#include "disassem.h"
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark ARMAssembler...
#endif
ARMAssembler::ARMAssembler(const sp<Assembly>& assembly)
: ARMAssemblerInterface(),
mAssembly(assembly)
{
mBase = mPC = (uint32_t *)assembly->base();
mDuration = ggl_system_time();
}
ARMAssembler::~ARMAssembler()
{
}
uint32_t* ARMAssembler::pc() const
{
return mPC;
}
uint32_t* ARMAssembler::base() const
{
return mBase;
}
void ARMAssembler::reset()
{
mBase = mPC = (uint32_t *)mAssembly->base();
mBranchTargets.clear();
mLabels.clear();
mLabelsInverseMapping.clear();
mComments.clear();
}
int ARMAssembler::getCodegenArch()
{
return CODEGEN_ARCH_ARM;
}
// ----------------------------------------------------------------------------
void ARMAssembler::disassemble(const char* name)
{
if (name) {
printf("%s:\n", name);
}
size_t count = pc()-base();
uint32_t* i = base();
while (count--) {
ssize_t label = mLabelsInverseMapping.indexOfKey(i);
if (label >= 0) {
printf("%s:\n", mLabelsInverseMapping.valueAt(label));
}
ssize_t comment = mComments.indexOfKey(i);
if (comment >= 0) {
printf("; %s\n", mComments.valueAt(comment));
}
printf("%08x: %08x ", uintptr_t(i), int(i[0]));
::disassemble((uintptr_t)i);
i++;
}
}
void ARMAssembler::comment(const char* string)
{
mComments.add(mPC, string);
}
void ARMAssembler::label(const char* theLabel)
{
mLabels.add(theLabel, mPC);
mLabelsInverseMapping.add(mPC, theLabel);
}
void ARMAssembler::B(int cc, const char* label)
{
mBranchTargets.add(branch_target_t(label, mPC));
*mPC++ = (cc<<28) | (0xA<<24) | 0;
}
void ARMAssembler::BL(int cc, const char* label)
{
mBranchTargets.add(branch_target_t(label, mPC));
*mPC++ = (cc<<28) | (0xB<<24) | 0;
}
#if 0
#pragma mark -
#pragma mark Prolog/Epilog & Generate...
#endif
void ARMAssembler::prolog()
{
// write dummy prolog code
mPrologPC = mPC;
STM(AL, FD, SP, 1, LSAVED);
}
void ARMAssembler::epilog(uint32_t touched)
{
touched &= LSAVED;
if (touched) {
// write prolog code
uint32_t* pc = mPC;
mPC = mPrologPC;
STM(AL, FD, SP, 1, touched | LLR);
mPC = pc;
// write epilog code
LDM(AL, FD, SP, 1, touched | LLR);
BX(AL, LR);
} else { // heh, no registers to save!
// write prolog code
uint32_t* pc = mPC;
mPC = mPrologPC;
MOV(AL, 0, R0, R0); // NOP
mPC = pc;
// write epilog code
BX(AL, LR);
}
}
int ARMAssembler::generate(const char* name)
{
// fixup all the branches
size_t count = mBranchTargets.size();
while (count--) {
const branch_target_t& bt = mBranchTargets[count];
uint32_t* target_pc = mLabels.valueFor(bt.label);
LOG_ALWAYS_FATAL_IF(!target_pc,
"error resolving branch targets, target_pc is null");
int32_t offset = int32_t(target_pc - (bt.pc+2));
*bt.pc |= offset & 0xFFFFFF;
}
mAssembly->resize( int(pc()-base())*4 );
// the instruction cache is flushed by CodeCache
const int64_t duration = ggl_system_time() - mDuration;
const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
ALOGI(format, name, int(pc()-base()), base(), pc(), duration);
char value[PROPERTY_VALUE_MAX];
property_get("debug.pf.disasm", value, "0");
if (atoi(value) != 0) {
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
return OK;
}
uint32_t* ARMAssembler::pcForLabel(const char* label)
{
return mLabels.valueFor(label);
}
// ----------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Data Processing...
#endif
void ARMAssembler::dataProcessing(int opcode, int cc,
int s, int Rd, int Rn, uint32_t Op2)
{
*mPC++ = (cc<<28) | (opcode<<21) | (s<<20) | (Rn<<16) | (Rd<<12) | Op2;
}
#if 0
#pragma mark -
#pragma mark Multiply...
#endif
// multiply...
void ARMAssembler::MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn) {
if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MLA(r%u,r%u,r%u,r%u)", Rd,Rm,Rs,Rn);
*mPC++ = (cc<<28) | (1<<21) | (s<<20) |
(Rd<<16) | (Rn<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::MUL(int cc, int s,
int Rd, int Rm, int Rs) {
if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MUL(r%u,r%u,r%u)", Rd,Rm,Rs);
*mPC++ = (cc<<28) | (s<<20) | (Rd<<16) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
"UMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
*mPC++ = (cc<<28) | (1<<23) | (s<<20) |
(RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
"UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
*mPC++ = (cc<<28) | (1<<23) | (1<<21) | (s<<20) |
(RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
"SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
*mPC++ = (cc<<28) | (1<<23) | (1<<22) | (s<<20) |
(RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
"SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
*mPC++ = (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) |
(RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
}
#if 0
#pragma mark -
#pragma mark Branches...
#endif
// branches...
void ARMAssembler::B(int cc, uint32_t* pc)
{
int32_t offset = int32_t(pc - (mPC+2));
*mPC++ = (cc<<28) | (0xA<<24) | (offset & 0xFFFFFF);
}
void ARMAssembler::BL(int cc, uint32_t* pc)
{
int32_t offset = int32_t(pc - (mPC+2));
*mPC++ = (cc<<28) | (0xB<<24) | (offset & 0xFFFFFF);
}
void ARMAssembler::BX(int cc, int Rn)
{
*mPC++ = (cc<<28) | 0x12FFF10 | Rn;
}
#if 0
#pragma mark -
#pragma mark Data Transfer...
#endif
// data transfert...
void ARMAssembler::LDR(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<26) | (1<<20) | (Rn<<16) | (Rd<<12) | offset;
}
void ARMAssembler::LDRB(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<26) | (1<<22) | (1<<20) | (Rn<<16) | (Rd<<12) | offset;
}
void ARMAssembler::STR(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<26) | (Rn<<16) | (Rd<<12) | offset;
}
void ARMAssembler::STRB(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<26) | (1<<22) | (Rn<<16) | (Rd<<12) | offset;
}
void ARMAssembler::LDRH(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<20) | (Rn<<16) | (Rd<<12) | 0xB0 | offset;
}
void ARMAssembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<20) | (Rn<<16) | (Rd<<12) | 0xD0 | offset;
}
void ARMAssembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (1<<20) | (Rn<<16) | (Rd<<12) | 0xF0 | offset;
}
void ARMAssembler::STRH(int cc, int Rd, int Rn, uint32_t offset) {
*mPC++ = (cc<<28) | (Rn<<16) | (Rd<<12) | 0xB0 | offset;
}
#if 0
#pragma mark -
#pragma mark Block Data Transfer...
#endif
// block data transfer...
void ARMAssembler::LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list)
{ // ED FD EA FA IB IA DB DA
const uint8_t P[8] = { 1, 0, 1, 0, 1, 0, 1, 0 };
const uint8_t U[8] = { 1, 1, 0, 0, 1, 1, 0, 0 };
*mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
(uint32_t(U[dir])<<23) | (1<<20) | (W<<21) | (Rn<<16) | reg_list;
}
void ARMAssembler::STM(int cc, int dir,
int Rn, int W, uint32_t reg_list)
{ // ED FD EA FA IB IA DB DA
const uint8_t P[8] = { 0, 1, 0, 1, 1, 0, 1, 0 };
const uint8_t U[8] = { 0, 0, 1, 1, 1, 1, 0, 0 };
*mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
(uint32_t(U[dir])<<23) | (0<<20) | (W<<21) | (Rn<<16) | reg_list;
}
#if 0
#pragma mark -
#pragma mark Special...
#endif
// special...
void ARMAssembler::SWP(int cc, int Rn, int Rd, int Rm) {
*mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
}
void ARMAssembler::SWPB(int cc, int Rn, int Rd, int Rm) {
*mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
}
void ARMAssembler::SWI(int cc, uint32_t comment) {
*mPC++ = (cc<<28) | (0xF<<24) | comment;
}
#if 0
#pragma mark -
#pragma mark DSP instructions...
#endif
// DSP instructions...
void ARMAssembler::PLD(int Rn, uint32_t offset) {
LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))),
"PLD only P=1, W=0");
*mPC++ = 0xF550F000 | (Rn<<16) | offset;
}
void ARMAssembler::CLZ(int cc, int Rd, int Rm)
{
*mPC++ = (cc<<28) | 0x16F0F10| (Rd<<12) | Rm;
}
void ARMAssembler::QADD(int cc, int Rd, int Rm, int Rn)
{
*mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm;
}
void ARMAssembler::QDADD(int cc, int Rd, int Rm, int Rn)
{
*mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm;
}
void ARMAssembler::QSUB(int cc, int Rd, int Rm, int Rn)
{
*mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm;
}
void ARMAssembler::QDSUB(int cc, int Rd, int Rm, int Rn)
{
*mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm;
}
void ARMAssembler::SMUL(int cc, int xy,
int Rd, int Rm, int Rs)
{
*mPC++ = (cc<<28) | 0x1600080 | (Rd<<16) | (Rs<<8) | (xy<<4) | Rm;
}
void ARMAssembler::SMULW(int cc, int y,
int Rd, int Rm, int Rs)
{
*mPC++ = (cc<<28) | 0x12000A0 | (Rd<<16) | (Rs<<8) | (y<<4) | Rm;
}
void ARMAssembler::SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn)
{
*mPC++ = (cc<<28) | 0x1000080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (xy<<4) | Rm;
}
void ARMAssembler::SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm)
{
*mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm;
}
void ARMAssembler::SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn)
{
*mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm;
}
#if 0
#pragma mark -
#pragma mark Byte/half word extract and extend (ARMv6+ only)...
#endif
void ARMAssembler::UXTB16(int cc, int Rd, int Rm, int rotate)
{
*mPC++ = (cc<<28) | 0x6CF0070 | (Rd<<12) | ((rotate >> 3) << 10) | Rm;
}
#if 0
#pragma mark -
#pragma mark Bit manipulation (ARMv7+ only)...
#endif
// Bit manipulation (ARMv7+ only)...
void ARMAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
{
*mPC++ = (cc<<28) | 0x7E00000 | ((width-1)<<16) | (Rd<<12) | (lsb<<7) | 0x50 | Rn;
}
#if 0
#pragma mark -
#pragma mark Addressing modes...
#endif
int ARMAssembler::buildImmediate(
uint32_t immediate, uint32_t& rot, uint32_t& imm)
{
rot = 0;
imm = immediate;
if (imm > 0x7F) { // skip the easy cases
while (!(imm&3) || (imm&0xFC000000)) {
uint32_t newval;
newval = imm >> 2;
newval |= (imm&3) << 30;
imm = newval;
rot += 2;
if (rot == 32) {
rot = 0;
break;
}
}
}
rot = (16 - (rot>>1)) & 0xF;
if (imm>=0x100)
return -EINVAL;
if (((imm>>(rot<<1)) | (imm<<(32-(rot<<1)))) != immediate)
return -1;
return 0;
}
// shifters...
bool ARMAssembler::isValidImmediate(uint32_t immediate)
{
uint32_t rot, imm;
return buildImmediate(immediate, rot, imm) == 0;
}
uint32_t ARMAssembler::imm(uint32_t immediate)
{
uint32_t rot, imm;
int err = buildImmediate(immediate, rot, imm);
LOG_ALWAYS_FATAL_IF(err==-EINVAL,
"immediate %08x cannot be encoded",
immediate);
LOG_ALWAYS_FATAL_IF(err,
"immediate (%08x) encoding bogus!",
immediate);
return (1<<25) | (rot<<8) | imm;
}
uint32_t ARMAssembler::reg_imm(int Rm, int type, uint32_t shift)
{
return ((shift&0x1F)<<7) | ((type&0x3)<<5) | (Rm&0xF);
}
uint32_t ARMAssembler::reg_rrx(int Rm)
{
return (ROR<<5) | (Rm&0xF);
}
uint32_t ARMAssembler::reg_reg(int Rm, int type, int Rs)
{
return ((Rs&0xF)<<8) | ((type&0x3)<<5) | (1<<4) | (Rm&0xF);
}
// addressing modes...
// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
uint32_t ARMAssembler::immed12_pre(int32_t immed12, int W)
{
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
immed12);
return (1<<24) | (((uint32_t(immed12)>>31)^1)<<23) |
((W&1)<<21) | (abs(immed12)&0x7FF);
}
uint32_t ARMAssembler::immed12_post(int32_t immed12)
{
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
immed12);
return (((uint32_t(immed12)>>31)^1)<<23) | (abs(immed12)&0x7FF);
}
uint32_t ARMAssembler::reg_scale_pre(int Rm, int type,
uint32_t shift, int W)
{
return (1<<25) | (1<<24) |
(((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) |
reg_imm(abs(Rm), type, shift);
}
uint32_t ARMAssembler::reg_scale_post(int Rm, int type, uint32_t shift)
{
return (1<<25) | (((uint32_t(Rm)>>31)^1)<<23) | reg_imm(abs(Rm), type, shift);
}
// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
uint32_t ARMAssembler::immed8_pre(int32_t immed8, int W)
{
uint32_t offset = abs(immed8);
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
immed8);
return (1<<24) | (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
((W&1)<<21) | (((offset&0xF0)<<4)|(offset&0xF));
}
uint32_t ARMAssembler::immed8_post(int32_t immed8)
{
uint32_t offset = abs(immed8);
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
immed8);
return (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
(((offset&0xF0)<<4) | (offset&0xF));
}
uint32_t ARMAssembler::reg_pre(int Rm, int W)
{
return (1<<24) | (((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) | (abs(Rm)&0xF);
}
uint32_t ARMAssembler::reg_post(int Rm)
{
return (((uint32_t(Rm)>>31)^1)<<23) | (abs(Rm)&0xF);
}
}; // namespace android

View File

@ -1,187 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssembler.h
**
** Copyright 2006, 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 ANDROID_ARMASSEMBLER_H
#define ANDROID_ARMASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include "tinyutils/smartpointer.h"
#include "utils/Vector.h"
#include "utils/KeyedVector.h"
#include "ARMAssemblerInterface.h"
#include "CodeCache.h"
namespace android {
// ----------------------------------------------------------------------------
class ARMAssembler : public ARMAssemblerInterface
{
public:
explicit ARMAssembler(const sp<Assembly>& assembly);
virtual ~ARMAssembler();
uint32_t* base() const;
uint32_t* pc() const;
void disassemble(const char* name);
// ------------------------------------------------------------------------
// ARMAssemblerInterface...
// ------------------------------------------------------------------------
virtual void reset();
virtual int generate(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// shifters...
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
virtual uint32_t* pcForLabel(const char* label);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ARMAssembler(const ARMAssembler& rhs);
ARMAssembler& operator = (const ARMAssembler& rhs);
sp<Assembly> mAssembly;
uint32_t* mBase;
uint32_t* mPC;
uint32_t* mPrologPC;
int64_t mDuration;
struct branch_target_t {
inline branch_target_t() : label(0), pc(0) { }
inline branch_target_t(const char* l, uint32_t* p)
: label(l), pc(p) { }
const char* label;
uint32_t* pc;
};
Vector<branch_target_t> mBranchTargets;
KeyedVector< const char*, uint32_t* > mLabels;
KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
KeyedVector< uint32_t*, const char* > mComments;
};
}; // namespace android
#endif //ANDROID_ARMASSEMBLER_H

View File

@ -1,90 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssemblerInterface.cpp
**
** Copyright 2006, 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.
*/
#define LOG_TAG "pixelflinger-code"
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <log/log.h>
#include "ARMAssemblerInterface.h"
namespace android {
// ----------------------------------------------------------------------------
ARMAssemblerInterface::~ARMAssemblerInterface()
{
}
// --------------------------------------------------------------------
// The following two functions are static and used for initializers
// in the original ARM code. The above versions (without __), are now
// virtual, and can be overridden in the MIPS code. But since these are
// needed at initialization time, they must be static. Not thrilled with
// this implementation, but it works...
uint32_t ARMAssemblerInterface::__immed12_pre(int32_t immed12, int W)
{
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
immed12);
return (1<<24) | (((uint32_t(immed12)>>31)^1)<<23) |
((W&1)<<21) | (abs(immed12)&0x7FF);
}
uint32_t ARMAssemblerInterface::__immed8_pre(int32_t immed8, int W)
{
uint32_t offset = abs(immed8);
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
immed8);
return (1<<24) | (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
((W&1)<<21) | (((offset&0xF0)<<4)|(offset&0xF));
}
// The following four functions are required for address manipulation
// These are virtual functions, which can be overridden by architectures
// that need special handling of address values (e.g. 64-bit arch)
void ARMAssemblerInterface::ADDR_LDR(int cc, int Rd,
int Rn, uint32_t offset)
{
LDR(cc, Rd, Rn, offset);
}
void ARMAssemblerInterface::ADDR_STR(int cc, int Rd,
int Rn, uint32_t offset)
{
STR(cc, Rd, Rn, offset);
}
void ARMAssemblerInterface::ADDR_ADD(int cc, int s,
int Rd, int Rn, uint32_t Op2)
{
dataProcessing(opADD, cc, s, Rd, Rn, Op2);
}
void ARMAssemblerInterface::ADDR_SUB(int cc, int s,
int Rd, int Rn, uint32_t Op2)
{
dataProcessing(opSUB, cc, s, Rd, Rn, Op2);
}
}; // namespace android

View File

@ -1,349 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssemblerInterface.h
**
** Copyright 2006, 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 ANDROID_ARMASSEMBLER_INTERFACE_H
#define ANDROID_ARMASSEMBLER_INTERFACE_H
#include <stdint.h>
#include <sys/types.h>
namespace android {
// ----------------------------------------------------------------------------
class ARMAssemblerInterface
{
public:
virtual ~ARMAssemblerInterface();
enum {
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
HS = CS,
LO = CC
};
enum {
S = 1
};
enum {
LSL, LSR, ASR, ROR
};
enum {
ED, FD, EA, FA,
IB, IA, DB, DA
};
enum {
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15,
SP = R13,
LR = R14,
PC = R15
};
enum {
#define LIST(rr) L##rr=1<<rr
LIST(R0), LIST(R1), LIST(R2), LIST(R3), LIST(R4), LIST(R5), LIST(R6),
LIST(R7), LIST(R8), LIST(R9), LIST(R10), LIST(R11), LIST(R12),
LIST(R13), LIST(R14), LIST(R15),
LIST(SP), LIST(LR), LIST(PC),
#undef LIST
LSAVED = LR4|LR5|LR6|LR7|LR8|LR9|LR10|LR11 | LLR
};
enum {
CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64, CODEGEN_ARCH_MIPS64
};
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// these static versions are used for initializers on LDxx/STxx below
static uint32_t __immed12_pre(int32_t immed12, int W=0);
static uint32_t __immed8_pre(int32_t immed12, int W=0);
virtual bool isValidImmediate(uint32_t immed) = 0;
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm) = 0;
virtual uint32_t imm(uint32_t immediate) = 0;
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift) = 0;
virtual uint32_t reg_rrx(int Rm) = 0;
virtual uint32_t reg_reg(int Rm, int type, int Rs) = 0;
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0) = 0;
virtual uint32_t immed12_post(int32_t immed12) = 0;
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0) = 0;
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0) = 0;
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0) = 0;
virtual uint32_t immed8_post(int32_t immed8) = 0;
virtual uint32_t reg_pre(int Rm, int W=0) = 0;
virtual uint32_t reg_post(int Rm) = 0;
// -----------------------------------------------------------------------
// basic instructions & code generation
// -----------------------------------------------------------------------
// generate the code
virtual void reset() = 0;
virtual int generate(const char* name) = 0;
virtual void disassemble(const char* name) = 0;
virtual int getCodegenArch() = 0;
// construct prolog and epilog
virtual void prolog() = 0;
virtual void epilog(uint32_t touched) = 0;
virtual void comment(const char* string) = 0;
// data processing...
enum {
opAND, opEOR, opSUB, opRSB, opADD, opADC, opSBC, opRSC,
opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN,
opADD64, opSUB64
};
virtual void
dataProcessing( int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2) = 0;
// multiply...
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn) = 0;
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs) = 0;
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) = 0;
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) = 0;
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) = 0;
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) = 0;
// branches...
virtual void B(int cc, uint32_t* pc) = 0;
virtual void BL(int cc, uint32_t* pc) = 0;
virtual void BX(int cc, int Rn) = 0;
virtual void label(const char* theLabel) = 0;
virtual void B(int cc, const char* label) = 0;
virtual void BL(int cc, const char* label) = 0;
// valid only after generate() has been called
virtual uint32_t* pcForLabel(const char* label) = 0;
// data transfer...
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
// block data transfer...
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list) = 0;
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list) = 0;
// special...
virtual void SWP(int cc, int Rn, int Rd, int Rm) = 0;
virtual void SWPB(int cc, int Rn, int Rd, int Rm) = 0;
virtual void SWI(int cc, uint32_t comment) = 0;
// DSP instructions...
enum {
// B=0, T=1
// yx
xyBB = 0, // 0000,
xyTB = 2, // 0010,
xyBT = 4, // 0100,
xyTT = 6, // 0110,
yB = 0, // 0000,
yT = 4, // 0100
};
virtual void PLD(int Rn, uint32_t offset) = 0;
virtual void CLZ(int cc, int Rd, int Rm) = 0;
virtual void QADD(int cc, int Rd, int Rm, int Rn) = 0;
virtual void QDADD(int cc, int Rd, int Rm, int Rn) = 0;
virtual void QSUB(int cc, int Rd, int Rm, int Rn) = 0;
virtual void QDSUB(int cc, int Rd, int Rm, int Rn) = 0;
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs) = 0;
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs) = 0;
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn) = 0;
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm) = 0;
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn) = 0;
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate) = 0;
// bit manipulation...
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width) = 0;
// -----------------------------------------------------------------------
// convenience...
// -----------------------------------------------------------------------
inline void
ADC(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opADC, cc, s, Rd, Rn, Op2);
}
inline void
ADD(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opADD, cc, s, Rd, Rn, Op2);
}
inline void
AND(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opAND, cc, s, Rd, Rn, Op2);
}
inline void
BIC(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opBIC, cc, s, Rd, Rn, Op2);
}
inline void
EOR(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opEOR, cc, s, Rd, Rn, Op2);
}
inline void
MOV(int cc, int s, int Rd, uint32_t Op2) {
dataProcessing(opMOV, cc, s, Rd, 0, Op2);
}
inline void
MVN(int cc, int s, int Rd, uint32_t Op2) {
dataProcessing(opMVN, cc, s, Rd, 0, Op2);
}
inline void
ORR(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opORR, cc, s, Rd, Rn, Op2);
}
inline void
RSB(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opRSB, cc, s, Rd, Rn, Op2);
}
inline void
RSC(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opRSC, cc, s, Rd, Rn, Op2);
}
inline void
SBC(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opSBC, cc, s, Rd, Rn, Op2);
}
inline void
SUB(int cc, int s, int Rd, int Rn, uint32_t Op2) {
dataProcessing(opSUB, cc, s, Rd, Rn, Op2);
}
inline void
TEQ(int cc, int Rn, uint32_t Op2) {
dataProcessing(opTEQ, cc, 1, 0, Rn, Op2);
}
inline void
TST(int cc, int Rn, uint32_t Op2) {
dataProcessing(opTST, cc, 1, 0, Rn, Op2);
}
inline void
CMP(int cc, int Rn, uint32_t Op2) {
dataProcessing(opCMP, cc, 1, 0, Rn, Op2);
}
inline void
CMN(int cc, int Rn, uint32_t Op2) {
dataProcessing(opCMN, cc, 1, 0, Rn, Op2);
}
inline void SMULBB(int cc, int Rd, int Rm, int Rs) {
SMUL(cc, xyBB, Rd, Rm, Rs); }
inline void SMULTB(int cc, int Rd, int Rm, int Rs) {
SMUL(cc, xyTB, Rd, Rm, Rs); }
inline void SMULBT(int cc, int Rd, int Rm, int Rs) {
SMUL(cc, xyBT, Rd, Rm, Rs); }
inline void SMULTT(int cc, int Rd, int Rm, int Rs) {
SMUL(cc, xyTT, Rd, Rm, Rs); }
inline void SMULWB(int cc, int Rd, int Rm, int Rs) {
SMULW(cc, yB, Rd, Rm, Rs); }
inline void SMULWT(int cc, int Rd, int Rm, int Rs) {
SMULW(cc, yT, Rd, Rm, Rs); }
inline void
SMLABB(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLA(cc, xyBB, Rd, Rm, Rs, Rn); }
inline void
SMLATB(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLA(cc, xyTB, Rd, Rm, Rs, Rn); }
inline void
SMLABT(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLA(cc, xyBT, Rd, Rm, Rs, Rn); }
inline void
SMLATT(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLA(cc, xyTT, Rd, Rm, Rs, Rn); }
inline void
SMLALBB(int cc, int RdHi, int RdLo, int Rs, int Rm) {
SMLAL(cc, xyBB, RdHi, RdLo, Rs, Rm); }
inline void
SMLALTB(int cc, int RdHi, int RdLo, int Rs, int Rm) {
SMLAL(cc, xyTB, RdHi, RdLo, Rs, Rm); }
inline void
SMLALBT(int cc, int RdHi, int RdLo, int Rs, int Rm) {
SMLAL(cc, xyBT, RdHi, RdLo, Rs, Rm); }
inline void
SMLALTT(int cc, int RdHi, int RdLo, int Rs, int Rm) {
SMLAL(cc, xyTT, RdHi, RdLo, Rs, Rm); }
inline void
SMLAWB(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLAW(cc, yB, Rd, Rm, Rs, Rn); }
inline void
SMLAWT(int cc, int Rd, int Rm, int Rs, int Rn) {
SMLAW(cc, yT, Rd, Rm, Rs, Rn); }
// Address loading/storing/manipulation
virtual void ADDR_LDR(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_STR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_ADD(int cc, int s, int Rd,
int Rn, uint32_t Op2);
virtual void ADDR_SUB(int cc, int s, int Rd,
int Rn, uint32_t Op2);
};
}; // namespace android
#endif //ANDROID_ARMASSEMBLER_INTERFACE_H

View File

@ -1,311 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssemblerProxy.cpp
**
** Copyright 2006, 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 <sys/types.h>
#include "ARMAssemblerProxy.h"
namespace android {
// ----------------------------------------------------------------------------
ARMAssemblerProxy::ARMAssemblerProxy()
: mTarget(0)
{
}
ARMAssemblerProxy::ARMAssemblerProxy(ARMAssemblerInterface* target)
: mTarget(target)
{
}
ARMAssemblerProxy::~ARMAssemblerProxy()
{
delete mTarget;
}
void ARMAssemblerProxy::setTarget(ARMAssemblerInterface* target)
{
delete mTarget;
mTarget = target;
}
void ARMAssemblerProxy::reset() {
mTarget->reset();
}
int ARMAssemblerProxy::generate(const char* name) {
return mTarget->generate(name);
}
void ARMAssemblerProxy::disassemble(const char* name) {
return mTarget->disassemble(name);
}
int ARMAssemblerProxy::getCodegenArch()
{
return mTarget->getCodegenArch();
}
void ARMAssemblerProxy::prolog() {
mTarget->prolog();
}
void ARMAssemblerProxy::epilog(uint32_t touched) {
mTarget->epilog(touched);
}
void ARMAssemblerProxy::comment(const char* string) {
mTarget->comment(string);
}
// addressing modes
bool ARMAssemblerProxy::isValidImmediate(uint32_t immed)
{
return mTarget->isValidImmediate(immed);
}
int ARMAssemblerProxy::buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm)
{
return mTarget->buildImmediate(i, rot, imm);
}
uint32_t ARMAssemblerProxy::imm(uint32_t immediate)
{
return mTarget->imm(immediate);
}
uint32_t ARMAssemblerProxy::reg_imm(int Rm, int type, uint32_t shift)
{
return mTarget->reg_imm(Rm, type, shift);
}
uint32_t ARMAssemblerProxy::reg_rrx(int Rm)
{
return mTarget->reg_rrx(Rm);
}
uint32_t ARMAssemblerProxy::reg_reg(int Rm, int type, int Rs)
{
return mTarget->reg_reg(Rm, type, Rs);
}
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
uint32_t ARMAssemblerProxy::immed12_pre(int32_t immed12, int W)
{
return mTarget->immed12_pre(immed12, W);
}
uint32_t ARMAssemblerProxy::immed12_post(int32_t immed12)
{
return mTarget->immed12_post(immed12);
}
uint32_t ARMAssemblerProxy::reg_scale_pre(int Rm, int type, uint32_t shift, int W)
{
return mTarget->reg_scale_pre(Rm, type, shift, W);
}
uint32_t ARMAssemblerProxy::reg_scale_post(int Rm, int type, uint32_t shift)
{
return mTarget->reg_scale_post(Rm, type, shift);
}
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
uint32_t ARMAssemblerProxy::immed8_pre(int32_t immed8, int W)
{
return mTarget->immed8_pre(immed8, W);
}
uint32_t ARMAssemblerProxy::immed8_post(int32_t immed8)
{
return mTarget->immed8_post(immed8);
}
uint32_t ARMAssemblerProxy::reg_pre(int Rm, int W)
{
return mTarget->reg_pre(Rm, W);
}
uint32_t ARMAssemblerProxy::reg_post(int Rm)
{
return mTarget->reg_post(Rm);
}
//------------------------------------------------------------------------
void ARMAssemblerProxy::dataProcessing( int opcode, int cc, int s,
int Rd, int Rn, uint32_t Op2)
{
mTarget->dataProcessing(opcode, cc, s, Rd, Rn, Op2);
}
void ARMAssemblerProxy::MLA(int cc, int s, int Rd, int Rm, int Rs, int Rn) {
mTarget->MLA(cc, s, Rd, Rm, Rs, Rn);
}
void ARMAssemblerProxy::MUL(int cc, int s, int Rd, int Rm, int Rs) {
mTarget->MUL(cc, s, Rd, Rm, Rs);
}
void ARMAssemblerProxy::UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
mTarget->UMULL(cc, s, RdLo, RdHi, Rm, Rs);
}
void ARMAssemblerProxy::UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
mTarget->UMUAL(cc, s, RdLo, RdHi, Rm, Rs);
}
void ARMAssemblerProxy::SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
mTarget->SMULL(cc, s, RdLo, RdHi, Rm, Rs);
}
void ARMAssemblerProxy::SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs) {
mTarget->SMUAL(cc, s, RdLo, RdHi, Rm, Rs);
}
void ARMAssemblerProxy::B(int cc, uint32_t* pc) {
mTarget->B(cc, pc);
}
void ARMAssemblerProxy::BL(int cc, uint32_t* pc) {
mTarget->BL(cc, pc);
}
void ARMAssemblerProxy::BX(int cc, int Rn) {
mTarget->BX(cc, Rn);
}
void ARMAssemblerProxy::label(const char* theLabel) {
mTarget->label(theLabel);
}
void ARMAssemblerProxy::B(int cc, const char* label) {
mTarget->B(cc, label);
}
void ARMAssemblerProxy::BL(int cc, const char* label) {
mTarget->BL(cc, label);
}
uint32_t* ARMAssemblerProxy::pcForLabel(const char* label) {
return mTarget->pcForLabel(label);
}
void ARMAssemblerProxy::LDR(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->LDR(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::LDRB(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->LDRB(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::STR(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->STR(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::STRB(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->STRB(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::LDRH(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->LDRH(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::LDRSB(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->LDRSB(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::LDRSH(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->LDRSH(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::STRH(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->STRH(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::LDM(int cc, int dir, int Rn, int W, uint32_t reg_list) {
mTarget->LDM(cc, dir, Rn, W, reg_list);
}
void ARMAssemblerProxy::STM(int cc, int dir, int Rn, int W, uint32_t reg_list) {
mTarget->STM(cc, dir, Rn, W, reg_list);
}
void ARMAssemblerProxy::SWP(int cc, int Rn, int Rd, int Rm) {
mTarget->SWP(cc, Rn, Rd, Rm);
}
void ARMAssemblerProxy::SWPB(int cc, int Rn, int Rd, int Rm) {
mTarget->SWPB(cc, Rn, Rd, Rm);
}
void ARMAssemblerProxy::SWI(int cc, uint32_t comment) {
mTarget->SWI(cc, comment);
}
void ARMAssemblerProxy::PLD(int Rn, uint32_t offset) {
mTarget->PLD(Rn, offset);
}
void ARMAssemblerProxy::CLZ(int cc, int Rd, int Rm) {
mTarget->CLZ(cc, Rd, Rm);
}
void ARMAssemblerProxy::QADD(int cc, int Rd, int Rm, int Rn) {
mTarget->QADD(cc, Rd, Rm, Rn);
}
void ARMAssemblerProxy::QDADD(int cc, int Rd, int Rm, int Rn) {
mTarget->QDADD(cc, Rd, Rm, Rn);
}
void ARMAssemblerProxy::QSUB(int cc, int Rd, int Rm, int Rn) {
mTarget->QSUB(cc, Rd, Rm, Rn);
}
void ARMAssemblerProxy::QDSUB(int cc, int Rd, int Rm, int Rn) {
mTarget->QDSUB(cc, Rd, Rm, Rn);
}
void ARMAssemblerProxy::SMUL(int cc, int xy, int Rd, int Rm, int Rs) {
mTarget->SMUL(cc, xy, Rd, Rm, Rs);
}
void ARMAssemblerProxy::SMULW(int cc, int y, int Rd, int Rm, int Rs) {
mTarget->SMULW(cc, y, Rd, Rm, Rs);
}
void ARMAssemblerProxy::SMLA(int cc, int xy, int Rd, int Rm, int Rs, int Rn) {
mTarget->SMLA(cc, xy, Rd, Rm, Rs, Rn);
}
void ARMAssemblerProxy::SMLAL( int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm) {
mTarget->SMLAL(cc, xy, RdHi, RdLo, Rs, Rm);
}
void ARMAssemblerProxy::SMLAW(int cc, int y, int Rd, int Rm, int Rs, int Rn) {
mTarget->SMLAW(cc, y, Rd, Rm, Rs, Rn);
}
void ARMAssemblerProxy::UXTB16(int cc, int Rd, int Rm, int rotate) {
mTarget->UXTB16(cc, Rd, Rm, rotate);
}
void ARMAssemblerProxy::UBFX(int cc, int Rd, int Rn, int lsb, int width) {
mTarget->UBFX(cc, Rd, Rn, lsb, width);
}
void ARMAssemblerProxy::ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->ADDR_LDR(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::ADDR_STR(int cc, int Rd, int Rn, uint32_t offset) {
mTarget->ADDR_STR(cc, Rd, Rn, offset);
}
void ARMAssemblerProxy::ADDR_ADD(int cc, int s, int Rd, int Rn, uint32_t Op2){
mTarget->ADDR_ADD(cc, s, Rd, Rn, Op2);
}
void ARMAssemblerProxy::ADDR_SUB(int cc, int s, int Rd, int Rn, uint32_t Op2){
mTarget->ADDR_SUB(cc, s, Rd, Rn, Op2);
}
}; // namespace android

View File

@ -1,164 +0,0 @@
/* libs/pixelflinger/codeflinger/ARMAssemblerProxy.h
**
** Copyright 2006, 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 ANDROID_ARMASSEMBLER_PROXY_H
#define ANDROID_ARMASSEMBLER_PROXY_H
#include <stdint.h>
#include <sys/types.h>
#include "ARMAssemblerInterface.h"
namespace android {
// ----------------------------------------------------------------------------
class ARMAssemblerProxy : public ARMAssemblerInterface
{
public:
// ARMAssemblerProxy take ownership of the target
ARMAssemblerProxy();
explicit ARMAssemblerProxy(ARMAssemblerInterface* target);
virtual ~ARMAssemblerProxy();
void setTarget(ARMAssemblerInterface* target);
virtual void reset();
virtual int generate(const char* name);
virtual void disassemble(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
uint32_t* pcForLabel(const char* label);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = __immed8_pre(0));
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
virtual void ADDR_LDR(int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_STR (int cc, int Rd,
int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_ADD(int cc, int s, int Rd,
int Rn, uint32_t Op2);
virtual void ADDR_SUB(int cc, int s, int Rd,
int Rn, uint32_t Op2);
private:
ARMAssemblerInterface* mTarget;
};
}; // namespace android
#endif //ANDROID_ARMASSEMBLER_PROXY_H

File diff suppressed because it is too large Load Diff

View File

@ -1,290 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef ANDROID_ARMTOARM64ASSEMBLER_H
#define ANDROID_ARMTOARM64ASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include "tinyutils/smartpointer.h"
#include "utils/Vector.h"
#include "utils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
#include "codeflinger/ARMAssemblerInterface.h"
#include "codeflinger/CodeCache.h"
namespace android {
// ----------------------------------------------------------------------------
class ArmToArm64Assembler : public ARMAssemblerInterface
{
public:
explicit ArmToArm64Assembler(const sp<Assembly>& assembly);
explicit ArmToArm64Assembler(void *base);
virtual ~ArmToArm64Assembler();
uint32_t* base() const;
uint32_t* pc() const;
void disassemble(const char* name);
// ------------------------------------------------------------------------
// ARMAssemblerInterface...
// ------------------------------------------------------------------------
virtual void reset();
virtual int generate(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// shifters...
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
virtual uint32_t* pcForLabel(const char* label);
virtual void ADDR_LDR(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void ADDR_ADD(int cc, int s, int Rd,
int Rn, uint32_t Op2);
virtual void ADDR_SUB(int cc, int s, int Rd,
int Rn, uint32_t Op2);
virtual void ADDR_STR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ArmToArm64Assembler(const ArmToArm64Assembler& rhs);
ArmToArm64Assembler& operator = (const ArmToArm64Assembler& rhs);
// -----------------------------------------------------------------------
// helper functions
// -----------------------------------------------------------------------
void dataTransfer(int operation, int cc, int Rd, int Rn,
uint32_t operand_type, uint32_t size = 32);
void dataProcessingCommon(int opcode, int s,
int Rd, int Rn, uint32_t Op2);
// -----------------------------------------------------------------------
// Arm64 instructions
// -----------------------------------------------------------------------
uint32_t A64_B_COND(uint32_t cc, uint32_t offset);
uint32_t A64_RET(uint32_t Rn);
uint32_t A64_LDRSTR_Wm_SXTW_0(uint32_t operation,
uint32_t size, uint32_t Rt,
uint32_t Rn, uint32_t Rm);
uint32_t A64_STR_IMM_PreIndex(uint32_t Rt, uint32_t Rn, int32_t simm);
uint32_t A64_LDR_IMM_PostIndex(uint32_t Rt,uint32_t Rn, int32_t simm);
uint32_t A64_ADD_X_Wm_SXTW(uint32_t Rd, uint32_t Rn, uint32_t Rm,
uint32_t amount);
uint32_t A64_SUB_X_Wm_SXTW(uint32_t Rd, uint32_t Rn, uint32_t Rm,
uint32_t amount);
uint32_t A64_ADD_IMM_X(uint32_t Rd, uint32_t Rn,
uint32_t imm, uint32_t shift = 0);
uint32_t A64_SUB_IMM_X(uint32_t Rd, uint32_t Rn,
uint32_t imm, uint32_t shift = 0);
uint32_t A64_ADD_X(uint32_t Rd, uint32_t Rn,
uint32_t Rm, uint32_t shift = 0, uint32_t amount = 0);
uint32_t A64_ADD_W(uint32_t Rd, uint32_t Rn, uint32_t Rm,
uint32_t shift = 0, uint32_t amount = 0);
uint32_t A64_SUB_W(uint32_t Rd, uint32_t Rn, uint32_t Rm,
uint32_t shift = 0, uint32_t amount = 0,
uint32_t setflag = 0);
uint32_t A64_AND_W(uint32_t Rd, uint32_t Rn,
uint32_t Rm, uint32_t shift = 0, uint32_t amount = 0);
uint32_t A64_ORR_W(uint32_t Rd, uint32_t Rn,
uint32_t Rm, uint32_t shift = 0, uint32_t amount = 0);
uint32_t A64_ORN_W(uint32_t Rd, uint32_t Rn,
uint32_t Rm, uint32_t shift = 0, uint32_t amount = 0);
uint32_t A64_MOVZ_W(uint32_t Rd, uint32_t imm, uint32_t shift);
uint32_t A64_MOVZ_X(uint32_t Rd, uint32_t imm, uint32_t shift);
uint32_t A64_MOVK_W(uint32_t Rd, uint32_t imm, uint32_t shift);
uint32_t A64_SMADDL(uint32_t Rd, uint32_t Rn, uint32_t Rm, uint32_t Ra);
uint32_t A64_MADD_W(uint32_t Rd, uint32_t Rn, uint32_t Rm, uint32_t Ra);
uint32_t A64_SBFM_W(uint32_t Rd, uint32_t Rn,
uint32_t immr, uint32_t imms);
uint32_t A64_UBFM_W(uint32_t Rd, uint32_t Rn,
uint32_t immr, uint32_t imms);
uint32_t A64_UBFM_X(uint32_t Rd, uint32_t Rn,
uint32_t immr, uint32_t imms);
uint32_t A64_EXTR_W(uint32_t Rd, uint32_t Rn, uint32_t Rm, uint32_t lsb);
uint32_t A64_CSEL_X(uint32_t Rd, uint32_t Rn, uint32_t Rm, uint32_t cond);
uint32_t A64_CSEL_W(uint32_t Rd, uint32_t Rn, uint32_t Rm, uint32_t cond);
uint32_t* mBase;
uint32_t* mPC;
uint32_t* mPrologPC;
int64_t mDuration;
uint32_t mTmpReg1, mTmpReg2, mTmpReg3, mZeroReg;
struct branch_target_t {
inline branch_target_t() : label(0), pc(0) { }
inline branch_target_t(const char* l, uint32_t* p)
: label(l), pc(p) { }
const char* label;
uint32_t* pc;
};
sp<Assembly> mAssembly;
Vector<branch_target_t> mBranchTargets;
KeyedVector< const char*, uint32_t* > mLabels;
KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
KeyedVector< uint32_t*, const char* > mComments;
enum operand_type_t
{
OPERAND_REG = 0x20,
OPERAND_IMM,
OPERAND_REG_IMM,
OPERAND_REG_OFFSET,
OPERAND_UNSUPPORTED
};
struct addr_mode_t {
int32_t immediate;
bool writeback;
bool preindex;
bool postindex;
int32_t reg_imm_Rm;
int32_t reg_imm_type;
uint32_t reg_imm_shift;
int32_t reg_offset;
} mAddrMode;
};
}; // namespace android
#endif //ANDROID_ARM64ASSEMBLER_H

View File

@ -1,316 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
struct disasm_table_entry_t
{
uint32_t mask;
uint32_t value;
const char* instr_template;
};
static disasm_table_entry_t disasm_table[] =
{
{0xff000000, 0x91000000, "add <xd|sp>, <xn|sp>, #<imm1>, <shift1>"},
{0xff000000, 0xd1000000, "sub <xd|sp>, <xn|sp>, #<imm1>, <shift1>"},
{0xff200000, 0x8b000000, "add <xd>, <xn>, <xm>, <shift2> #<amt1>"},
{0xff200000, 0x0b000000, "add <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff200000, 0x4b000000, "sub <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff200000, 0x6b000000, "subs <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff200000, 0x0a000000, "and <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff200000, 0x2a000000, "orr <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff200000, 0x2a200000, "orn <wd>, <wn>, <wm>, <shift2> #<amt1>"},
{0xff800000, 0x72800000, "movk <wd>, #<imm2>, lsl #<shift3>"},
{0xff800000, 0x52800000, "movz <wd>, #<imm2>, lsl #<shift3>"},
{0xff800000, 0xd2800000, "movz <xd>, #<imm2>, lsl #<shift3>"},
{0xffe00c00, 0x1a800000, "csel <wd>, <wn>, <wm>, <cond1>"},
{0xffe00c00, 0x9a800000, "csel <xd>, <xn>, <xm>, <cond1>"},
{0xffe00c00, 0x5a800000, "csinv <wd>, <wn>, <wm>, <cond1>"},
{0xffe08000, 0x1b000000, "madd <wd>, <wn>, <wm>, <wa>"},
{0xffe08000, 0x9b200000, "smaddl <xd>, <wn>, <wm>, <xa>"},
{0xffe04c00, 0xb8604800, "ldr <wt>, [<xn|sp>, <r1><m1>, <ext1> #<amt2>]"},
{0xffe04c00, 0xb8204800, "str <wt>, [<xn|sp>, <r1><m1>, <ext1> #<amt2>]"},
{0xffe04c00, 0xf8604800, "ldr <xt>, [<xn|sp>, <r1><m1>, <ext1> #<amt3>]"},
{0xffe04c00, 0xf8204800, "str <xt>, [<xn|sp>, <r1><m1>, <ext1> #<amt3>]"},
{0xffe04c00, 0x38604800, "ldrb <wt>, [<xn|sp>, <r1><m1>, <ext1> <amt5>]"},
{0xffe04c00, 0x38204800, "strb <wt>, [<xn|sp>, <r1><m1>, <ext1> <amt5>]"},
{0xffe04c00, 0x78604800, "ldrh <wt>, [<xn|sp>, <r1><m1>, <ext1> #<amt6>]"},
{0xffe04c00, 0x78204800, "strh <wt>, [<xn|sp>, <r1><m1>, <ext1> #<amt6>]"},
{0xffe00c00, 0xb8400400, "ldr <wt>, [<xn|sp>], #<simm1>"},
{0xffe00c00, 0xb8000c00, "str <wt>, [<xn|sp>, #<simm1>]!"},
{0xffc00000, 0x13000000, "sbfm <wd>, <wn>, #<immr1>, #<imms1>"},
{0xffc00000, 0x53000000, "ubfm <wd>, <wn>, #<immr1>, #<imms1>"},
{0xffc00000, 0xd3400000, "ubfm <xd>, <xn>, #<immr1>, #<imms1>"},
{0xffe00000, 0x13800000, "extr <wd>, <wn>, <wm>, #<lsb1>"},
{0xff000000, 0x54000000, "b.<cond2> <label1>"},
{0xfffffc1f, 0xd65f0000, "ret <xn>"},
{0xffe00000, 0x8b200000, "add <xd|sp>, <xn|sp>, <r2><m1>, <ext2> #<amt4>"},
{0xffe00000, 0xcb200000, "sub <xd|sp>, <xn|sp>, <r2><m1>, <ext2> #<amt4>"}
};
static int32_t bits_signed(uint32_t instr, uint32_t msb, uint32_t lsb)
{
int32_t value;
value = ((int32_t)instr) << (31 - msb);
value >>= (31 - msb);
value >>= lsb;
return value;
}
static uint32_t bits_unsigned(uint32_t instr, uint32_t msb, uint32_t lsb)
{
uint32_t width = msb - lsb + 1;
uint32_t mask = (1 << width) - 1;
return ((instr >> lsb) & mask);
}
static void get_token(const char *instr, uint32_t index, char *token)
{
uint32_t i, j;
for(i = index, j = 0; i < strlen(instr); ++i)
{
if(instr[index] == '<' && instr[i] == '>')
{
token[j++] = instr[i];
break;
}
else if(instr[index] != '<' && instr[i] == '<')
{
break;
}
else
{
token[j++] = instr[i];
}
}
token[j] = '\0';
return;
}
static const char * token_cc_table[] =
{
"eq", "ne", "cs", "cc", "mi",
"pl", "vs", "vc", "hi", "ls",
"ge", "lt", "gt", "le", "al", "nv"
};
static void decode_rx_zr_token(uint32_t reg, const char *prefix, char *instr_part)
{
if(reg == 31)
sprintf(instr_part, "%s%s", prefix, "zr");
else
sprintf(instr_part, "%s%d", prefix, reg);
}
static void decode_token(uint32_t code, char *token, char *instr_part)
{
if(strcmp(token, "<imm1>") == 0)
sprintf(instr_part, "0x%x", bits_unsigned(code, 21,10));
else if(strcmp(token, "<imm2>") == 0)
sprintf(instr_part, "0x%x", bits_unsigned(code, 20,5));
else if(strcmp(token, "<shift1>") == 0)
sprintf(instr_part, "lsl #%d", bits_unsigned(code, 23,22) * 12);
else if(strcmp(token, "<shift2>") == 0)
{
static const char * shift2_table[] = { "lsl", "lsr", "asr", "ror"};
sprintf(instr_part, "%s", shift2_table[bits_unsigned(code, 23,22)]);
}
else if(strcmp(token, "<shift3>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 22,21) * 16);
else if(strcmp(token, "<amt1>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 15,10));
else if(strcmp(token, "<amt2>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 12,12) * 2);
else if(strcmp(token, "<amt3>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 12,12) * 3);
else if(strcmp(token, "<amt4>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 12,10));
else if(strcmp(token, "<amt5>") == 0)
{
static const char * amt5_table[] = {"", "#0"};
sprintf(instr_part, "%s", amt5_table[bits_unsigned(code, 12,12)]);
}
else if(strcmp(token, "<amt6>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 12,12));
else if(strcmp(token, "<simm1>") == 0)
sprintf(instr_part, "%d", bits_signed(code, 20,12));
else if(strcmp(token, "<immr1>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 21,16));
else if(strcmp(token, "<imms1>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 15,10));
else if(strcmp(token, "<lsb1>") == 0)
sprintf(instr_part, "%d", bits_unsigned(code, 15,10));
else if(strcmp(token, "<cond1>") == 0)
sprintf(instr_part, "%s", token_cc_table[bits_unsigned(code, 15,12)]);
else if(strcmp(token, "<cond2>") == 0)
sprintf(instr_part, "%s", token_cc_table[bits_unsigned(code, 4,0)]);
else if(strcmp(token, "<r1>") == 0)
{
const char * token_r1_table[] =
{
"reserved", "reserved", "w", "x",
"reserved", "reserved", "w", "x"
};
sprintf(instr_part, "%s", token_r1_table[bits_unsigned(code, 15,13)]);
}
else if(strcmp(token, "<r2>") == 0)
{
static const char * token_r2_table[] =
{
"w","w","w", "x", "w", "w", "w", "x"
};
sprintf(instr_part, "%s", token_r2_table[bits_unsigned(code, 15,13)]);
}
else if(strcmp(token, "<m1>") == 0)
{
uint32_t reg = bits_unsigned(code, 20,16);
if(reg == 31)
sprintf(instr_part, "%s", "zr");
else
sprintf(instr_part, "%d", reg);
}
else if(strcmp(token, "<ext1>") == 0)
{
static const char * token_ext1_table[] =
{
"reserved","reserved","uxtw", "lsl",
"reserved","reserved", "sxtw", "sxtx"
};
sprintf(instr_part, "%s", token_ext1_table[bits_unsigned(code, 15,13)]);
}
else if(strcmp(token, "<ext2>") == 0)
{
static const char * token_ext2_table[] =
{
"uxtb","uxth","uxtw","uxtx",
"sxtb","sxth","sxtw","sxtx"
};
sprintf(instr_part, "%s", token_ext2_table[bits_unsigned(code, 15,13)]);
}
else if (strcmp(token, "<label1>") == 0)
{
int32_t offset = bits_signed(code, 23,5) * 4;
if(offset > 0)
sprintf(instr_part, "#.+%d", offset);
else
sprintf(instr_part, "#.-%d", -offset);
}
else if (strcmp(token, "<xn|sp>") == 0)
{
uint32_t reg = bits_unsigned(code, 9, 5);
if(reg == 31)
sprintf(instr_part, "%s", "sp");
else
sprintf(instr_part, "x%d", reg);
}
else if (strcmp(token, "<xd|sp>") == 0)
{
uint32_t reg = bits_unsigned(code, 4, 0);
if(reg == 31)
sprintf(instr_part, "%s", "sp");
else
sprintf(instr_part, "x%d", reg);
}
else if (strcmp(token, "<xn>") == 0)
decode_rx_zr_token(bits_unsigned(code, 9, 5), "x", instr_part);
else if (strcmp(token, "<xd>") == 0)
decode_rx_zr_token(bits_unsigned(code, 4, 0), "x", instr_part);
else if (strcmp(token, "<xm>") == 0)
decode_rx_zr_token(bits_unsigned(code, 20, 16), "x", instr_part);
else if (strcmp(token, "<xa>") == 0)
decode_rx_zr_token(bits_unsigned(code, 14, 10), "x", instr_part);
else if (strcmp(token, "<xt>") == 0)
decode_rx_zr_token(bits_unsigned(code, 4, 0), "x", instr_part);
else if (strcmp(token, "<wn>") == 0)
decode_rx_zr_token(bits_unsigned(code, 9, 5), "w", instr_part);
else if (strcmp(token, "<wd>") == 0)
decode_rx_zr_token(bits_unsigned(code, 4, 0), "w", instr_part);
else if (strcmp(token, "<wm>") == 0)
decode_rx_zr_token(bits_unsigned(code, 20, 16), "w", instr_part);
else if (strcmp(token, "<wa>") == 0)
decode_rx_zr_token(bits_unsigned(code, 14, 10), "w", instr_part);
else if (strcmp(token, "<wt>") == 0)
decode_rx_zr_token(bits_unsigned(code, 4, 0), "w", instr_part);
else
{
sprintf(instr_part, "error");
}
return;
}
int arm64_disassemble(uint32_t code, char* instr)
{
uint32_t i;
char token[256];
char instr_part[256];
if(instr == NULL)
return -1;
bool matched = false;
disasm_table_entry_t *entry = NULL;
for(i = 0; i < sizeof(disasm_table)/sizeof(disasm_table_entry_t); ++i)
{
entry = &disasm_table[i];
if((code & entry->mask) == entry->value)
{
matched = true;
break;
}
}
if(matched == false)
{
strcpy(instr, "Unknown Instruction");
return -1;
}
else
{
uint32_t index = 0;
uint32_t length = strlen(entry->instr_template);
instr[0] = '\0';
do
{
get_token(entry->instr_template, index, token);
if(token[0] == '<')
{
decode_token(code, token, instr_part);
strcat(instr, instr_part);
}
else
{
strcat(instr, token);
}
index += strlen(token);
}while(index < length);
return 0;
}
}

View File

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

View File

@ -1,217 +0,0 @@
/* libs/pixelflinger/codeflinger/CodeCache.cpp
**
** Copyright 2006, 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.
*/
#define LOG_TAG "CodeCache"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cutils/ashmem.h>
#include <log/log.h>
#include "CodeCache.h"
namespace android {
// ----------------------------------------------------------------------------
#if defined(__arm__) || defined(__aarch64__)
#include <unistd.h>
#include <errno.h>
#endif
#if defined(__mips__)
#include <asm/cachectl.h>
#include <errno.h>
#endif
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// A dlmalloc mspace is used to manage the code cache over a mmaped region.
#define HAVE_MMAP 0
#define HAVE_MREMAP 0
#define HAVE_MORECORE 0
#define MALLOC_ALIGNMENT 16
#define MSPACES 1
#define NO_MALLINFO 1
#define ONLY_MSPACES 1
// Custom heap error handling.
#define PROCEED_ON_ERROR 0
static void heap_error(const char* msg, const char* function, void* p);
#define CORRUPTION_ERROR_ACTION(m) \
heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__, NULL)
#define USAGE_ERROR_ACTION(m,p) \
heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wexpansion-to-defined"
#pragma GCC diagnostic ignored "-Wnull-pointer-arithmetic"
#include "../../../../external/dlmalloc/malloc.c"
#pragma GCC diagnostic pop
static void heap_error(const char* msg, const char* function, void* p) {
ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: CODE FLINGER: %s IN %s addr=%p",
msg, function, p);
/* So that we can get a memory dump around p */
*((int **) 0xdeadbaad) = (int *) p;
}
// ----------------------------------------------------------------------------
static void* gExecutableStore = NULL;
static mspace gMspace = NULL;
const size_t kMaxCodeCacheCapacity = 1024 * 1024;
static mspace getMspace()
{
if (gExecutableStore == NULL) {
int fd = ashmem_create_region("CodeFlinger code cache",
kMaxCodeCacheCapacity);
LOG_ALWAYS_FATAL_IF(fd < 0,
"Creating code cache, ashmem_create_region "
"failed with error '%s'", strerror(errno));
gExecutableStore = mmap(NULL, kMaxCodeCacheCapacity,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE, fd, 0);
LOG_ALWAYS_FATAL_IF(gExecutableStore == MAP_FAILED,
"Creating code cache, mmap failed with error "
"'%s'", strerror(errno));
close(fd);
gMspace = create_mspace_with_base(gExecutableStore, kMaxCodeCacheCapacity,
/*locked=*/ false);
mspace_set_footprint_limit(gMspace, kMaxCodeCacheCapacity);
}
return gMspace;
}
Assembly::Assembly(size_t size)
: mCount(0), mSize(0)
{
mBase = (uint32_t*)mspace_malloc(getMspace(), size);
LOG_ALWAYS_FATAL_IF(mBase == NULL,
"Failed to create Assembly of size %zd in executable "
"store of size %zd", size, kMaxCodeCacheCapacity);
mSize = size;
}
Assembly::~Assembly()
{
mspace_free(getMspace(), mBase);
}
void Assembly::incStrong(const void*) const
{
mCount.fetch_add(1, std::memory_order_relaxed);
}
void Assembly::decStrong(const void*) const
{
if (mCount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete this;
}
}
ssize_t Assembly::size() const
{
if (!mBase) return NO_MEMORY;
return mSize;
}
uint32_t* Assembly::base() const
{
return mBase;
}
ssize_t Assembly::resize(size_t newSize)
{
mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize);
LOG_ALWAYS_FATAL_IF(mBase == NULL,
"Failed to resize Assembly to %zd in code cache "
"of size %zd", newSize, kMaxCodeCacheCapacity);
mSize = newSize;
return size();
}
// ----------------------------------------------------------------------------
CodeCache::CodeCache(size_t size)
: mCacheSize(size), mCacheInUse(0)
{
pthread_mutex_init(&mLock, 0);
}
CodeCache::~CodeCache()
{
pthread_mutex_destroy(&mLock);
}
sp<Assembly> CodeCache::lookup(const AssemblyKeyBase& keyBase) const
{
pthread_mutex_lock(&mLock);
sp<Assembly> r;
ssize_t index = mCacheData.indexOfKey(key_t(keyBase));
if (index >= 0) {
const cache_entry_t& e = mCacheData.valueAt(index);
e.when = mWhen++;
r = e.entry;
}
pthread_mutex_unlock(&mLock);
return r;
}
int CodeCache::cache( const AssemblyKeyBase& keyBase,
const sp<Assembly>& assembly)
{
pthread_mutex_lock(&mLock);
const ssize_t assemblySize = assembly->size();
while (mCacheInUse + assemblySize > mCacheSize) {
// evict the LRU
size_t lru = 0;
size_t count = mCacheData.size();
for (size_t i=0 ; i<count ; i++) {
const cache_entry_t& e = mCacheData.valueAt(i);
if (e.when < mCacheData.valueAt(lru).when) {
lru = i;
}
}
const cache_entry_t& e = mCacheData.valueAt(lru);
mCacheInUse -= e.entry->size();
mCacheData.removeItemsAt(lru);
}
ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen));
if (err >= 0) {
mCacheInUse += assemblySize;
mWhen++;
// synchronize caches...
char* base = reinterpret_cast<char*>(assembly->base());
char* curr = reinterpret_cast<char*>(base + assembly->size());
__builtin___clear_cache(base, curr);
}
pthread_mutex_unlock(&mLock);
return err;
}
// ----------------------------------------------------------------------------
}; // namespace android

View File

@ -1,136 +0,0 @@
/* libs/pixelflinger/codeflinger/CodeCache.h
**
** Copyright 2006, 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 ANDROID_CODECACHE_H
#define ANDROID_CODECACHE_H
#include <atomic>
#include <stdint.h>
#include <pthread.h>
#include <sys/types.h>
#include "utils/KeyedVector.h"
#include "tinyutils/smartpointer.h"
namespace android {
using namespace tinyutils;
// ----------------------------------------------------------------------------
class AssemblyKeyBase {
public:
virtual ~AssemblyKeyBase() { }
virtual int compare_type(const AssemblyKeyBase& key) const = 0;
};
template <typename T>
class AssemblyKey : public AssemblyKeyBase
{
public:
explicit AssemblyKey(const T& rhs) : mKey(rhs) { }
virtual int compare_type(const AssemblyKeyBase& key) const {
const T& rhs = static_cast<const AssemblyKey&>(key).mKey;
return android::compare_type(mKey, rhs);
}
private:
T mKey;
};
// ----------------------------------------------------------------------------
class Assembly
{
public:
explicit Assembly(size_t size);
virtual ~Assembly();
ssize_t size() const;
uint32_t* base() const;
ssize_t resize(size_t size);
// protocol for sp<>
void incStrong(const void* id) const;
void decStrong(const void* id) const;
typedef void weakref_type;
private:
mutable std::atomic<int32_t> mCount;
uint32_t* mBase;
size_t mSize;
};
// ----------------------------------------------------------------------------
class CodeCache
{
public:
// pretty simple cache API...
explicit CodeCache(size_t size);
~CodeCache();
sp<Assembly> lookup(const AssemblyKeyBase& key) const;
int cache(const AssemblyKeyBase& key,
const sp<Assembly>& assembly);
private:
// nothing to see here...
struct cache_entry_t {
inline cache_entry_t() { }
inline cache_entry_t(const sp<Assembly>& a, int64_t w)
: entry(a), when(w) { }
sp<Assembly> entry;
mutable int64_t when;
};
class key_t {
friend int compare_type(
const key_value_pair_t<key_t, cache_entry_t>&,
const key_value_pair_t<key_t, cache_entry_t>&);
const AssemblyKeyBase* mKey;
public:
key_t() { };
explicit key_t(const AssemblyKeyBase& k) : mKey(&k) { }
};
mutable pthread_mutex_t mLock;
mutable int64_t mWhen;
size_t mCacheSize;
size_t mCacheInUse;
KeyedVector<key_t, cache_entry_t> mCacheData;
friend int compare_type(
const key_value_pair_t<key_t, cache_entry_t>&,
const key_value_pair_t<key_t, cache_entry_t>&);
};
// KeyedVector uses compare_type(), which is more efficient, than
// just using operator < ()
inline int compare_type(
const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& lhs,
const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& rhs)
{
return lhs.key.mKey->compare_type(*(rhs.key.mKey));
}
// ----------------------------------------------------------------------------
}; // namespace android
#endif //ANDROID_CODECACHE_H

File diff suppressed because it is too large Load Diff

View File

@ -1,572 +0,0 @@
/* libs/pixelflinger/codeflinger/GGLAssembler.h
**
** Copyright 2006, 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 ANDROID_GGLASSEMBLER_H
#define ANDROID_GGLASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include <private/pixelflinger/ggl_context.h>
#include "ARMAssemblerProxy.h"
namespace android {
// ----------------------------------------------------------------------------
#define CONTEXT_ADDR_LOAD(REG, FIELD) \
ADDR_LDR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
#define CONTEXT_ADDR_STORE(REG, FIELD) \
ADDR_STR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
#define CONTEXT_LOAD(REG, FIELD) \
LDR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
#define CONTEXT_STORE(REG, FIELD) \
STR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
class RegisterAllocator
{
public:
class RegisterFile;
RegisterAllocator(int arch); // NOLINT, implicit
RegisterFile& registerFile();
int reserveReg(int reg);
int obtainReg();
void recycleReg(int reg);
void reset();
class RegisterFile
{
public:
RegisterFile(int arch); // NOLINT, implicit
RegisterFile(const RegisterFile& rhs, int arch);
~RegisterFile();
void reset();
bool operator == (const RegisterFile& rhs) const;
bool operator != (const RegisterFile& rhs) const {
return !operator == (rhs);
}
int reserve(int reg);
void reserveSeveral(uint32_t regMask);
void recycle(int reg);
void recycleSeveral(uint32_t regMask);
int obtain();
inline int isUsed(int reg) const;
bool hasFreeRegs() const;
int countFreeRegs() const;
uint32_t touched() const;
inline uint32_t status() const { return mStatus; }
enum {
OUT_OF_REGISTERS = 0x1
};
private:
uint32_t mRegs;
uint32_t mTouched;
uint32_t mStatus;
int mArch;
uint32_t mRegisterOffset; // lets reg alloc use 2..17 for mips
// while arm uses 0..15
};
class Scratch
{
public:
explicit Scratch(RegisterFile& regFile)
: mRegFile(regFile), mScratch(0) {
}
~Scratch() {
mRegFile.recycleSeveral(mScratch);
}
int obtain() {
int reg = mRegFile.obtain();
mScratch |= 1<<reg;
return reg;
}
void recycle(int reg) {
mRegFile.recycle(reg);
mScratch &= ~(1<<reg);
}
bool isUsed(int reg) {
return (mScratch & (1<<reg));
}
int countFreeRegs() {
return mRegFile.countFreeRegs();
}
private:
RegisterFile& mRegFile;
uint32_t mScratch;
};
class Spill
{
public:
Spill(RegisterFile& regFile, ARMAssemblerInterface& gen, uint32_t reglist)
: mRegFile(regFile), mGen(gen), mRegList(reglist), mCount(0)
{
if (reglist) {
int count = 0;
while (reglist) {
count++;
reglist &= ~(1 << (31 - __builtin_clz(reglist)));
}
if (count == 1) {
int reg = 31 - __builtin_clz(mRegList);
mGen.STR(mGen.AL, reg, mGen.SP, mGen.immed12_pre(-4, 1));
} else {
mGen.STM(mGen.AL, mGen.DB, mGen.SP, 1, mRegList);
}
mRegFile.recycleSeveral(mRegList);
mCount = count;
}
}
~Spill() {
if (mRegList) {
if (mCount == 1) {
int reg = 31 - __builtin_clz(mRegList);
mGen.LDR(mGen.AL, reg, mGen.SP, mGen.immed12_post(4));
} else {
mGen.LDM(mGen.AL, mGen.IA, mGen.SP, 1, mRegList);
}
mRegFile.reserveSeveral(mRegList);
}
}
private:
RegisterFile& mRegFile;
ARMAssemblerInterface& mGen;
uint32_t mRegList;
int mCount;
};
private:
RegisterFile mRegs;
};
// ----------------------------------------------------------------------------
class GGLAssembler : public ARMAssemblerProxy, public RegisterAllocator
{
public:
explicit GGLAssembler(ARMAssemblerInterface* target);
virtual ~GGLAssembler();
uint32_t* base() const { return 0; } // XXX
uint32_t* pc() const { return 0; } // XXX
void reset(int opt_level);
virtual void prolog();
virtual void epilog(uint32_t touched);
// generate scanline code for given needs
int scanline(const needs_t& needs, context_t const* c);
int scanline_core(const needs_t& needs, context_t const* c);
enum {
CLEAR_LO = 0x0001,
CLEAR_HI = 0x0002,
CORRUPTIBLE = 0x0004,
FIRST = 0x0008
};
enum { //load/store flags
WRITE_BACK = 0x0001
};
struct reg_t {
reg_t() : reg(-1), flags(0) {
}
reg_t(int r, int f=0) // NOLINT, implicit
: reg(r), flags(f) {
}
void setTo(int r, int f=0) {
reg=r; flags=f;
}
int reg;
uint16_t flags;
};
struct integer_t : public reg_t {
integer_t() : reg_t(), s(0) {
}
integer_t(int r, int sz=32, int f=0) // NOLINT, implicit
: reg_t(r, f), s(sz) {
}
void setTo(int r, int sz=32, int f=0) {
reg_t::setTo(r, f); s=sz;
}
int8_t s;
inline int size() const { return s; }
};
struct pixel_t : public reg_t {
pixel_t() : reg_t() {
memset(&format, 0, sizeof(GGLFormat));
}
pixel_t(int r, const GGLFormat* fmt, int f=0)
: reg_t(r, f), format(*fmt) {
}
void setTo(int r, const GGLFormat* fmt, int f=0) {
reg_t::setTo(r, f); format = *fmt;
}
GGLFormat format;
inline int hi(int c) const { return format.c[c].h; }
inline int low(int c) const { return format.c[c].l; }
inline int mask(int c) const { return ((1<<size(c))-1) << low(c); }
inline int size() const { return format.size*8; }
inline int size(int c) const { return component_size(c); }
inline int component_size(int c) const { return hi(c) - low(c); }
};
struct component_t : public reg_t {
component_t() : reg_t(), h(0), l(0) {
}
component_t(int r, int f=0) // NOLINT, implicit
: reg_t(r, f), h(0), l(0) {
}
component_t(int r, int lo, int hi, int f=0)
: reg_t(r, f), h(hi), l(lo) {
}
explicit component_t(const integer_t& rhs)
: reg_t(rhs.reg, rhs.flags), h(rhs.s), l(0) {
}
explicit component_t(const pixel_t& rhs, int component) {
setTo( rhs.reg,
rhs.format.c[component].l,
rhs.format.c[component].h,
rhs.flags|CLEAR_LO|CLEAR_HI);
}
void setTo(int r, int lo=0, int hi=0, int f=0) {
reg_t::setTo(r, f); h=hi; l=lo;
}
int8_t h;
int8_t l;
inline int size() const { return h-l; }
};
struct pointer_t : public reg_t {
pointer_t() : reg_t(), size(0) {
}
pointer_t(int r, int s, int f=0)
: reg_t(r, f), size(s) {
}
void setTo(int r, int s, int f=0) {
reg_t::setTo(r, f); size=s;
}
int8_t size;
};
private:
// GGLAssembler hides RegisterAllocator's and ARMAssemblerProxy's reset
// methods by providing a reset method with a different parameter set. The
// intent of GGLAssembler's reset method is to wrap the inherited reset
// methods, so make these methods private in order to prevent direct calls
// to these methods from clients.
using RegisterAllocator::reset;
using ARMAssemblerProxy::reset;
struct tex_coord_t {
reg_t s;
reg_t t;
pointer_t ptr;
};
struct fragment_parts_t {
uint32_t packed : 1;
uint32_t reload : 2;
uint32_t iterated_packed : 1;
pixel_t iterated;
pointer_t cbPtr;
pointer_t covPtr;
reg_t count;
reg_t argb[4];
reg_t argb_dx[4];
reg_t z;
reg_t dither;
pixel_t texel[GGL_TEXTURE_UNIT_COUNT];
tex_coord_t coords[GGL_TEXTURE_UNIT_COUNT];
};
struct texture_unit_t {
int format_idx;
GGLFormat format;
int bits;
int swrap;
int twrap;
int env;
int pot;
int linear;
uint8_t mask;
uint8_t replaced;
};
struct texture_machine_t {
texture_unit_t tmu[GGL_TEXTURE_UNIT_COUNT];
uint8_t mask;
uint8_t replaced;
uint8_t directTexture;
uint8_t activeUnits;
};
struct component_info_t {
bool masked : 1;
bool inDest : 1;
bool needed : 1;
bool replaced : 1;
bool iterated : 1;
bool smooth : 1;
bool blend : 1;
bool fog : 1;
};
struct builder_context_t {
context_t const* c;
needs_t needs;
int Rctx;
};
template <typename T>
void modify(T& r, Scratch& regs)
{
if (!(r.flags & CORRUPTIBLE)) {
r.reg = regs.obtain();
r.flags |= CORRUPTIBLE;
}
}
// helpers
void base_offset(const pointer_t& d, const pointer_t& b, const reg_t& o);
// texture environement
void modulate( component_t& dest,
const component_t& incoming,
const pixel_t& texel, int component);
void decal( component_t& dest,
const component_t& incoming,
const pixel_t& texel, int component);
void blend( component_t& dest,
const component_t& incoming,
const pixel_t& texel, int component, int tmu);
void add( component_t& dest,
const component_t& incoming,
const pixel_t& texel, int component);
// load/store stuff
void store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0);
void load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0);
void extract(integer_t& d, const pixel_t& s, int component);
void extract(component_t& d, const pixel_t& s, int component);
void extract(integer_t& d, int s, int h, int l, int bits=32);
void expand(integer_t& d, const integer_t& s, int dbits);
void expand(integer_t& d, const component_t& s, int dbits);
void expand(component_t& d, const component_t& s, int dbits);
void downshift(pixel_t& d, int component, component_t s, const reg_t& dither);
void mul_factor( component_t& d,
const integer_t& v,
const integer_t& f);
void mul_factor_add( component_t& d,
const integer_t& v,
const integer_t& f,
const component_t& a);
void component_add( component_t& d,
const integer_t& dst,
const integer_t& src);
void component_sat( const component_t& v);
void build_scanline_prolog( fragment_parts_t& parts,
const needs_t& needs);
void build_smooth_shade(const fragment_parts_t& parts);
void build_component( pixel_t& pixel,
const fragment_parts_t& parts,
int component,
Scratch& global_scratches);
void build_incoming_component(
component_t& temp,
int dst_size,
const fragment_parts_t& parts,
int component,
Scratch& scratches,
Scratch& global_scratches);
void init_iterated_color(fragment_parts_t& parts, const reg_t& x);
void build_iterated_color( component_t& fragment,
const fragment_parts_t& parts,
int component,
Scratch& regs);
void decodeLogicOpNeeds(const needs_t& needs);
void decodeTMUNeeds(const needs_t& needs, context_t const* c);
void init_textures( tex_coord_t* coords,
const reg_t& x,
const reg_t& y);
void build_textures( fragment_parts_t& parts,
Scratch& regs);
void filter8( const fragment_parts_t& parts,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS);
void filter16( const fragment_parts_t& parts,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS);
void filter24( const fragment_parts_t& parts,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS);
void filter32( const fragment_parts_t& parts,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS);
void build_texture_environment( component_t& fragment,
const fragment_parts_t& parts,
int component,
Scratch& regs);
void wrapping( int d,
int coord, int size,
int tx_wrap, int tx_linear);
void build_fog( component_t& temp,
int component,
Scratch& parent_scratches);
void build_blending( component_t& in_out,
const pixel_t& pixel,
int component,
Scratch& parent_scratches);
void build_blend_factor(
integer_t& factor, int f, int component,
const pixel_t& dst_pixel,
integer_t& fragment,
integer_t& fb,
Scratch& scratches);
void build_blendFOneMinusF( component_t& temp,
const integer_t& factor,
const integer_t& fragment,
const integer_t& fb);
void build_blendOneMinusFF( component_t& temp,
const integer_t& factor,
const integer_t& fragment,
const integer_t& fb);
void build_coverage_application(component_t& fragment,
const fragment_parts_t& parts,
Scratch& regs);
void build_alpha_test(component_t& fragment, const fragment_parts_t& parts);
enum { Z_TEST=1, Z_WRITE=2 };
void build_depth_test(const fragment_parts_t& parts, uint32_t mask);
void build_iterate_z(const fragment_parts_t& parts);
void build_iterate_f(const fragment_parts_t& parts);
void build_iterate_texture_coordinates(const fragment_parts_t& parts);
void build_logic_op(pixel_t& pixel, Scratch& regs);
void build_masking(pixel_t& pixel, Scratch& regs);
void build_and_immediate(int d, int s, uint32_t mask, int bits);
bool isAlphaSourceNeeded() const;
enum {
FACTOR_SRC=1, FACTOR_DST=2, BLEND_SRC=4, BLEND_DST=8
};
enum {
LOGIC_OP=1, LOGIC_OP_SRC=2, LOGIC_OP_DST=4
};
static int blending_codes(int fs, int fd);
builder_context_t mBuilderContext;
texture_machine_t mTextureMachine;
component_info_t mInfo[4];
int mBlending;
int mMasking;
int mAllMasked;
int mLogicOp;
int mAlphaTest;
int mAA;
int mDithering;
int mDepthTest;
int mSmooth;
int mFog;
pixel_t mDstPixel;
GGLFormat mCbFormat;
int mBlendFactorCached;
integer_t mAlphaSource;
int mBaseRegister;
int mBlendSrc;
int mBlendDst;
int mBlendSrcA;
int mBlendDstA;
int mOptLevel;
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_GGLASSEMBLER_H

File diff suppressed because it is too large Load Diff

View File

@ -1,404 +0,0 @@
/* libs/pixelflinger/codeflinger/MIPS64Assembler.h
**
** Copyright 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.
*/
#ifndef ANDROID_MIPS64ASSEMBLER_H
#define ANDROID_MIPS64ASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include "utils/KeyedVector.h"
#include "utils/Vector.h"
#include "tinyutils/smartpointer.h"
#include "ARMAssemblerInterface.h"
#include "MIPSAssembler.h"
#include "CodeCache.h"
namespace android {
class MIPS64Assembler; // forward reference
// this class mimics ARMAssembler interface
// intent is to translate each ARM instruction to 1 or more MIPS instr
// implementation calls MIPS64Assembler class to generate mips code
class ArmToMips64Assembler : public ARMAssemblerInterface
{
public:
ArmToMips64Assembler(const sp<Assembly>& assembly,
char *abuf = 0, int linesz = 0, int instr_count = 0);
ArmToMips64Assembler(void* assembly);
virtual ~ArmToMips64Assembler();
uint32_t* base() const;
uint32_t* pc() const;
void disassemble(const char* name);
virtual void reset();
virtual int generate(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// for testing purposes
void fix_branches();
void set_condition(int mode, int R1, int R2);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// shifters...
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
virtual uint32_t* pcForLabel(const char* label);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
// bit manipulation...
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
// Address loading/storing/manipulation
virtual void ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_STR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_ADD(int cc, int s, int Rd, int Rn, uint32_t Op2);
virtual void ADDR_SUB(int cc, int s, int Rd, int Rn, uint32_t Op2);
// this is some crap to share is MIPS64Assembler class for debug
char * mArmDisassemblyBuffer;
int mArmLineLength;
int mArmInstrCount;
int mInum; // current arm instuction number (0..n)
uint32_t** mArmPC; // array: PC for 1st mips instr of
// each translated ARM instr
private:
ArmToMips64Assembler(const ArmToMips64Assembler& rhs);
ArmToMips64Assembler& operator = (const ArmToMips64Assembler& rhs);
void init_conditional_labels(void);
void protectConditionalOperands(int Rd);
// reg__tmp set to MIPS AT, reg 1
int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
sp<Assembly> mAssembly;
MIPS64Assembler* mMips;
enum misc_constants_t {
ARM_MAX_INSTUCTIONS = 512 // based on ASSEMBLY_SCRATCH_SIZE
};
enum {
SRC_REG = 0,
SRC_IMM,
SRC_ERROR = -1
};
enum addr_modes {
// start above the range of legal mips reg #'s (0-31)
AMODE_REG = 0x20,
AMODE_IMM, AMODE_REG_IMM, // for data processing
AMODE_IMM_12_PRE, AMODE_IMM_12_POST, // for load/store
AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
AMODE_IMM_8_POST, AMODE_REG_PRE,
AMODE_UNSUPPORTED
};
struct addr_mode_t { // address modes for current ARM instruction
int reg;
int stype;
uint32_t value;
bool writeback; // writeback the adr reg after modification
} amode;
enum cond_types {
CMP_COND = 1,
SBIT_COND
};
struct cond_mode_t { // conditional-execution info for current ARM instruction
cond_types type;
int r1;
int r2;
int labelnum;
char label[100][10];
} cond;
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// This is the basic MIPS64 assembler, which just creates the opcodes in memory.
// All the more complicated work is done in ArmToMips64Assember above.
// Inherits MIPSAssembler class, and overrides only MIPS64r6 specific stuff
class MIPS64Assembler : public MIPSAssembler
{
public:
MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent);
MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent);
virtual ~MIPS64Assembler();
virtual void reset();
virtual void disassemble(const char* name);
void fix_branches();
// ------------------------------------------------------------------------
// MIPS64AssemblerInterface...
// ------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Arithmetic...
#endif
void DADDU(int Rd, int Rs, int Rt);
void DADDIU(int Rt, int Rs, int16_t imm);
void DSUBU(int Rd, int Rs, int Rt);
void DSUBIU(int Rt, int Rs, int16_t imm);
virtual void MUL(int Rd, int Rs, int Rt);
void MUH(int Rd, int Rs, int Rt);
#if 0
#pragma mark -
#pragma mark Logical...
#endif
virtual void CLO(int Rd, int Rs);
virtual void CLZ(int Rd, int Rs);
#if 0
#pragma mark -
#pragma mark Load/store...
#endif
void LD(int Rt, int Rbase, int16_t offset);
void SD(int Rt, int Rbase, int16_t offset);
virtual void LUI(int Rt, int16_t offset);
#if 0
#pragma mark -
#pragma mark Branch...
#endif
void JR(int Rs);
protected:
ArmToMips64Assembler *mParent;
// opcode field of all instructions
enum opcode_field {
spec_op, regimm_op, j_op, jal_op, // 0x00 - 0x03
beq_op, bne_op, pop06_op, pop07_op, // 0x04 - 0x07
pop10_op, addiu_op, slti_op, sltiu_op, // 0x08 - 0x0b
andi_op, ori_op, xori_op, aui_op, // 0x0c - 0x0f
cop0_op, cop1_op, cop2_op, rsrv_opc_0, // 0x10 - 0x13
rsrv_opc_1, rsrv_opc_2, pop26_op, pop27_op, // 0x14 - 0x17
pop30_op, daddiu_op, rsrv_opc_3, rsrv_opc_4, // 0x18 - 0x1b
rsrv_opc_5, daui_op, msa_op, spec3_op, // 0x1c - 0x1f
lb_op, lh_op, rsrv_opc_6, lw_op, // 0x20 - 0x23
lbu_op, lhu_op, rsrv_opc_7, lwu_op, // 0x24 - 0x27
sb_op, sh_op, rsrv_opc_8, sw_op, // 0x28 - 0x2b
rsrv_opc_9, rsrv_opc_10, rsrv_opc_11, rsrv_opc_12, // 0x2c - 0x2f
rsrv_opc_13, lwc1_op, bc_op, rsrv_opc_14, // 0x2c - 0x2f
rsrv_opc_15, ldc1_op, pop66_op, ld_op, // 0x30 - 0x33
rsrv_opc_16, swc1_op, balc_op, pcrel_op, // 0x34 - 0x37
rsrv_opc_17, sdc1_op, pop76_op, sd_op // 0x38 - 0x3b
};
// func field for special opcode
enum func_spec_op {
sll_fn, rsrv_spec_0, srl_fn, sra_fn,
sllv_fn, lsa_fn, srlv_fn, srav_fn,
rsrv_spec_1, jalr_fn, rsrv_spec_2, rsrv_spec_3,
syscall_fn, break_fn, sdbbp_fn, sync_fn,
clz_fn, clo_fn, dclz_fn, dclo_fn,
dsllv_fn, dlsa_fn, dsrlv_fn, dsrav_fn,
sop30_fn, sop31_fn, sop32_fn, sop33_fn,
sop34_fn, sop35_fn, sop36_fn, sop37_fn,
add_fn, addu_fn, sub_fn, subu_fn,
and_fn, or_fn, xor_fn, nor_fn,
rsrv_spec_4, rsrv_spec_5, slt_fn, sltu_fn,
dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
tge_fn, tgeu_fn, tlt_fn, tltu_fn,
teq_fn, seleqz_fn, tne_fn, selnez_fn,
dsll_fn, rsrv_spec_6, dsrl_fn, dsra_fn,
dsll32_fn, rsrv_spec_7, dsrl32_fn, dsra32_fn
};
// func field for spec3 opcode
enum func_spec3_op {
ext_fn, dextm_fn, dextu_fn, dext_fn,
ins_fn, dinsm_fn, dinsu_fn, dins_fn,
cachee_fn = 0x1b, sbe_fn, she_fn, sce_fn, swe_fn,
bshfl_fn, prefe_fn = 0x23, dbshfl_fn, cache_fn, sc_fn, scd_fn,
lbue_fn, lhue_fn, lbe_fn = 0x2c, lhe_fn, lle_fn, lwe_fn,
pref_fn = 0x35, ll_fn, lld_fn, rdhwr_fn = 0x3b
};
// sa field for spec3 opcodes, with BSHFL function
enum func_spec3_bshfl {
bitswap_fn,
wsbh_fn = 0x02,
dshd_fn = 0x05,
seb_fn = 0x10,
seh_fn = 0x18
};
// rt field of regimm opcodes.
enum regimm_fn {
bltz_fn, bgez_fn,
dahi_fn = 0x6,
nal_fn = 0x10, bal_fn, bltzall_fn, bgezall_fn,
sigrie_fn = 0x17,
dati_fn = 0x1e, synci_fn
};
enum muldiv_fn {
mul_fn = 0x02, muh_fn
};
enum mips_inst_shifts {
OP_SHF = 26,
JTARGET_SHF = 0,
RS_SHF = 21,
RT_SHF = 16,
RD_SHF = 11,
RE_SHF = 6,
SA_SHF = RE_SHF, // synonym
IMM_SHF = 0,
FUNC_SHF = 0,
// mask values
MSK_16 = 0xffff,
CACHEOP_SHF = 18,
CACHESEL_SHF = 16,
};
};
}; // namespace android
#endif //ANDROID_MIPS64ASSEMBLER_H

File diff suppressed because it is too large Load Diff

View File

@ -1,557 +0,0 @@
/* libs/pixelflinger/codeflinger/MIPSAssembler.h
**
** Copyright 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 ANDROID_MIPSASSEMBLER_H
#define ANDROID_MIPSASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include "tinyutils/smartpointer.h"
#include "utils/KeyedVector.h"
#include "utils/Vector.h"
#include "ARMAssemblerInterface.h"
#include "CodeCache.h"
namespace android {
class MIPSAssembler; // forward reference
// this class mimics ARMAssembler interface
// intent is to translate each ARM instruction to 1 or more MIPS instr
// implementation calls MIPSAssembler class to generate mips code
class ArmToMipsAssembler : public ARMAssemblerInterface
{
public:
ArmToMipsAssembler(const sp<Assembly>& assembly,
char *abuf = 0, int linesz = 0, int instr_count = 0);
virtual ~ArmToMipsAssembler();
uint32_t* base() const;
uint32_t* pc() const;
void disassemble(const char* name);
virtual void reset();
virtual int generate(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// shifters...
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
virtual uint32_t* pcForLabel(const char* label);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
// bit manipulation...
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
// this is some crap to share is MIPSAssembler class for debug
char * mArmDisassemblyBuffer;
int mArmLineLength;
int mArmInstrCount;
int mInum; // current arm instuction number (0..n)
uint32_t** mArmPC; // array: PC for 1st mips instr of
// each translated ARM instr
private:
ArmToMipsAssembler(const ArmToMipsAssembler& rhs);
ArmToMipsAssembler& operator = (const ArmToMipsAssembler& rhs);
void init_conditional_labels(void);
void protectConditionalOperands(int Rd);
// reg__tmp set to MIPS AT, reg 1
int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
sp<Assembly> mAssembly;
MIPSAssembler* mMips;
enum misc_constants_t {
ARM_MAX_INSTUCTIONS = 512 // based on ASSEMBLY_SCRATCH_SIZE
};
enum {
SRC_REG = 0,
SRC_IMM,
SRC_ERROR = -1
};
enum addr_modes {
// start above the range of legal mips reg #'s (0-31)
AMODE_REG = 0x20,
AMODE_IMM, AMODE_REG_IMM, // for data processing
AMODE_IMM_12_PRE, AMODE_IMM_12_POST, // for load/store
AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
AMODE_IMM_8_POST, AMODE_REG_PRE,
AMODE_UNSUPPORTED
};
struct addr_mode_t { // address modes for current ARM instruction
int reg;
int stype;
uint32_t value;
bool writeback; // writeback the adr reg after modification
} amode;
enum cond_types {
CMP_COND = 1,
SBIT_COND
};
struct cond_mode_t { // conditional-execution info for current ARM instruction
cond_types type;
int r1;
int r2;
int labelnum;
char label[100][10];
} cond;
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// This is the basic MIPS assembler, which just creates the opcodes in memory.
// All the more complicated work is done in ArmToMipsAssember above.
class MIPSAssembler
{
public:
MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent);
MIPSAssembler(void* assembly);
virtual ~MIPSAssembler();
virtual uint32_t* base() const;
virtual uint32_t* pc() const;
virtual void reset();
virtual void disassemble(const char* name);
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual int generate(const char* name);
virtual void comment(const char* string);
virtual void label(const char* string);
// valid only after generate() has been called
virtual uint32_t* pcForLabel(const char* label);
// ------------------------------------------------------------------------
// MIPSAssemblerInterface...
// ------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Arithmetic...
#endif
void ADDU(int Rd, int Rs, int Rt);
void ADDIU(int Rt, int Rs, int16_t imm);
void SUBU(int Rd, int Rs, int Rt);
void SUBIU(int Rt, int Rs, int16_t imm);
void NEGU(int Rd, int Rs);
void MUL(int Rd, int Rs, int Rt);
void MULT(int Rs, int Rt); // dest is hi,lo
void MULTU(int Rs, int Rt); // dest is hi,lo
void MADD(int Rs, int Rt); // hi,lo = hi,lo + Rs * Rt
void MADDU(int Rs, int Rt); // hi,lo = hi,lo + Rs * Rt
void MSUB(int Rs, int Rt); // hi,lo = hi,lo - Rs * Rt
void MSUBU(int Rs, int Rt); // hi,lo = hi,lo - Rs * Rt
void SEB(int Rd, int Rt); // sign-extend byte (mips32r2)
void SEH(int Rd, int Rt); // sign-extend half-word (mips32r2)
#if 0
#pragma mark -
#pragma mark Comparisons...
#endif
void SLT(int Rd, int Rs, int Rt);
void SLTI(int Rt, int Rs, int16_t imm);
void SLTU(int Rd, int Rs, int Rt);
void SLTIU(int Rt, int Rs, int16_t imm);
#if 0
#pragma mark -
#pragma mark Logical...
#endif
void AND(int Rd, int Rs, int Rt);
void ANDI(int Rd, int Rs, uint16_t imm);
void OR(int Rd, int Rs, int Rt);
void ORI(int Rt, int Rs, uint16_t imm);
void NOR(int Rd, int Rs, int Rt);
void NOT(int Rd, int Rs);
void XOR(int Rd, int Rs, int Rt);
void XORI(int Rt, int Rs, uint16_t imm);
void SLL(int Rd, int Rt, int shft);
void SLLV(int Rd, int Rt, int Rs);
void SRL(int Rd, int Rt, int shft);
void SRLV(int Rd, int Rt, int Rs);
void SRA(int Rd, int Rt, int shft);
void SRAV(int Rd, int Rt, int Rs);
void ROTR(int Rd, int Rt, int shft); // mips32r2
void ROTRV(int Rd, int Rt, int Rs); // mips32r2
void RORsyn(int Rd, int Rs, int Rt); // synthetic: d = s rotated by t
void RORIsyn(int Rd, int Rt, int rot); // synthetic: d = s rotated by immed
void CLO(int Rd, int Rs);
void CLZ(int Rd, int Rs);
void WSBH(int Rd, int Rt);
#if 0
#pragma mark -
#pragma mark Load/store...
#endif
void LW(int Rt, int Rbase, int16_t offset);
void SW(int Rt, int Rbase, int16_t offset);
void LB(int Rt, int Rbase, int16_t offset);
void LBU(int Rt, int Rbase, int16_t offset);
void SB(int Rt, int Rbase, int16_t offset);
void LH(int Rt, int Rbase, int16_t offset);
void LHU(int Rt, int Rbase, int16_t offset);
void SH(int Rt, int Rbase, int16_t offset);
void LUI(int Rt, int16_t offset);
#if 0
#pragma mark -
#pragma mark Register moves...
#endif
void MOVE(int Rd, int Rs);
void MOVN(int Rd, int Rs, int Rt);
void MOVZ(int Rd, int Rs, int Rt);
void MFHI(int Rd);
void MFLO(int Rd);
void MTHI(int Rs);
void MTLO(int Rs);
#if 0
#pragma mark -
#pragma mark Branch...
#endif
void B(const char* label);
void BEQ(int Rs, int Rt, const char* label);
void BNE(int Rs, int Rt, const char* label);
void BGEZ(int Rs, const char* label);
void BGTZ(int Rs, const char* label);
void BLEZ(int Rs, const char* label);
void BLTZ(int Rs, const char* label);
void JR(int Rs);
#if 0
#pragma mark -
#pragma mark Synthesized Branch...
#endif
// synthetic variants of above (using slt & friends)
void BEQZ(int Rs, const char* label);
void BNEZ(int Rs, const char* label);
void BGE(int Rs, int Rt, const char* label);
void BGEU(int Rs, int Rt, const char* label);
void BGT(int Rs, int Rt, const char* label);
void BGTU(int Rs, int Rt, const char* label);
void BLE(int Rs, int Rt, const char* label);
void BLEU(int Rs, int Rt, const char* label);
void BLT(int Rs, int Rt, const char* label);
void BLTU(int Rs, int Rt, const char* label);
#if 0
#pragma mark -
#pragma mark Misc...
#endif
void NOP(void);
void NOP2(void);
void UNIMPL(void);
protected:
virtual void string_detab(char *s);
virtual void string_pad(char *s, int padded_len);
ArmToMipsAssembler *mParent;
sp<Assembly> mAssembly;
uint32_t* mBase;
uint32_t* mPC;
uint32_t* mPrologPC;
int64_t mDuration;
struct branch_target_t {
inline branch_target_t() : label(0), pc(0) { }
inline branch_target_t(const char* l, uint32_t* p)
: label(l), pc(p) { }
const char* label;
uint32_t* pc;
};
Vector<branch_target_t> mBranchTargets;
KeyedVector< const char*, uint32_t* > mLabels;
KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
KeyedVector< uint32_t*, const char* > mComments;
// opcode field of all instructions
enum opcode_field {
spec_op, regimm_op, j_op, jal_op, // 00
beq_op, bne_op, blez_op, bgtz_op,
addi_op, addiu_op, slti_op, sltiu_op, // 08
andi_op, ori_op, xori_op, lui_op,
cop0_op, cop1_op, cop2_op, cop1x_op, // 10
beql_op, bnel_op, blezl_op, bgtzl_op,
daddi_op, daddiu_op, ldl_op, ldr_op, // 18
spec2_op, jalx_op, mdmx_op, spec3_op,
lb_op, lh_op, lwl_op, lw_op, // 20
lbu_op, lhu_op, lwr_op, lwu_op,
sb_op, sh_op, swl_op, sw_op, // 28
sdl_op, sdr_op, swr_op, cache_op,
ll_op, lwc1_op, lwc2_op, pref_op, // 30
lld_op, ldc1_op, ldc2_op, ld_op,
sc_op, swc1_op, swc2_op, rsrv_3b_op, // 38
scd_op, sdc1_op, sdc2_op, sd_op
};
// func field for special opcode
enum func_spec_op {
sll_fn, movc_fn, srl_fn, sra_fn, // 00
sllv_fn, pmon_fn, srlv_fn, srav_fn,
jr_fn, jalr_fn, movz_fn, movn_fn, // 08
syscall_fn, break_fn, spim_fn, sync_fn,
mfhi_fn, mthi_fn, mflo_fn, mtlo_fn, // 10
dsllv_fn, rsrv_spec_2, dsrlv_fn, dsrav_fn,
mult_fn, multu_fn, div_fn, divu_fn, // 18
dmult_fn, dmultu_fn, ddiv_fn, ddivu_fn,
add_fn, addu_fn, sub_fn, subu_fn, // 20
and_fn, or_fn, xor_fn, nor_fn,
rsrv_spec_3, rsrv_spec_4, slt_fn, sltu_fn, // 28
dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
tge_fn, tgeu_fn, tlt_fn, tltu_fn, // 30
teq_fn, rsrv_spec_5, tne_fn, rsrv_spec_6,
dsll_fn, rsrv_spec_7, dsrl_fn, dsra_fn, // 38
dsll32_fn, rsrv_spec_8, dsrl32_fn, dsra32_fn
};
// func field for spec2 opcode
enum func_spec2_op {
madd_fn, maddu_fn, mul_fn, rsrv_spec2_3,
msub_fn, msubu_fn,
clz_fn = 0x20, clo_fn,
dclz_fn = 0x24, dclo_fn,
sdbbp_fn = 0x3f
};
// func field for spec3 opcode
enum func_spec3_op {
ext_fn, dextm_fn, dextu_fn, dext_fn,
ins_fn, dinsm_fn, dinsu_fn, dins_fn,
bshfl_fn = 0x20,
dbshfl_fn = 0x24,
rdhwr_fn = 0x3b
};
// sa field for spec3 opcodes, with BSHFL function
enum func_spec3_bshfl {
wsbh_fn = 0x02,
seb_fn = 0x10,
seh_fn = 0x18
};
// rt field of regimm opcodes.
enum regimm_fn {
bltz_fn, bgez_fn, bltzl_fn, bgezl_fn,
rsrv_ri_fn4, rsrv_ri_fn5, rsrv_ri_fn6, rsrv_ri_fn7,
tgei_fn, tgeiu_fn, tlti_fn, tltiu_fn,
teqi_fn, rsrv_ri_fn_0d, tnei_fn, rsrv_ri_fn0f,
bltzal_fn, bgezal_fn, bltzall_fn, bgezall_fn,
bposge32_fn= 0x1c,
synci_fn = 0x1f
};
// func field for mad opcodes (MIPS IV).
enum mad_func {
madd_fp_op = 0x08, msub_fp_op = 0x0a,
nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e
};
enum mips_inst_shifts {
OP_SHF = 26,
JTARGET_SHF = 0,
RS_SHF = 21,
RT_SHF = 16,
RD_SHF = 11,
RE_SHF = 6,
SA_SHF = RE_SHF, // synonym
IMM_SHF = 0,
FUNC_SHF = 0,
// mask values
MSK_16 = 0xffff,
CACHEOP_SHF = 18,
CACHESEL_SHF = 16,
};
};
enum mips_regnames {
R_zero = 0,
R_at, R_v0, R_v1, R_a0, R_a1, R_a2, R_a3,
#if __mips_isa_rev < 6
R_t0, R_t1, R_t2, R_t3, R_t4, R_t5, R_t6, R_t7,
#else
R_a4, R_a5, R_a6, R_a7, R_t0, R_t1, R_t2, R_t3,
#endif
R_s0, R_s1, R_s2, R_s3, R_s4, R_s5, R_s6, R_s7,
R_t8, R_t9, R_k0, R_k1, R_gp, R_sp, R_s8, R_ra,
R_lr = R_s8,
// arm regs 0-15 are mips regs 2-17 (meaning s0 & s1 are used)
R_at2 = R_s2, // R_at2 = 18 = s2
R_cmp = R_s3, // R_cmp = 19 = s3
R_cmp2 = R_s4 // R_cmp2 = 20 = s4
};
}; // namespace android
#endif //ANDROID_MIPSASSEMBLER_H

View File

@ -1,300 +0,0 @@
/* $NetBSD: armreg.h,v 1.28 2003/10/31 16:30:15 scw Exp $ */
/*-
* Copyright (c) 1998, 2001 Ben Harris
* Copyright (c) 1994-1996 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* 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 Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI 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.
*
* $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/armreg.h,v 1.3 2005/11/21 19:06:25 cognet Exp $
*/
#ifndef MACHINE_ARMREG_H
#define MACHINE_ARMREG_H
#define INSN_SIZE 4
#define INSN_COND_MASK 0xf0000000 /* Condition mask */
#define PSR_MODE 0x0000001f /* mode mask */
#define PSR_USR26_MODE 0x00000000
#define PSR_FIQ26_MODE 0x00000001
#define PSR_IRQ26_MODE 0x00000002
#define PSR_SVC26_MODE 0x00000003
#define PSR_USR32_MODE 0x00000010
#define PSR_FIQ32_MODE 0x00000011
#define PSR_IRQ32_MODE 0x00000012
#define PSR_SVC32_MODE 0x00000013
#define PSR_ABT32_MODE 0x00000017
#define PSR_UND32_MODE 0x0000001b
#define PSR_SYS32_MODE 0x0000001f
#define PSR_32_MODE 0x00000010
#define PSR_FLAGS 0xf0000000 /* flags */
#define PSR_C_bit (1 << 29) /* carry */
/* The high-order byte is always the implementor */
#define CPU_ID_IMPLEMENTOR_MASK 0xff000000
#define CPU_ID_ARM_LTD 0x41000000 /* 'A' */
#define CPU_ID_DEC 0x44000000 /* 'D' */
#define CPU_ID_INTEL 0x69000000 /* 'i' */
#define CPU_ID_TI 0x54000000 /* 'T' */
/* How to decide what format the CPUID is in. */
#define CPU_ID_ISOLD(x) (((x) & 0x0000f000) == 0x00000000)
#define CPU_ID_IS7(x) (((x) & 0x0000f000) == 0x00007000)
#define CPU_ID_ISNEW(x) (!CPU_ID_ISOLD(x) && !CPU_ID_IS7(x))
/* On ARM3 and ARM6, this byte holds the foundry ID. */
#define CPU_ID_FOUNDRY_MASK 0x00ff0000
#define CPU_ID_FOUNDRY_VLSI 0x00560000
/* On ARM7 it holds the architecture and variant (sub-model) */
#define CPU_ID_7ARCH_MASK 0x00800000
#define CPU_ID_7ARCH_V3 0x00000000
#define CPU_ID_7ARCH_V4T 0x00800000
#define CPU_ID_7VARIANT_MASK 0x007f0000
/* On more recent ARMs, it does the same, but in a different format */
#define CPU_ID_ARCH_MASK 0x000f0000
#define CPU_ID_ARCH_V3 0x00000000
#define CPU_ID_ARCH_V4 0x00010000
#define CPU_ID_ARCH_V4T 0x00020000
#define CPU_ID_ARCH_V5 0x00030000
#define CPU_ID_ARCH_V5T 0x00040000
#define CPU_ID_ARCH_V5TE 0x00050000
#define CPU_ID_VARIANT_MASK 0x00f00000
/* Next three nybbles are part number */
#define CPU_ID_PARTNO_MASK 0x0000fff0
/* Intel XScale has sub fields in part number */
#define CPU_ID_XSCALE_COREGEN_MASK 0x0000e000 /* core generation */
#define CPU_ID_XSCALE_COREREV_MASK 0x00001c00 /* core revision */
#define CPU_ID_XSCALE_PRODUCT_MASK 0x000003f0 /* product number */
/* And finally, the revision number. */
#define CPU_ID_REVISION_MASK 0x0000000f
/* Individual CPUs are probably best IDed by everything but the revision. */
#define CPU_ID_CPU_MASK 0xfffffff0
/* Fake CPU IDs for ARMs without CP15 */
#define CPU_ID_ARM2 0x41560200
#define CPU_ID_ARM250 0x41560250
/* Pre-ARM7 CPUs -- [15:12] == 0 */
#define CPU_ID_ARM3 0x41560300
#define CPU_ID_ARM600 0x41560600
#define CPU_ID_ARM610 0x41560610
#define CPU_ID_ARM620 0x41560620
/* ARM7 CPUs -- [15:12] == 7 */
#define CPU_ID_ARM700 0x41007000 /* XXX This is a guess. */
#define CPU_ID_ARM710 0x41007100
#define CPU_ID_ARM7500 0x41027100 /* XXX This is a guess. */
#define CPU_ID_ARM710A 0x41047100 /* inc ARM7100 */
#define CPU_ID_ARM7500FE 0x41077100
#define CPU_ID_ARM710T 0x41807100
#define CPU_ID_ARM720T 0x41807200
#define CPU_ID_ARM740T8K 0x41807400 /* XXX no MMU, 8KB cache */
#define CPU_ID_ARM740T4K 0x41817400 /* XXX no MMU, 4KB cache */
/* Post-ARM7 CPUs */
#define CPU_ID_ARM810 0x41018100
#define CPU_ID_ARM920T 0x41129200
#define CPU_ID_ARM920T_ALT 0x41009200
#define CPU_ID_ARM922T 0x41029220
#define CPU_ID_ARM940T 0x41029400 /* XXX no MMU */
#define CPU_ID_ARM946ES 0x41049460 /* XXX no MMU */
#define CPU_ID_ARM966ES 0x41049660 /* XXX no MMU */
#define CPU_ID_ARM966ESR1 0x41059660 /* XXX no MMU */
#define CPU_ID_ARM1020E 0x4115a200 /* (AKA arm10 rev 1) */
#define CPU_ID_ARM1022ES 0x4105a220
#define CPU_ID_SA110 0x4401a100
#define CPU_ID_SA1100 0x4401a110
#define CPU_ID_TI925T 0x54029250
#define CPU_ID_SA1110 0x6901b110
#define CPU_ID_IXP1200 0x6901c120
#define CPU_ID_80200 0x69052000
#define CPU_ID_PXA250 0x69052100 /* sans core revision */
#define CPU_ID_PXA210 0x69052120
#define CPU_ID_PXA250A 0x69052100 /* 1st version Core */
#define CPU_ID_PXA210A 0x69052120 /* 1st version Core */
#define CPU_ID_PXA250B 0x69052900 /* 3rd version Core */
#define CPU_ID_PXA210B 0x69052920 /* 3rd version Core */
#define CPU_ID_PXA250C 0x69052d00 /* 4th version Core */
#define CPU_ID_PXA210C 0x69052d20 /* 4th version Core */
#define CPU_ID_80321_400 0x69052420
#define CPU_ID_80321_600 0x69052430
#define CPU_ID_80321_400_B0 0x69052c20
#define CPU_ID_80321_600_B0 0x69052c30
#define CPU_ID_IXP425_533 0x690541c0
#define CPU_ID_IXP425_400 0x690541d0
#define CPU_ID_IXP425_266 0x690541f0
/* ARM3-specific coprocessor 15 registers */
#define ARM3_CP15_FLUSH 1
#define ARM3_CP15_CONTROL 2
#define ARM3_CP15_CACHEABLE 3
#define ARM3_CP15_UPDATEABLE 4
#define ARM3_CP15_DISRUPTIVE 5
/* ARM3 Control register bits */
#define ARM3_CTL_CACHE_ON 0x00000001
#define ARM3_CTL_SHARED 0x00000002
#define ARM3_CTL_MONITOR 0x00000004
/*
* Post-ARM3 CP15 registers:
*
* 1 Control register
*
* 2 Translation Table Base
*
* 3 Domain Access Control
*
* 4 Reserved
*
* 5 Fault Status
*
* 6 Fault Address
*
* 7 Cache/write-buffer Control
*
* 8 TLB Control
*
* 9 Cache Lockdown
*
* 10 TLB Lockdown
*
* 11 Reserved
*
* 12 Reserved
*
* 13 Process ID (for FCSE)
*
* 14 Reserved
*
* 15 Implementation Dependent
*/
/* Some of the definitions below need cleaning up for V3/V4 architectures */
/* CPU control register (CP15 register 1) */
#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */
#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */
#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */
#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */
#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */
#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */
#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */
#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */
#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */
#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */
#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */
#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */
#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */
#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */
#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */
#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */
#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */
#define XSCALE_AUXCTL_K 0x00000001 /* dis. write buffer coalescing */
#define XSCALE_AUXCTL_P 0x00000002 /* ECC protect page table access */
#define XSCALE_AUXCTL_MD_WB_RA 0x00000000 /* mini-D$ wb, read-allocate */
#define XSCALE_AUXCTL_MD_WB_RWA 0x00000010 /* mini-D$ wb, read/write-allocate */
#define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */
#define XSCALE_AUXCTL_MD_MASK 0x00000030
/* Cache type register definitions */
#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */
#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */
#define CPU_CT_S (1U << 24) /* split cache */
#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */
#define CPU_CT_CTYPE_WT 0 /* write-through */
#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */
#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */
#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */
#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */
#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */
#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */
#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */
#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */
/* Fault status register definitions */
#define FAULT_TYPE_MASK 0x0f
#define FAULT_USER 0x10
#define FAULT_WRTBUF_0 0x00 /* Vector Exception */
#define FAULT_WRTBUF_1 0x02 /* Terminal Exception */
#define FAULT_BUSERR_0 0x04 /* External Abort on Linefetch -- Section */
#define FAULT_BUSERR_1 0x06 /* External Abort on Linefetch -- Page */
#define FAULT_BUSERR_2 0x08 /* External Abort on Non-linefetch -- Section */
#define FAULT_BUSERR_3 0x0a /* External Abort on Non-linefetch -- Page */
#define FAULT_BUSTRNL1 0x0c /* External abort on Translation -- Level 1 */
#define FAULT_BUSTRNL2 0x0e /* External abort on Translation -- Level 2 */
#define FAULT_ALIGN_0 0x01 /* Alignment */
#define FAULT_ALIGN_1 0x03 /* Alignment */
#define FAULT_TRANS_S 0x05 /* Translation -- Section */
#define FAULT_TRANS_P 0x07 /* Translation -- Page */
#define FAULT_DOMAIN_S 0x09 /* Domain -- Section */
#define FAULT_DOMAIN_P 0x0b /* Domain -- Page */
#define FAULT_PERM_S 0x0d /* Permission -- Section */
#define FAULT_PERM_P 0x0f /* Permission -- Page */
#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */
/*
* Address of the vector page, low and high versions.
*/
#define ARM_VECTORS_LOW 0x00000000U
#define ARM_VECTORS_HIGH 0xffff0000U
/*
* ARM Instructions
*
* 3 3 2 2 2
* 1 0 9 8 7 0
* +-------+-------------------------------------------------------+
* | cond | instruction dependant |
* |c c c c| |
* +-------+-------------------------------------------------------+
*/
#define INSN_SIZE 4 /* Always 4 bytes */
#define INSN_COND_MASK 0xf0000000 /* Condition mask */
#define INSN_COND_AL 0xe0000000 /* Always condition */
#endif /* !MACHINE_ARMREG_H */

View File

@ -1,674 +0,0 @@
/* libs/pixelflinger/codeflinger/blending.cpp
**
** Copyright 2006, 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.
*/
#define LOG_TAG "pixelflinger-code"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <android-base/macros.h>
#include <log/log.h>
#include "GGLAssembler.h"
namespace android {
void GGLAssembler::build_fog(
component_t& temp, // incomming fragment / output
int component,
Scratch& regs)
{
if (mInfo[component].fog) {
Scratch scratches(registerFile());
comment("fog");
integer_t fragment(temp.reg, temp.h, temp.flags);
if (!(temp.flags & CORRUPTIBLE)) {
temp.reg = regs.obtain();
temp.flags |= CORRUPTIBLE;
}
integer_t fogColor(scratches.obtain(), 8, CORRUPTIBLE);
LDRB(AL, fogColor.reg, mBuilderContext.Rctx,
immed12_pre(GGL_OFFSETOF(state.fog.color[component])));
integer_t factor(scratches.obtain(), 16, CORRUPTIBLE);
CONTEXT_LOAD(factor.reg, generated_vars.f);
// clamp fog factor (TODO: see if there is a way to guarantee
// we won't overflow, when setting the iterators)
BIC(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, ASR, 31));
CMP(AL, factor.reg, imm( 0x10000 ));
MOV(HS, 0, factor.reg, imm( 0x10000 ));
build_blendFOneMinusF(temp, factor, fragment, fogColor);
}
}
void GGLAssembler::build_blending(
component_t& temp, // incomming fragment / output
const pixel_t& pixel, // framebuffer
int component,
Scratch& regs)
{
if (!mInfo[component].blend)
return;
int fs = component==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc;
int fd = component==GGLFormat::ALPHA ? mBlendDstA : mBlendDst;
if (fs==GGL_SRC_ALPHA_SATURATE && component==GGLFormat::ALPHA)
fs = GGL_ONE;
const int blending = blending_codes(fs, fd);
if (!temp.size()) {
// here, blending will produce something which doesn't depend on
// that component (eg: GL_ZERO:GL_*), so the register has not been
// allocated yet. Will never be used as a source.
temp = component_t(regs.obtain(), CORRUPTIBLE);
}
// we are doing real blending...
// fb: extracted dst
// fragment: extracted src
// temp: component_t(fragment) and result
// scoped register allocator
Scratch scratches(registerFile());
comment("blending");
// we can optimize these cases a bit...
// (1) saturation is not needed
// (2) we can use only one multiply instead of 2
// (3) we can reduce the register pressure
// R = S*f + D*(1-f) = (S-D)*f + D
// R = S*(1-f) + D*f = (D-S)*f + S
const bool same_factor_opt1 =
(fs==GGL_DST_COLOR && fd==GGL_ONE_MINUS_DST_COLOR) ||
(fs==GGL_SRC_COLOR && fd==GGL_ONE_MINUS_SRC_COLOR) ||
(fs==GGL_DST_ALPHA && fd==GGL_ONE_MINUS_DST_ALPHA) ||
(fs==GGL_SRC_ALPHA && fd==GGL_ONE_MINUS_SRC_ALPHA);
const bool same_factor_opt2 =
(fs==GGL_ONE_MINUS_DST_COLOR && fd==GGL_DST_COLOR) ||
(fs==GGL_ONE_MINUS_SRC_COLOR && fd==GGL_SRC_COLOR) ||
(fs==GGL_ONE_MINUS_DST_ALPHA && fd==GGL_DST_ALPHA) ||
(fs==GGL_ONE_MINUS_SRC_ALPHA && fd==GGL_SRC_ALPHA);
// XXX: we could also optimize these cases:
// R = S*f + D*f = (S+D)*f
// R = S*(1-f) + D*(1-f) = (S+D)*(1-f)
// R = S*D + D*S = 2*S*D
// see if we need to extract 'component' from the destination (fb)
integer_t fb;
if (blending & (BLEND_DST|FACTOR_DST)) {
fb.setTo(scratches.obtain(), 32);
extract(fb, pixel, component);
if (mDithering) {
// XXX: maybe what we should do instead, is simply
// expand fb -or- fragment to the larger of the two
if (fb.size() < temp.size()) {
// for now we expand 'fb' to min(fragment, 8)
int new_size = temp.size() < 8 ? temp.size() : 8;
expand(fb, fb, new_size);
}
}
}
// convert input fragment to integer_t
if (temp.l && (temp.flags & CORRUPTIBLE)) {
MOV(AL, 0, temp.reg, reg_imm(temp.reg, LSR, temp.l));
temp.h -= temp.l;
temp.l = 0;
}
integer_t fragment(temp.reg, temp.size(), temp.flags);
// if not done yet, convert input fragment to integer_t
if (temp.l) {
// here we know temp is not CORRUPTIBLE
fragment.reg = scratches.obtain();
MOV(AL, 0, fragment.reg, reg_imm(temp.reg, LSR, temp.l));
fragment.flags |= CORRUPTIBLE;
}
if (!(temp.flags & CORRUPTIBLE)) {
// temp is not corruptible, but since it's the destination it
// will be modified, so we need to allocate a new register.
temp.reg = regs.obtain();
temp.flags &= ~CORRUPTIBLE;
fragment.flags &= ~CORRUPTIBLE;
}
if ((blending & BLEND_SRC) && !same_factor_opt1) {
// source (fragment) is needed for the blending stage
// so it's not CORRUPTIBLE (unless we're doing same_factor_opt1)
fragment.flags &= ~CORRUPTIBLE;
}
if (same_factor_opt1) {
// R = S*f + D*(1-f) = (S-D)*f + D
integer_t factor;
build_blend_factor(factor, fs,
component, pixel, fragment, fb, scratches);
// fb is always corruptible from this point
fb.flags |= CORRUPTIBLE;
build_blendFOneMinusF(temp, factor, fragment, fb);
} else if (same_factor_opt2) {
// R = S*(1-f) + D*f = (D-S)*f + S
integer_t factor;
// fb is always corrruptible here
fb.flags |= CORRUPTIBLE;
build_blend_factor(factor, fd,
component, pixel, fragment, fb, scratches);
build_blendOneMinusFF(temp, factor, fragment, fb);
} else {
integer_t src_factor;
integer_t dst_factor;
// if destination (fb) is not needed for the blending stage,
// then it can be marked as CORRUPTIBLE
if (!(blending & BLEND_DST)) {
fb.flags |= CORRUPTIBLE;
}
// XXX: try to mark some registers as CORRUPTIBLE
// in most case we could make those corruptible
// when we're processing the last component
// but not always, for instance
// when fragment is constant and not reloaded
// when fb is needed for logic-ops or masking
// when a register is aliased (for instance with mAlphaSource)
// blend away...
if (fs==GGL_ZERO) {
if (fd==GGL_ZERO) { // R = 0
// already taken care of
} else if (fd==GGL_ONE) { // R = D
// already taken care of
} else { // R = D*fd
// compute fd
build_blend_factor(dst_factor, fd,
component, pixel, fragment, fb, scratches);
mul_factor(temp, fb, dst_factor);
}
} else if (fs==GGL_ONE) {
if (fd==GGL_ZERO) { // R = S
// NOP, taken care of
} else if (fd==GGL_ONE) { // R = S + D
component_add(temp, fb, fragment); // args order matters
component_sat(temp);
} else { // R = S + D*fd
// compute fd
build_blend_factor(dst_factor, fd,
component, pixel, fragment, fb, scratches);
mul_factor_add(temp, fb, dst_factor, component_t(fragment));
component_sat(temp);
}
} else {
// compute fs
build_blend_factor(src_factor, fs,
component, pixel, fragment, fb, scratches);
if (fd==GGL_ZERO) { // R = S*fs
mul_factor(temp, fragment, src_factor);
} else if (fd==GGL_ONE) { // R = S*fs + D
mul_factor_add(temp, fragment, src_factor, component_t(fb));
component_sat(temp);
} else { // R = S*fs + D*fd
mul_factor(temp, fragment, src_factor);
if (scratches.isUsed(src_factor.reg))
scratches.recycle(src_factor.reg);
// compute fd
build_blend_factor(dst_factor, fd,
component, pixel, fragment, fb, scratches);
mul_factor_add(temp, fb, dst_factor, temp);
if (!same_factor_opt1 && !same_factor_opt2) {
component_sat(temp);
}
}
}
}
// now we can be corrupted (it's the dest)
temp.flags |= CORRUPTIBLE;
}
void GGLAssembler::build_blend_factor(
integer_t& factor, int f, int component,
const pixel_t& dst_pixel,
integer_t& fragment,
integer_t& fb,
Scratch& scratches)
{
integer_t src_alpha(fragment);
// src_factor/dst_factor won't be used after blending,
// so it's fine to mark them as CORRUPTIBLE (if not aliased)
factor.flags |= CORRUPTIBLE;
switch(f) {
case GGL_ONE_MINUS_SRC_ALPHA:
case GGL_SRC_ALPHA:
if (component==GGLFormat::ALPHA && !isAlphaSourceNeeded()) {
// we're processing alpha, so we already have
// src-alpha in fragment, and we need src-alpha just this time.
} else {
// alpha-src will be needed for other components
if (!mBlendFactorCached || mBlendFactorCached==f) {
src_alpha = mAlphaSource;
factor = mAlphaSource;
factor.flags &= ~CORRUPTIBLE;
// we already computed the blend factor before, nothing to do.
if (mBlendFactorCached)
return;
// this is the first time, make sure to compute the blend
// factor properly.
mBlendFactorCached = f;
break;
} else {
// we have a cached alpha blend factor, but we want another one,
// this should really not happen because by construction,
// we cannot have BOTH source and destination
// blend factors use ALPHA *and* ONE_MINUS_ALPHA (because
// the blending stage uses the f/(1-f) optimization
// for completeness, we handle this case though. Since there
// are only 2 choices, this meens we want "the other one"
// (1-factor)
factor = mAlphaSource;
factor.flags &= ~CORRUPTIBLE;
RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
mBlendFactorCached = f;
return;
}
}
FALLTHROUGH_INTENDED;
case GGL_ONE_MINUS_DST_COLOR:
case GGL_DST_COLOR:
case GGL_ONE_MINUS_SRC_COLOR:
case GGL_SRC_COLOR:
case GGL_ONE_MINUS_DST_ALPHA:
case GGL_DST_ALPHA:
case GGL_SRC_ALPHA_SATURATE:
// help us find out what register we can use for the blend-factor
// CORRUPTIBLE registers are chosen first, or a new one is allocated.
if (fragment.flags & CORRUPTIBLE) {
factor.setTo(fragment.reg, 32, CORRUPTIBLE);
fragment.flags &= ~CORRUPTIBLE;
} else if (fb.flags & CORRUPTIBLE) {
factor.setTo(fb.reg, 32, CORRUPTIBLE);
fb.flags &= ~CORRUPTIBLE;
} else {
factor.setTo(scratches.obtain(), 32, CORRUPTIBLE);
}
break;
}
// XXX: doesn't work if size==1
switch(f) {
case GGL_ONE_MINUS_DST_COLOR:
case GGL_DST_COLOR:
factor.s = fb.s;
ADD(AL, 0, factor.reg, fb.reg, reg_imm(fb.reg, LSR, fb.s-1));
break;
case GGL_ONE_MINUS_SRC_COLOR:
case GGL_SRC_COLOR:
factor.s = fragment.s;
ADD(AL, 0, factor.reg, fragment.reg,
reg_imm(fragment.reg, LSR, fragment.s-1));
break;
case GGL_ONE_MINUS_SRC_ALPHA:
case GGL_SRC_ALPHA:
factor.s = src_alpha.s;
ADD(AL, 0, factor.reg, src_alpha.reg,
reg_imm(src_alpha.reg, LSR, src_alpha.s-1));
break;
case GGL_ONE_MINUS_DST_ALPHA:
case GGL_DST_ALPHA:
// XXX: should be precomputed
extract(factor, dst_pixel, GGLFormat::ALPHA);
ADD(AL, 0, factor.reg, factor.reg,
reg_imm(factor.reg, LSR, factor.s-1));
break;
case GGL_SRC_ALPHA_SATURATE:
// XXX: should be precomputed
// XXX: f = min(As, 1-Ad)
// btw, we're guaranteed that Ad's size is <= 8, because
// it's extracted from the framebuffer
break;
}
switch(f) {
case GGL_ONE_MINUS_DST_COLOR:
case GGL_ONE_MINUS_SRC_COLOR:
case GGL_ONE_MINUS_DST_ALPHA:
case GGL_ONE_MINUS_SRC_ALPHA:
RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
}
// don't need more than 8-bits for the blend factor
// and this will prevent overflows in the multiplies later
if (factor.s > 8) {
MOV(AL, 0, factor.reg, reg_imm(factor.reg, LSR, factor.s-8));
factor.s = 8;
}
}
int GGLAssembler::blending_codes(int fs, int fd)
{
int blending = 0;
switch(fs) {
case GGL_ONE:
blending |= BLEND_SRC;
break;
case GGL_ONE_MINUS_DST_COLOR:
case GGL_DST_COLOR:
blending |= FACTOR_DST|BLEND_SRC;
break;
case GGL_ONE_MINUS_DST_ALPHA:
case GGL_DST_ALPHA:
// no need to extract 'component' from the destination
// for the blend factor, because we need ALPHA only.
blending |= BLEND_SRC;
break;
case GGL_ONE_MINUS_SRC_COLOR:
case GGL_SRC_COLOR:
blending |= FACTOR_SRC|BLEND_SRC;
break;
case GGL_ONE_MINUS_SRC_ALPHA:
case GGL_SRC_ALPHA:
case GGL_SRC_ALPHA_SATURATE:
blending |= FACTOR_SRC|BLEND_SRC;
break;
}
switch(fd) {
case GGL_ONE:
blending |= BLEND_DST;
break;
case GGL_ONE_MINUS_DST_COLOR:
case GGL_DST_COLOR:
blending |= FACTOR_DST|BLEND_DST;
break;
case GGL_ONE_MINUS_DST_ALPHA:
case GGL_DST_ALPHA:
blending |= FACTOR_DST|BLEND_DST;
break;
case GGL_ONE_MINUS_SRC_COLOR:
case GGL_SRC_COLOR:
blending |= FACTOR_SRC|BLEND_DST;
break;
case GGL_ONE_MINUS_SRC_ALPHA:
case GGL_SRC_ALPHA:
// no need to extract 'component' from the source
// for the blend factor, because we need ALPHA only.
blending |= BLEND_DST;
break;
}
return blending;
}
// ---------------------------------------------------------------------------
void GGLAssembler::build_blendFOneMinusF(
component_t& temp,
const integer_t& factor,
const integer_t& fragment,
const integer_t& fb)
{
// R = S*f + D*(1-f) = (S-D)*f + D
Scratch scratches(registerFile());
// compute S-D
integer_t diff(fragment.flags & CORRUPTIBLE ?
fragment.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
const int shift = fragment.size() - fb.size();
if (shift>0) RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
else if (shift<0) RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
else RSB(AL, 0, diff.reg, fb.reg, fragment.reg);
mul_factor_add(temp, diff, factor, component_t(fb));
}
void GGLAssembler::build_blendOneMinusFF(
component_t& temp,
const integer_t& factor,
const integer_t& fragment,
const integer_t& fb)
{
// R = S*f + D*(1-f) = (S-D)*f + D
Scratch scratches(registerFile());
// compute D-S
integer_t diff(fb.flags & CORRUPTIBLE ?
fb.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
const int shift = fragment.size() - fb.size();
if (shift>0) SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
else if (shift<0) SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
else SUB(AL, 0, diff.reg, fb.reg, fragment.reg);
mul_factor_add(temp, diff, factor, component_t(fragment));
}
// ---------------------------------------------------------------------------
void GGLAssembler::mul_factor( component_t& d,
const integer_t& v,
const integer_t& f)
{
int vs = v.size();
int fs = f.size();
int ms = vs+fs;
// XXX: we could have special cases for 1 bit mul
// all this code below to use the best multiply instruction
// wrt the parameters size. We take advantage of the fact
// that the 16-bits multiplies allow a 16-bit shift
// The trick is that we just make sure that we have at least 8-bits
// per component (which is enough for a 8 bits display).
int xy;
int vshift = 0;
int fshift = 0;
int smulw = 0;
if (vs<16) {
if (fs<16) {
xy = xyBB;
} else if (GGL_BETWEEN(fs, 24, 31)) {
ms -= 16;
xy = xyTB;
} else {
// eg: 15 * 18 -> 15 * 15
fshift = fs - 15;
ms -= fshift;
xy = xyBB;
}
} else if (GGL_BETWEEN(vs, 24, 31)) {
if (fs<16) {
ms -= 16;
xy = xyTB;
} else if (GGL_BETWEEN(fs, 24, 31)) {
ms -= 32;
xy = xyTT;
} else {
// eg: 24 * 18 -> 8 * 18
fshift = fs - 15;
ms -= 16 + fshift;
xy = xyTB;
}
} else {
if (fs<16) {
// eg: 18 * 15 -> 15 * 15
vshift = vs - 15;
ms -= vshift;
xy = xyBB;
} else if (GGL_BETWEEN(fs, 24, 31)) {
// eg: 18 * 24 -> 15 * 8
vshift = vs - 15;
ms -= 16 + vshift;
xy = xyBT;
} else {
// eg: 18 * 18 -> (15 * 18)>>16
fshift = fs - 15;
ms -= 16 + fshift;
xy = yB; //XXX SMULWB
smulw = 1;
}
}
ALOGE_IF(ms>=32, "mul_factor overflow vs=%d, fs=%d", vs, fs);
int vreg = v.reg;
int freg = f.reg;
if (vshift) {
MOV(AL, 0, d.reg, reg_imm(vreg, LSR, vshift));
vreg = d.reg;
}
if (fshift) {
MOV(AL, 0, d.reg, reg_imm(vreg, LSR, fshift));
freg = d.reg;
}
if (smulw) SMULW(AL, xy, d.reg, vreg, freg);
else SMUL(AL, xy, d.reg, vreg, freg);
d.h = ms;
if (mDithering) {
d.l = 0;
} else {
d.l = fs;
d.flags |= CLEAR_LO;
}
}
void GGLAssembler::mul_factor_add( component_t& d,
const integer_t& v,
const integer_t& f,
const component_t& a)
{
// XXX: we could have special cases for 1 bit mul
Scratch scratches(registerFile());
int vs = v.size();
int fs = f.size();
int as = a.h;
int ms = vs+fs;
ALOGE_IF(ms>=32, "mul_factor_add overflow vs=%d, fs=%d, as=%d", vs, fs, as);
integer_t add(a.reg, a.h, a.flags);
// 'a' is a component_t but it is guaranteed to have
// its high bits set to 0. However in the dithering case,
// we can't get away with truncating the potentially bad bits
// so extraction is needed.
if ((mDithering) && (a.size() < ms)) {
// we need to expand a
if (!(a.flags & CORRUPTIBLE)) {
// ... but it's not corruptible, so we need to pick a
// temporary register.
// Try to uses the destination register first (it's likely
// to be usable, unless it aliases an input).
if (d.reg!=a.reg && d.reg!=v.reg && d.reg!=f.reg) {
add.reg = d.reg;
} else {
add.reg = scratches.obtain();
}
}
expand(add, a, ms); // extracts and expands
as = ms;
}
if (ms == as) {
if (vs<16 && fs<16) SMLABB(AL, d.reg, v.reg, f.reg, add.reg);
else MLA(AL, 0, d.reg, v.reg, f.reg, add.reg);
} else {
int temp = d.reg;
if (temp == add.reg) {
// the mul will modify add.reg, we need an intermediary reg
if (v.flags & CORRUPTIBLE) temp = v.reg;
else if (f.flags & CORRUPTIBLE) temp = f.reg;
else temp = scratches.obtain();
}
if (vs<16 && fs<16) SMULBB(AL, temp, v.reg, f.reg);
else MUL(AL, 0, temp, v.reg, f.reg);
if (ms>as) {
ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSL, ms-as));
} else if (ms<as) {
// not sure if we should expand the mul instead?
ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSR, as-ms));
}
}
d.h = ms;
if (mDithering) {
d.l = a.l;
} else {
d.l = fs>a.l ? fs : a.l;
d.flags |= CLEAR_LO;
}
}
void GGLAssembler::component_add(component_t& d,
const integer_t& dst, const integer_t& src)
{
// here we're guaranteed that fragment.size() >= fb.size()
const int shift = src.size() - dst.size();
if (!shift) {
ADD(AL, 0, d.reg, src.reg, dst.reg);
} else {
ADD(AL, 0, d.reg, src.reg, reg_imm(dst.reg, LSL, shift));
}
d.h = src.size();
if (mDithering) {
d.l = 0;
} else {
d.l = shift;
d.flags |= CLEAR_LO;
}
}
void GGLAssembler::component_sat(const component_t& v)
{
const int one = ((1<<v.size())-1)<<v.l;
CMP(AL, v.reg, imm( 1<<v.h ));
if (isValidImmediate(one)) {
MOV(HS, 0, v.reg, imm( one ));
} else if (isValidImmediate(~one)) {
MVN(HS, 0, v.reg, imm( ~one ));
} else {
MOV(HS, 0, v.reg, imm( 1<<v.h ));
SUB(HS, 0, v.reg, v.reg, imm( 1<<v.l ));
}
}
// ----------------------------------------------------------------------------
}; // namespace android

View File

@ -1,714 +0,0 @@
/* $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $ */
/*-
* Copyright (c) 1996 Mark Brinicombe.
* Copyright (c) 1996 Brini.
*
* 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 Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI 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.
*
* RiscBSD kernel project
*
* db_disasm.c
*
* Kernel disassembler
*
* Created : 10/02/96
*
* Structured after the sparc/sparc/db_disasm.c by David S. Miller &
* Paul Kranenburg
*
* This code is not complete. Not all instructions are disassembled.
*/
#include <sys/cdefs.h>
//__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/arm/arm/disassem.c,v 1.2 2005/01/05 21:58:47 imp Exp $");
#include <sys/param.h>
#include <stdio.h>
#include "disassem.h"
#include "armreg.h"
//#include <ddb/ddb.h>
/*
* General instruction format
*
* insn[cc][mod] [operands]
*
* Those fields with an uppercase format code indicate that the field
* follows directly after the instruction before the separator i.e.
* they modify the instruction rather than just being an operand to
* the instruction. The only exception is the writeback flag which
* follows a operand.
*
*
* 2 - print Operand 2 of a data processing instruction
* d - destination register (bits 12-15)
* n - n register (bits 16-19)
* s - s register (bits 8-11)
* o - indirect register rn (bits 16-19) (used by swap)
* m - m register (bits 0-3)
* a - address operand of ldr/str instruction
* e - address operand of ldrh/strh instruction
* l - register list for ldm/stm instruction
* f - 1st fp operand (register) (bits 12-14)
* g - 2nd fp operand (register) (bits 16-18)
* h - 3rd fp operand (register/immediate) (bits 0-4)
* j - xtb rotate literal (bits 10-11)
* i - bfx lsb literal (bits 7-11)
* w - bfx width literal (bits 16-20)
* b - branch address
* t - thumb branch address (bits 24, 0-23)
* k - breakpoint comment (bits 0-3, 8-19)
* X - block transfer type
* Y - block transfer type (r13 base)
* c - comment field bits(0-23)
* p - saved or current status register
* F - PSR transfer fields
* D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN
* L - co-processor transfer size
* S - set status flag
* P - fp precision
* Q - fp precision (for ldf/stf)
* R - fp rounding
* v - co-processor data transfer registers + addressing mode
* W - writeback flag
* x - instruction in hex
* # - co-processor number
* y - co-processor data processing registers
* z - co-processor register transfer registers
*/
struct arm32_insn {
u_int mask;
u_int pattern;
char* name;
char* format;
};
static const struct arm32_insn arm32_i[] = {
{ 0x0fffffff, 0x0ff00000, "imb", "c" }, /* Before swi */
{ 0x0fffffff, 0x0ff00001, "imbrange", "c" }, /* Before swi */
{ 0x0f000000, 0x0f000000, "swi", "c" },
{ 0xfe000000, 0xfa000000, "blx", "t" }, /* Before b and bl */
{ 0x0f000000, 0x0a000000, "b", "b" },
{ 0x0f000000, 0x0b000000, "bl", "b" },
{ 0x0fe000f0, 0x00000090, "mul", "Snms" },
{ 0x0fe000f0, 0x00200090, "mla", "Snmsd" },
{ 0x0fe000f0, 0x00800090, "umull", "Sdnms" },
{ 0x0fe000f0, 0x00c00090, "smull", "Sdnms" },
{ 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" },
{ 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" },
{ 0x0fff03f0, 0x06cf0070, "uxtb16", "dmj" },
{ 0x0fe00070, 0x07e00050, "ubfx", "dmiw" },
{ 0x0d700000, 0x04200000, "strt", "daW" },
{ 0x0d700000, 0x04300000, "ldrt", "daW" },
{ 0x0d700000, 0x04600000, "strbt", "daW" },
{ 0x0d700000, 0x04700000, "ldrbt", "daW" },
{ 0x0c500000, 0x04000000, "str", "daW" },
{ 0x0c500000, 0x04100000, "ldr", "daW" },
{ 0x0c500000, 0x04400000, "strb", "daW" },
{ 0x0c500000, 0x04500000, "ldrb", "daW" },
{ 0x0e1f0000, 0x080d0000, "stm", "YnWl" },/* separate out r13 base */
{ 0x0e1f0000, 0x081d0000, "ldm", "YnWl" },/* separate out r13 base */
{ 0x0e100000, 0x08000000, "stm", "XnWl" },
{ 0x0e100000, 0x08100000, "ldm", "XnWl" },
{ 0x0e1000f0, 0x00100090, "ldrb", "deW" },
{ 0x0e1000f0, 0x00000090, "strb", "deW" },
{ 0x0e1000f0, 0x001000d0, "ldrsb", "deW" },
{ 0x0e1000f0, 0x001000b0, "ldrh", "deW" },
{ 0x0e1000f0, 0x000000b0, "strh", "deW" },
{ 0x0e1000f0, 0x001000f0, "ldrsh", "deW" },
{ 0x0f200090, 0x00200090, "und", "x" }, /* Before data processing */
{ 0x0e1000d0, 0x000000d0, "und", "x" }, /* Before data processing */
{ 0x0ff00ff0, 0x01000090, "swp", "dmo" },
{ 0x0ff00ff0, 0x01400090, "swpb", "dmo" },
{ 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, /* Before data processing */
{ 0x0fb0fff0, 0x0120f000, "msr", "pFm" },/* Before data processing */
{ 0x0fb0f000, 0x0320f000, "msr", "pF2" },/* Before data processing */
{ 0x0ffffff0, 0x012fff10, "bx", "m" },
{ 0x0fff0ff0, 0x016f0f10, "clz", "dm" },
{ 0x0ffffff0, 0x012fff30, "blx", "m" },
{ 0xfff000f0, 0xe1200070, "bkpt", "k" },
{ 0x0de00000, 0x00000000, "and", "Sdn2" },
{ 0x0de00000, 0x00200000, "eor", "Sdn2" },
{ 0x0de00000, 0x00400000, "sub", "Sdn2" },
{ 0x0de00000, 0x00600000, "rsb", "Sdn2" },
{ 0x0de00000, 0x00800000, "add", "Sdn2" },
{ 0x0de00000, 0x00a00000, "adc", "Sdn2" },
{ 0x0de00000, 0x00c00000, "sbc", "Sdn2" },
{ 0x0de00000, 0x00e00000, "rsc", "Sdn2" },
{ 0x0df00000, 0x01100000, "tst", "Dn2" },
{ 0x0df00000, 0x01300000, "teq", "Dn2" },
{ 0x0df00000, 0x01500000, "cmp", "Dn2" },
{ 0x0df00000, 0x01700000, "cmn", "Dn2" },
{ 0x0de00000, 0x01800000, "orr", "Sdn2" },
{ 0x0de00000, 0x01a00000, "mov", "Sd2" },
{ 0x0de00000, 0x01c00000, "bic", "Sdn2" },
{ 0x0de00000, 0x01e00000, "mvn", "Sd2" },
{ 0x0ff08f10, 0x0e000100, "adf", "PRfgh" },
{ 0x0ff08f10, 0x0e100100, "muf", "PRfgh" },
{ 0x0ff08f10, 0x0e200100, "suf", "PRfgh" },
{ 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" },
{ 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" },
{ 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" },
{ 0x0ff08f10, 0x0e600100, "pow", "PRfgh" },
{ 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" },
{ 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" },
{ 0x0ff08f10, 0x0e900100, "fml", "PRfgh" },
{ 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" },
{ 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" },
{ 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" },
{ 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" },
{ 0x0ff08f10, 0x0e008100, "mvf", "PRfh" },
{ 0x0ff08f10, 0x0e108100, "mnf", "PRfh" },
{ 0x0ff08f10, 0x0e208100, "abs", "PRfh" },
{ 0x0ff08f10, 0x0e308100, "rnd", "PRfh" },
{ 0x0ff08f10, 0x0e408100, "sqt", "PRfh" },
{ 0x0ff08f10, 0x0e508100, "log", "PRfh" },
{ 0x0ff08f10, 0x0e608100, "lgn", "PRfh" },
{ 0x0ff08f10, 0x0e708100, "exp", "PRfh" },
{ 0x0ff08f10, 0x0e808100, "sin", "PRfh" },
{ 0x0ff08f10, 0x0e908100, "cos", "PRfh" },
{ 0x0ff08f10, 0x0ea08100, "tan", "PRfh" },
{ 0x0ff08f10, 0x0eb08100, "asn", "PRfh" },
{ 0x0ff08f10, 0x0ec08100, "acs", "PRfh" },
{ 0x0ff08f10, 0x0ed08100, "atn", "PRfh" },
{ 0x0f008f10, 0x0e008100, "fpuop", "PRfh" },
{ 0x0e100f00, 0x0c000100, "stf", "QLv" },
{ 0x0e100f00, 0x0c100100, "ldf", "QLv" },
{ 0x0ff00f10, 0x0e000110, "flt", "PRgd" },
{ 0x0ff00f10, 0x0e100110, "fix", "PRdh" },
{ 0x0ff00f10, 0x0e200110, "wfs", "d" },
{ 0x0ff00f10, 0x0e300110, "rfs", "d" },
{ 0x0ff00f10, 0x0e400110, "wfc", "d" },
{ 0x0ff00f10, 0x0e500110, "rfc", "d" },
{ 0x0ff0ff10, 0x0e90f110, "cmf", "PRgh" },
{ 0x0ff0ff10, 0x0eb0f110, "cnf", "PRgh" },
{ 0x0ff0ff10, 0x0ed0f110, "cmfe", "PRgh" },
{ 0x0ff0ff10, 0x0ef0f110, "cnfe", "PRgh" },
{ 0xff100010, 0xfe000010, "mcr2", "#z" },
{ 0x0f100010, 0x0e000010, "mcr", "#z" },
{ 0xff100010, 0xfe100010, "mrc2", "#z" },
{ 0x0f100010, 0x0e100010, "mrc", "#z" },
{ 0xff000010, 0xfe000000, "cdp2", "#y" },
{ 0x0f000010, 0x0e000000, "cdp", "#y" },
{ 0xfe100090, 0xfc100000, "ldc2", "L#v" },
{ 0x0e100090, 0x0c100000, "ldc", "L#v" },
{ 0xfe100090, 0xfc000000, "stc2", "L#v" },
{ 0x0e100090, 0x0c000000, "stc", "L#v" },
{ 0xf550f000, 0xf550f000, "pld", "ne" },
{ 0x0ff00ff0, 0x01000050, "qaad", "dmn" },
{ 0x0ff00ff0, 0x01400050, "qdaad", "dmn" },
{ 0x0ff00ff0, 0x01600050, "qdsub", "dmn" },
{ 0x0ff00ff0, 0x01200050, "dsub", "dmn" },
{ 0x0ff000f0, 0x01000080, "smlabb", "nmsd" }, // d & n inverted!!
{ 0x0ff000f0, 0x010000a0, "smlatb", "nmsd" }, // d & n inverted!!
{ 0x0ff000f0, 0x010000c0, "smlabt", "nmsd" }, // d & n inverted!!
{ 0x0ff000f0, 0x010000e0, "smlatt", "nmsd" }, // d & n inverted!!
{ 0x0ff000f0, 0x01400080, "smlalbb","ndms" }, // d & n inverted!!
{ 0x0ff000f0, 0x014000a0, "smlaltb","ndms" }, // d & n inverted!!
{ 0x0ff000f0, 0x014000c0, "smlalbt","ndms" }, // d & n inverted!!
{ 0x0ff000f0, 0x014000e0, "smlaltt","ndms" }, // d & n inverted!!
{ 0x0ff000f0, 0x01200080, "smlawb", "nmsd" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x012000a0, "smulwb","nms" }, // d & n inverted!!
{ 0x0ff000f0, 0x012000c0, "smlawt", "nmsd" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x012000e0, "smulwt","nms" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x01600080, "smulbb","nms" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x016000a0, "smultb","nms" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x016000c0, "smulbt","nms" }, // d & n inverted!!
{ 0x0ff0f0f0, 0x016000e0, "smultt","nms" }, // d & n inverted!!
{ 0x00000000, 0x00000000, NULL, NULL }
};
static char const arm32_insn_conditions[][4] = {
"eq", "ne", "cs", "cc",
"mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt",
"gt", "le", "", "nv"
};
static char const insn_block_transfers[][4] = {
"da", "ia", "db", "ib"
};
static char const insn_stack_block_transfers[][4] = {
"ed", "ea", "fd", "fa"
};
static char const op_shifts[][4] = {
"lsl", "lsr", "asr", "ror"
};
static char const insn_fpa_rounding[][2] = {
"", "p", "m", "z"
};
static char const insn_fpa_precision[][2] = {
"s", "d", "e", "p"
};
static char const insn_fpaconstants[][8] = {
"0.0", "1.0", "2.0", "3.0",
"4.0", "5.0", "0.5", "10.0"
};
#define insn_condition(x) arm32_insn_conditions[((x) >> 28) & 0x0f]
#define insn_blktrans(x) insn_block_transfers[((x) >> 23) & 3]
#define insn_stkblktrans(x) insn_stack_block_transfers[(3*(((x) >> 20)&1))^(((x) >> 23)&3)]
#define op2_shift(x) op_shifts[((x) >> 5) & 3]
#define insn_fparnd(x) insn_fpa_rounding[((x) >> 5) & 0x03]
#define insn_fpaprec(x) insn_fpa_precision[((((x) >> 18) & 2)|((x) >> 7)) & 1]
#define insn_fpaprect(x) insn_fpa_precision[((((x) >> 21) & 2)|((x) >> 15)) & 1]
#define insn_fpaimm(x) insn_fpaconstants[(x) & 0x07]
/* Local prototypes */
static void disasm_register_shift(const disasm_interface_t *di, u_int insn);
static void disasm_print_reglist(const disasm_interface_t *di, u_int insn);
static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn,
u_int loc);
static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn,
u_int loc);
static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn,
u_int loc);
static u_int disassemble_readword(u_int address);
static void disassemble_printaddr(u_int address);
u_int
disasm(const disasm_interface_t *di, u_int loc, int __unused altfmt)
{
const struct arm32_insn *i_ptr = &arm32_i[0];
u_int insn = di->di_readword(loc);
int matchp = 0;
int branch;
char* f_ptr;
int fmt = 0;
/* di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/
while (i_ptr->name) {
if ((insn & i_ptr->mask) == i_ptr->pattern) {
matchp = 1;
break;
}
i_ptr++;
}
if (!matchp) {
di->di_printf("und%s\t%08x\n", insn_condition(insn), insn);
return(loc + INSN_SIZE);
}
/* If instruction forces condition code, don't print it. */
if ((i_ptr->mask & 0xf0000000) == 0xf0000000)
di->di_printf("%s", i_ptr->name);
else
di->di_printf("%s%s", i_ptr->name, insn_condition(insn));
f_ptr = i_ptr->format;
/* Insert tab if there are no instruction modifiers */
if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') {
++fmt;
di->di_printf("\t");
}
while (*f_ptr) {
switch (*f_ptr) {
/* 2 - print Operand 2 of a data processing instruction */
case '2':
if (insn & 0x02000000) {
int rotate= ((insn >> 7) & 0x1e);
di->di_printf("#0x%08x",
(insn & 0xff) << (32 - rotate) |
(insn & 0xff) >> rotate);
} else {
disasm_register_shift(di, insn);
}
break;
/* d - destination register (bits 12-15) */
case 'd':
di->di_printf("r%d", ((insn >> 12) & 0x0f));
break;
/* D - insert 'p' if Rd is R15 */
case 'D':
if (((insn >> 12) & 0x0f) == 15)
di->di_printf("p");
break;
/* n - n register (bits 16-19) */
case 'n':
di->di_printf("r%d", ((insn >> 16) & 0x0f));
break;
/* s - s register (bits 8-11) */
case 's':
di->di_printf("r%d", ((insn >> 8) & 0x0f));
break;
/* o - indirect register rn (bits 16-19) (used by swap) */
case 'o':
di->di_printf("[r%d]", ((insn >> 16) & 0x0f));
break;
/* m - m register (bits 0-4) */
case 'm':
di->di_printf("r%d", ((insn >> 0) & 0x0f));
break;
/* a - address operand of ldr/str instruction */
case 'a':
disasm_insn_ldrstr(di, insn, loc);
break;
/* e - address operand of ldrh/strh instruction */
case 'e':
disasm_insn_ldrhstrh(di, insn, loc);
break;
/* l - register list for ldm/stm instruction */
case 'l':
disasm_print_reglist(di, insn);
break;
/* f - 1st fp operand (register) (bits 12-14) */
case 'f':
di->di_printf("f%d", (insn >> 12) & 7);
break;
/* g - 2nd fp operand (register) (bits 16-18) */
case 'g':
di->di_printf("f%d", (insn >> 16) & 7);
break;
/* h - 3rd fp operand (register/immediate) (bits 0-4) */
case 'h':
if (insn & (1 << 3))
di->di_printf("#%s", insn_fpaimm(insn));
else
di->di_printf("f%d", insn & 7);
break;
/* j - xtb rotate literal (bits 10-11) */
case 'j':
di->di_printf("ror #%d", ((insn >> 10) & 3) << 3);
break;
/* i - bfx lsb literal (bits 7-11) */
case 'i':
di->di_printf("#%d", (insn >> 7) & 31);
break;
/* w - bfx width literal (bits 16-20) */
case 'w':
di->di_printf("#%d", 1 + ((insn >> 16) & 31));
break;
/* b - branch address */
case 'b':
branch = ((insn << 2) & 0x03ffffff);
if (branch & 0x02000000)
branch |= 0xfc000000;
di->di_printaddr(loc + 8 + branch);
break;
/* t - blx address */
case 't':
branch = ((insn << 2) & 0x03ffffff) |
(insn >> 23 & 0x00000002);
if (branch & 0x02000000)
branch |= 0xfc000000;
di->di_printaddr(loc + 8 + branch);
break;
/* X - block transfer type */
case 'X':
di->di_printf("%s", insn_blktrans(insn));
break;
/* Y - block transfer type (r13 base) */
case 'Y':
di->di_printf("%s", insn_stkblktrans(insn));
break;
/* c - comment field bits(0-23) */
case 'c':
di->di_printf("0x%08x", (insn & 0x00ffffff));
break;
/* k - breakpoint comment (bits 0-3, 8-19) */
case 'k':
di->di_printf("0x%04x",
(insn & 0x000fff00) >> 4 | (insn & 0x0000000f));
break;
/* p - saved or current status register */
case 'p':
if (insn & 0x00400000)
di->di_printf("spsr");
else
di->di_printf("cpsr");
break;
/* F - PSR transfer fields */
case 'F':
di->di_printf("_");
if (insn & (1 << 16))
di->di_printf("c");
if (insn & (1 << 17))
di->di_printf("x");
if (insn & (1 << 18))
di->di_printf("s");
if (insn & (1 << 19))
di->di_printf("f");
break;
/* B - byte transfer flag */
case 'B':
if (insn & 0x00400000)
di->di_printf("b");
break;
/* L - co-processor transfer size */
case 'L':
if (insn & (1 << 22))
di->di_printf("l");
break;
/* S - set status flag */
case 'S':
if (insn & 0x00100000)
di->di_printf("s");
break;
/* P - fp precision */
case 'P':
di->di_printf("%s", insn_fpaprec(insn));
break;
/* Q - fp precision (for ldf/stf) */
case 'Q':
break;
/* R - fp rounding */
case 'R':
di->di_printf("%s", insn_fparnd(insn));
break;
/* W - writeback flag */
case 'W':
if (insn & (1 << 21))
di->di_printf("!");
break;
/* # - co-processor number */
case '#':
di->di_printf("p%d", (insn >> 8) & 0x0f);
break;
/* v - co-processor data transfer registers+addressing mode */
case 'v':
disasm_insn_ldcstc(di, insn, loc);
break;
/* x - instruction in hex */
case 'x':
di->di_printf("0x%08x", insn);
break;
/* y - co-processor data processing registers */
case 'y':
di->di_printf("%d, ", (insn >> 20) & 0x0f);
di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f,
(insn >> 16) & 0x0f, insn & 0x0f);
di->di_printf(", %d", (insn >> 5) & 0x07);
break;
/* z - co-processor register transfer registers */
case 'z':
di->di_printf("%d, ", (insn >> 21) & 0x07);
di->di_printf("r%d, c%d, c%d, %d",
(insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
insn & 0x0f, (insn >> 5) & 0x07);
/* if (((insn >> 5) & 0x07) != 0)
di->di_printf(", %d", (insn >> 5) & 0x07);*/
break;
default:
di->di_printf("[%c - unknown]", *f_ptr);
break;
}
if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z')
++f_ptr;
else if (*(++f_ptr)) {
++fmt;
if (fmt == 1)
di->di_printf("\t");
else
di->di_printf(", ");
}
};
di->di_printf("\n");
return(loc + INSN_SIZE);
}
static void
disasm_register_shift(const disasm_interface_t *di, u_int insn)
{
di->di_printf("r%d", (insn & 0x0f));
if ((insn & 0x00000ff0) == 0)
;
else if ((insn & 0x00000ff0) == 0x00000060)
di->di_printf(", rrx");
else {
if (insn & 0x10)
di->di_printf(", %s r%d", op2_shift(insn),
(insn >> 8) & 0x0f);
else
di->di_printf(", %s #%d", op2_shift(insn),
(insn >> 7) & 0x1f);
}
}
static void
disasm_print_reglist(const disasm_interface_t *di, u_int insn)
{
int loop;
int start;
int comma;
di->di_printf("{");
start = -1;
comma = 0;
for (loop = 0; loop < 17; ++loop) {
if (start != -1) {
if (loop == 16 || !(insn & (1 << loop))) {
if (comma)
di->di_printf(", ");
else
comma = 1;
if (start == loop - 1)
di->di_printf("r%d", start);
else
di->di_printf("r%d-r%d", start, loop - 1);
start = -1;
}
} else {
if (insn & (1 << loop))
start = loop;
}
}
di->di_printf("}");
if (insn & (1 << 22))
di->di_printf("^");
}
static void
disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc)
{
int offset;
offset = insn & 0xfff;
if ((insn & 0x032f0000) == 0x010f0000) {
/* rA = pc, immediate index */
if (insn & 0x00800000)
loc += offset;
else
loc -= offset;
di->di_printaddr(loc + 8);
} else {
di->di_printf("[r%d", (insn >> 16) & 0x0f);
if ((insn & 0x03000fff) != 0x01000000) {
di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
if (!(insn & 0x00800000))
di->di_printf("-");
if (insn & (1 << 25))
disasm_register_shift(di, insn);
else
di->di_printf("#0x%03x", offset);
}
if (insn & (1 << 24))
di->di_printf("]");
}
}
static void
disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc)
{
int offset;
offset = ((insn & 0xf00) >> 4) | (insn & 0xf);
if ((insn & 0x004f0000) == 0x004f0000) {
/* rA = pc, immediate index */
if (insn & 0x00800000)
loc += offset;
else
loc -= offset;
di->di_printaddr(loc + 8);
} else {
di->di_printf("[r%d", (insn >> 16) & 0x0f);
if ((insn & 0x01400f0f) != 0x01400000) {
di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
if (!(insn & 0x00800000))
di->di_printf("-");
if (insn & (1 << 22))
di->di_printf("#0x%02x", offset);
else
di->di_printf("r%d", (insn & 0x0f));
}
if (insn & (1 << 24))
di->di_printf("]");
}
}
static void
disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int __unused loc)
{
if (((insn >> 8) & 0xf) == 1)
di->di_printf("f%d, ", (insn >> 12) & 0x07);
else
di->di_printf("c%d, ", (insn >> 12) & 0x0f);
di->di_printf("[r%d", (insn >> 16) & 0x0f);
di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]");
if (!(insn & (1 << 23)))
di->di_printf("-");
di->di_printf("#0x%03x", (insn & 0xff) << 2);
if (insn & (1 << 24))
di->di_printf("]");
if (insn & (1 << 21))
di->di_printf("!");
}
static u_int
disassemble_readword(u_int address)
{
return(*((u_int *)address));
}
static void
disassemble_printaddr(u_int address)
{
printf("0x%08x", address);
}
static const disasm_interface_t disassemble_di = {
disassemble_readword, disassemble_printaddr, printf
};
void
disassemble(u_int address)
{
(void)disasm(&disassemble_di, address, 0);
}
/* End of disassem.c */

View File

@ -1,65 +0,0 @@
/* $NetBSD: disassem.h,v 1.4 2001/03/04 04:15:58 matt Exp $ */
/*-
* Copyright (c) 1997 Mark Brinicombe.
* Copyright (c) 1997 Causality 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:
* 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. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Define the interface structure required by the disassembler.
*
* $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/disassem.h,v 1.2 2005/01/05 21:58:48 imp Exp $
*/
#ifndef ANDROID_MACHINE_DISASSEM_H
#define ANDROID_MACHINE_DISASSEM_H
#include <sys/types.h>
#if __cplusplus
extern "C" {
#endif
typedef struct {
u_int (*di_readword)(u_int);
void (*di_printaddr)(u_int);
int (*di_printf)(const char *, ...);
} disasm_interface_t;
/* Prototypes for callable functions */
u_int disasm(const disasm_interface_t *, u_int, int);
void disassemble(u_int);
#if __cplusplus
}
#endif
#endif /* !ANDROID_MACHINE_DISASSEM_H */

View File

@ -1,384 +0,0 @@
/* libs/pixelflinger/codeflinger/load_store.cpp
**
** Copyright 2006, 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.
*/
#define LOG_TAG "pixelflinger-code"
#include <assert.h>
#include <stdio.h>
#include <log/log.h>
#include "GGLAssembler.h"
namespace android {
// ----------------------------------------------------------------------------
void GGLAssembler::store(const pointer_t& addr, const pixel_t& s, uint32_t flags)
{
const int bits = addr.size;
const int inc = (flags & WRITE_BACK)?1:0;
switch (bits) {
case 32:
if (inc) STR(AL, s.reg, addr.reg, immed12_post(4));
else STR(AL, s.reg, addr.reg);
break;
case 24:
// 24 bits formats are a little special and used only for RGB
// 0x00BBGGRR is unpacked as R,G,B
STRB(AL, s.reg, addr.reg, immed12_pre(0));
MOV(AL, 0, s.reg, reg_imm(s.reg, ROR, 8));
STRB(AL, s.reg, addr.reg, immed12_pre(1));
MOV(AL, 0, s.reg, reg_imm(s.reg, ROR, 8));
STRB(AL, s.reg, addr.reg, immed12_pre(2));
if (!(s.flags & CORRUPTIBLE)) {
MOV(AL, 0, s.reg, reg_imm(s.reg, ROR, 16));
}
if (inc)
ADD(AL, 0, addr.reg, addr.reg, imm(3));
break;
case 16:
if (inc) STRH(AL, s.reg, addr.reg, immed8_post(2));
else STRH(AL, s.reg, addr.reg);
break;
case 8:
if (inc) STRB(AL, s.reg, addr.reg, immed12_post(1));
else STRB(AL, s.reg, addr.reg);
break;
}
}
void GGLAssembler::load(const pointer_t& addr, const pixel_t& s, uint32_t flags)
{
Scratch scratches(registerFile());
int s0;
const int bits = addr.size;
const int inc = (flags & WRITE_BACK)?1:0;
switch (bits) {
case 32:
if (inc) LDR(AL, s.reg, addr.reg, immed12_post(4));
else LDR(AL, s.reg, addr.reg);
break;
case 24:
// 24 bits formats are a little special and used only for RGB
// R,G,B is packed as 0x00BBGGRR
s0 = scratches.obtain();
if (s.reg != addr.reg) {
LDRB(AL, s.reg, addr.reg, immed12_pre(0)); // R
LDRB(AL, s0, addr.reg, immed12_pre(1)); // G
ORR(AL, 0, s.reg, s.reg, reg_imm(s0, LSL, 8));
LDRB(AL, s0, addr.reg, immed12_pre(2)); // B
ORR(AL, 0, s.reg, s.reg, reg_imm(s0, LSL, 16));
} else {
int s1 = scratches.obtain();
LDRB(AL, s1, addr.reg, immed12_pre(0)); // R
LDRB(AL, s0, addr.reg, immed12_pre(1)); // G
ORR(AL, 0, s1, s1, reg_imm(s0, LSL, 8));
LDRB(AL, s0, addr.reg, immed12_pre(2)); // B
ORR(AL, 0, s.reg, s1, reg_imm(s0, LSL, 16));
}
if (inc)
ADD(AL, 0, addr.reg, addr.reg, imm(3));
break;
case 16:
if (inc) LDRH(AL, s.reg, addr.reg, immed8_post(2));
else LDRH(AL, s.reg, addr.reg);
break;
case 8:
if (inc) LDRB(AL, s.reg, addr.reg, immed12_post(1));
else LDRB(AL, s.reg, addr.reg);
break;
}
}
void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits)
{
const int maskLen = h-l;
#ifdef __mips__
assert(maskLen<=11);
#else
assert(maskLen<=8);
#endif
assert(h);
if (h != bits) {
const int mask = ((1<<maskLen)-1) << l;
if (isValidImmediate(mask)) {
AND(AL, 0, d.reg, s, imm(mask)); // component = packed & mask;
} else if (isValidImmediate(~mask)) {
BIC(AL, 0, d.reg, s, imm(~mask)); // component = packed & mask;
} else {
MOV(AL, 0, d.reg, reg_imm(s, LSL, 32-h));
l += 32-h;
h = 32;
}
s = d.reg;
}
if (l) {
MOV(AL, 0, d.reg, reg_imm(s, LSR, l)); // component = packed >> l;
s = d.reg;
}
if (s != d.reg) {
MOV(AL, 0, d.reg, s);
}
d.s = maskLen;
}
void GGLAssembler::extract(integer_t& d, const pixel_t& s, int component)
{
extract(d, s.reg,
s.format.c[component].h,
s.format.c[component].l,
s.size());
}
void GGLAssembler::extract(component_t& d, const pixel_t& s, int component)
{
integer_t r(d.reg, 32, d.flags);
extract(r, s.reg,
s.format.c[component].h,
s.format.c[component].l,
s.size());
d = component_t(r);
}
void GGLAssembler::expand(integer_t& d, const component_t& s, int dbits)
{
if (s.l || (s.flags & CLEAR_HI)) {
extract(d, s.reg, s.h, s.l, 32);
expand(d, d, dbits);
} else {
expand(d, integer_t(s.reg, s.size(), s.flags), dbits);
}
}
void GGLAssembler::expand(component_t& d, const component_t& s, int dbits)
{
integer_t r(d.reg, 32, d.flags);
expand(r, s, dbits);
d = component_t(r);
}
void GGLAssembler::expand(integer_t& dst, const integer_t& src, int dbits)
{
assert(src.size());
int sbits = src.size();
int s = src.reg;
int d = dst.reg;
// be sure to set 'dst' after we read 'src' as they may be identical
dst.s = dbits;
dst.flags = 0;
if (dbits<=sbits) {
if (s != d) {
MOV(AL, 0, d, s);
}
return;
}
if (sbits == 1) {
RSB(AL, 0, d, s, reg_imm(s, LSL, dbits));
// d = (s<<dbits) - s;
return;
}
if (dbits % sbits) {
MOV(AL, 0, d, reg_imm(s, LSL, dbits-sbits));
// d = s << (dbits-sbits);
dbits -= sbits;
do {
ORR(AL, 0, d, d, reg_imm(d, LSR, sbits));
// d |= d >> sbits;
dbits -= sbits;
sbits *= 2;
} while(dbits>0);
return;
}
dbits -= sbits;
do {
ORR(AL, 0, d, s, reg_imm(s, LSL, sbits));
// d |= d<<sbits;
s = d;
dbits -= sbits;
if (sbits*2 < dbits) {
sbits *= 2;
}
} while(dbits>0);
}
void GGLAssembler::downshift(
pixel_t& d, int component, component_t s, const reg_t& dither)
{
Scratch scratches(registerFile());
int sh = s.h;
int sl = s.l;
int maskHiBits = (sh!=32) ? ((s.flags & CLEAR_HI)?1:0) : 0;
int maskLoBits = (sl!=0) ? ((s.flags & CLEAR_LO)?1:0) : 0;
int sbits = sh - sl;
int dh = d.format.c[component].h;
int dl = d.format.c[component].l;
int dbits = dh - dl;
int dithering = 0;
ALOGE_IF(sbits<dbits, "sbits (%d) < dbits (%d) in downshift", sbits, dbits);
if (sbits>dbits) {
// see if we need to dither
dithering = mDithering;
}
int ireg = d.reg;
if (!(d.flags & FIRST)) {
if (s.flags & CORRUPTIBLE) {
ireg = s.reg;
} else {
ireg = scratches.obtain();
}
}
d.flags &= ~FIRST;
if (maskHiBits) {
// we need to mask the high bits (and possibly the lowbits too)
// and we might be able to use immediate mask.
if (!dithering) {
// we don't do this if we only have maskLoBits because we can
// do it more efficiently below (in the case where dl=0)
const int offset = sh - dbits;
if (dbits<=8 && offset >= 0) {
const uint32_t mask = ((1<<dbits)-1) << offset;
if (isValidImmediate(mask) || isValidImmediate(~mask)) {
build_and_immediate(ireg, s.reg, mask, 32);
sl = offset;
s.reg = ireg;
sbits = dbits;
maskLoBits = maskHiBits = 0;
}
}
} else {
// in the dithering case though, we need to preserve the lower bits
const uint32_t mask = ((1<<sbits)-1) << sl;
if (isValidImmediate(mask) || isValidImmediate(~mask)) {
build_and_immediate(ireg, s.reg, mask, 32);
s.reg = ireg;
maskLoBits = maskHiBits = 0;
}
}
}
// XXX: we could special case (maskHiBits & !maskLoBits)
// like we do for maskLoBits below, but it happens very rarely
// that we have maskHiBits only and the conditions necessary to lead
// to better code (like doing d |= s << 24)
if (maskHiBits) {
MOV(AL, 0, ireg, reg_imm(s.reg, LSL, 32-sh));
sl += 32-sh;
sh = 32;
s.reg = ireg;
maskHiBits = 0;
}
// Downsampling should be performed as follows:
// V * ((1<<dbits)-1) / ((1<<sbits)-1)
// V * [(1<<dbits)/((1<<sbits)-1) - 1/((1<<sbits)-1)]
// V * [1/((1<<sbits)-1)>>dbits - 1/((1<<sbits)-1)]
// V/((1<<(sbits-dbits))-(1>>dbits)) - (V>>sbits)/((1<<sbits)-1)>>sbits
// V/((1<<(sbits-dbits))-(1>>dbits)) - (V>>sbits)/(1-(1>>sbits))
//
// By approximating (1>>dbits) and (1>>sbits) to 0:
//
// V>>(sbits-dbits) - V>>sbits
//
// A good approximation is V>>(sbits-dbits),
// but better one (needed for dithering) is:
//
// (V>>(sbits-dbits)<<sbits - V)>>sbits
// (V<<dbits - V)>>sbits
// (V - V>>dbits)>>(sbits-dbits)
// Dithering is done here
if (dithering) {
comment("dithering");
if (sl) {
MOV(AL, 0, ireg, reg_imm(s.reg, LSR, sl));
sh -= sl;
sl = 0;
s.reg = ireg;
}
// scaling (V-V>>dbits)
SUB(AL, 0, ireg, s.reg, reg_imm(s.reg, LSR, dbits));
const int shift = (GGL_DITHER_BITS - (sbits-dbits));
if (shift>0) ADD(AL, 0, ireg, ireg, reg_imm(dither.reg, LSR, shift));
else if (shift<0) ADD(AL, 0, ireg, ireg, reg_imm(dither.reg, LSL,-shift));
else ADD(AL, 0, ireg, ireg, dither.reg);
s.reg = ireg;
}
if ((maskLoBits|dithering) && (sh > dbits)) {
int shift = sh-dbits;
if (dl) {
MOV(AL, 0, ireg, reg_imm(s.reg, LSR, shift));
if (ireg == d.reg) {
MOV(AL, 0, d.reg, reg_imm(ireg, LSL, dl));
} else {
ORR(AL, 0, d.reg, d.reg, reg_imm(ireg, LSL, dl));
}
} else {
if (ireg == d.reg) {
MOV(AL, 0, d.reg, reg_imm(s.reg, LSR, shift));
} else {
ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSR, shift));
}
}
} else {
int shift = sh-dh;
if (shift>0) {
if (ireg == d.reg) {
MOV(AL, 0, d.reg, reg_imm(s.reg, LSR, shift));
} else {
ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSR, shift));
}
} else if (shift<0) {
if (ireg == d.reg) {
MOV(AL, 0, d.reg, reg_imm(s.reg, LSL, -shift));
} else {
ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSL, -shift));
}
} else {
if (ireg == d.reg) {
if (s.reg != d.reg) {
MOV(AL, 0, d.reg, s.reg);
}
} else {
ORR(AL, 0, d.reg, d.reg, s.reg);
}
}
}
}
}; // namespace android

View File

@ -1,584 +0,0 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 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.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <android/log.h>
#include "mips_opcode.h"
#define __unused __attribute__((__unused__))
static char *sprintf_buffer;
static int sprintf_buf_len;
typedef uint64_t db_addr_t;
static void db_printf(const char* fmt, ...);
static const char * const op_name[64] = {
/* 0 */ "spec", "bcond", "j", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "pop10", "addiu", "slti", "sltiu", "andi", "ori", "xori", "aui",
/*16 */ "cop0", "cop1", "cop2", "?", "?", "?", "pop26", "pop27",
/*24 */ "pop30", "daddiu", "?", "?", "?", "daui", "msa", "op37",
/*32 */ "lb", "lh", "?", "lw", "lbu", "lhu", "?", "lwu",
/*40 */ "sb", "sh", "?", "sw", "?", "?", "?", "?",
/*48 */ "?", "lwc1", "bc", "?", "?", "ldc1", "pop66", "ld",
/*56 */ "?", "swc1", "balc", "pcrel", "?", "sdc1", "pop76", "sd"
};
static const char * const spec_name[64] = {
/* 0 */ "sll", "?", "srl", "sra", "sllv", "?", "srlv", "srav",
/* 8 */ "?", "jalr", "?", "?", "syscall", "break", "sdbpp", "sync",
/*16 */ "clz", "clo", "dclz", "dclo", "dsllv", "dlsa", "dsrlv", "dsrav",
/*24 */ "sop30", "sop31", "sop32", "sop33", "sop34", "sop35", "sop36", "sop37",
/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
/*40 */ "?", "?", "slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
/*48 */ "tge", "tgeu", "tlt", "tltu", "teq", "seleqz", "tne", "selnez",
/*56 */ "dsll", "?", "dsrl", "dsra", "dsll32", "?", "dsrl32", "dsra32"
};
static const char * const bcond_name[32] = {
/* 0 */ "bltz", "bgez", "?", "?", "?", "?", "dahi", "?",
/* 8 */ "?", "?", "?", "?", "?", "?", "?", "?",
/*16 */ "nal", "bal", "?", "?", "?", "?", "?", "sigrie",
/*24 */ "?", "?", "?", "?", "?", "?", "dati", "synci",
};
static const char * const cop1_name[64] = {
/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
"fcmp.ole","fcmp.ule",
/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
"fcmp.le","fcmp.ngt"
};
static const char * const fmt_name[16] = {
"s", "d", "e", "fmt3",
"w", "fmt5", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
static char * const mips_reg_name[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM code
"zero", "at", "r0", "r1", "r2", "r3", "r4", "r5",
"r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13",
"r14", "r15", "at2", "cmp", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char * const * reg_name = &mips_reg_name[0];
static const char * const c0_opname[64] = {
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
"eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
};
static const char * const c0_reg[32] = {
"index", "random", "tlblo0", "tlblo1",
"context", "pagemask", "wired", "cp0r7",
"badvaddr", "count", "tlbhi", "compare",
"status", "cause", "epc", "prid",
"config", "lladdr", "watchlo", "watchhi",
"xcontext", "cp0r21", "cp0r22", "debug",
"depc", "perfcnt", "ecc", "cacheerr",
"taglo", "taghi", "errepc", "desave"
};
static void print_addr(db_addr_t);
db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
/*
* Disassemble instruction 'insn' nominally at 'loc'.
* 'loc' may in fact contain a breakpoint instruction.
*/
static db_addr_t
db_disasm_insn(int insn, db_addr_t loc, bool altfmt __unused)
{
bool bdslot = false;
InstFmt i;
i.word = insn;
switch (i.JType.op) {
case OP_SPECIAL:
if (i.word == 0) {
db_printf("nop");
break;
}
if (i.word == 0x0080) {
db_printf("NIY");
break;
}
if (i.word == 0x00c0) {
db_printf("NOT IMPL");
break;
}
/* Special cases --------------------------------------------------
* "addu" is a "move" only in 32-bit mode. What's the correct
* answer - never decode addu/daddu as "move"?
*/
if ( (i.RType.func == OP_ADDU && i.RType.rt == 0) ||
(i.RType.func == OP_OR && i.RType.rt == 0) ) {
db_printf("move\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
}
if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
reg_name[i.RType.rt], i.RType.shamt);
break;
}
if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rt], reg_name[i.RType.rs]);
break;
}
if (i.RType.func == OP_SOP30) {
if (i.RType.shamt == OP_MUL) {
db_printf("mul");
} else if (i.RType.shamt == OP_MUH) {
db_printf("muh");
}
db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rs], reg_name[i.RType.rt]);
break;
}
if (i.RType.func == OP_SOP31) {
if (i.RType.shamt == OP_MUL) {
db_printf("mulu");
} else if (i.RType.shamt == OP_MUH) {
db_printf("muhu");
}
db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rs], reg_name[i.RType.rt]);
break;
}
if (i.RType.func == OP_JALR && i.RType.rd == 0) {
db_printf("jr\t%s", reg_name[i.RType.rs]);
bdslot = true;
break;
}
db_printf("%s", spec_name[i.RType.func]);
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
case OP_SRA:
case OP_DSLL:
case OP_DSRL:
case OP_DSRA:
case OP_DSLL32:
case OP_DSRL32:
case OP_DSRA32:
db_printf("\t%s,%s,%d",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
i.RType.shamt);
break;
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
reg_name[i.RType.rs]);
break;
case OP_CLZ:
case OP_CLO:
case OP_DCLZ:
case OP_DCLO:
db_printf("\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
case OP_JALR:
db_printf("\t");
if (i.RType.rd != 31) {
db_printf("%s,", reg_name[i.RType.rd]);
}
db_printf("%s", reg_name[i.RType.rs]);
bdslot = true;
break;
case OP_SYSCALL:
case OP_SYNC:
break;
case OP_BREAK:
db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
break;
default:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
}
break;
case OP_SPECIAL3:
if (i.RType.func == OP_EXT)
db_printf("ext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_DEXT)
db_printf("dext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_DEXTM)
db_printf("dextm\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+33);
else if (i.RType.func == OP_DEXTU)
db_printf("dextu\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt+32,
i.RType.rd+1);
else if (i.RType.func == OP_INS)
db_printf("ins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_DINS)
db_printf("dins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_DINSM)
db_printf("dinsm\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+33);
else if (i.RType.func == OP_DINSU)
db_printf("dinsu\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt+32,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
db_printf("wsbh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
db_printf("seb\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
db_printf("seh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_RDHWR)
db_printf("rdhwr\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else
db_printf("Unknown");
break;
case OP_BCOND:
db_printf("%s\t%s,", bcond_name[i.IType.rt],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BLEZ:
case OP_BGTZ:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BEQ:
if (i.IType.rs == 0 && i.IType.rt == 0) {
db_printf("b\t");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
db_printf("%s\t%s,%s,", op_name[i.IType.op],
reg_name[i.IType.rs],
reg_name[i.IType.rt]);
pr_displ:
print_addr(loc + 4 + ((short)i.IType.imm << 2));
bdslot = true;
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc0%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMT:
db_printf("dmtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_MF:
db_printf("mfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMF:
db_printf("dmfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
default:
db_printf("%s", c0_opname[i.FRType.func]);
}
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc1%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MF:
db_printf("mfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CT:
db_printf("ctc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CF:
db_printf("cfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
default:
db_printf("%s.%s\tf%d,f%d,f%d",
cop1_name[i.FRType.func],
fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs, i.FRType.ft);
}
break;
case OP_J:
case OP_JAL:
db_printf("%s\t", op_name[i.JType.op]);
print_addr((loc & 0xFFFFFFFFF0000000) | (i.JType.target << 2));
bdslot = true;
break;
case OP_LWC1:
case OP_SWC1:
db_printf("%s\tf%d,", op_name[i.IType.op],
i.IType.rt);
goto loadstore;
case OP_LB:
case OP_LH:
case OP_LW:
case OP_LD:
case OP_LBU:
case OP_LHU:
case OP_LWU:
case OP_SB:
case OP_SH:
case OP_SW:
case OP_SD:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rt]);
loadstore:
db_printf("%d(%s)", (short)i.IType.imm,
reg_name[i.IType.rs]);
break;
case OP_ORI:
case OP_XORI:
if (i.IType.rs == 0) {
db_printf("li\t%s,0x%x",
reg_name[i.IType.rt],
i.IType.imm);
break;
}
/* FALLTHROUGH */
case OP_ANDI:
db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
i.IType.imm);
break;
case OP_AUI:
if (i.IType.rs == 0) {
db_printf("lui\t%s,0x%x", reg_name[i.IType.rt],
i.IType.imm);
} else {
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt], reg_name[i.IType.rs],
(short)i.IType.imm);
}
break;
case OP_ADDIU:
case OP_DADDIU:
if (i.IType.rs == 0) {
db_printf("li\t%s,%d",
reg_name[i.IType.rt],
(short)i.IType.imm);
break;
}
/* FALLTHROUGH */
default:
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
(short)i.IType.imm);
}
// db_printf("\n");
// if (bdslot) {
// db_printf(" bd: ");
// mips_disassem(loc+4);
// return (loc + 8);
// }
return (loc + 4);
}
static void
print_addr(db_addr_t loc)
{
db_printf("0x%08lx", loc);
}
static void db_printf(const char* fmt, ...)
{
int cnt;
va_list argp;
va_start(argp, fmt);
if (sprintf_buffer) {
cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
sprintf_buffer += cnt;
sprintf_buf_len -= cnt;
} else {
vprintf(fmt, argp);
}
va_end(argp);
}
/*
* Disassemble instruction at 'loc'.
* Return address of start of next instruction.
* Since this function is used by 'examine' and by 'step'
* "next instruction" does NOT mean the next instruction to
* be executed but the 'linear' next instruction.
*/
db_addr_t
mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
{
u_int32_t instr;
if (alt_dis_format) { // use ARM register names for disassembly
reg_name = &alt_arm_reg_name[0];
}
sprintf_buffer = di_buffer; // quick 'n' dirty printf() vs sprintf()
sprintf_buf_len = 39; // should be passed in
instr = *(u_int32_t *)loc;
return (db_disasm_insn(instr, loc, false));
}

View File

@ -1,56 +0,0 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 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.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#ifndef ANDROID_MIPS_DISASSEM_H
#define ANDROID_MIPS_DISASSEM_H
#include <sys/types.h>
#if __cplusplus
extern "C" {
#endif
/* Prototypes for callable functions */
void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt);
#if __cplusplus
}
#endif
#endif /* !ANDROID_MIPS_DISASSEM_H */

View File

@ -1,592 +0,0 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 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.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include "mips_opcode.h"
// #include <sys/systm.h>
// #include <sys/param.h>
// #include <machine/reg.h>
// #include <machine/cpu.h>
/*#include <machine/param.h>*/
// #include <machine/db_machdep.h>
// #include <ddb/db_interface.h>
// #include <ddb/db_output.h>
// #include <ddb/db_extern.h>
// #include <ddb/db_sym.h>
#define __unused __attribute__((__unused__))
static char *sprintf_buffer;
static int sprintf_buf_len;
typedef uint32_t db_addr_t;
static void db_printf(const char* fmt, ...);
static const char * const op_name[64] = {
/* 0 */ "spec", "bcond","j ", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
/*32 */ "lb ", "lh ", "lwl", "lw ", "lbu", "lhu", "lwr", "lwu",
/*40 */ "sb ", "sh ", "swl", "sw ", "sdl", "sdr", "swr", "cache",
/*48 */ "ll ", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld ",
/*56 */ "sc ", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd "
};
static const char * const spec_name[64] = {
/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
/* 8 */ "jr", "jalr", "movz","movn","syscall","break","spec16","sync",
/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
/*32 */ "add", "addu", "sub", "subu", "and", "or ", "xor", "nor",
/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
};
static const char * const spec2_name[64] = { /* QED RM4650, R5000, etc. */
/* 0x00 */ "madd", "maddu", "mul", "spec3", "msub", "msubu", "rsrv6", "rsrv7",
/* 0x08 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
/* 0x10 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
/* 0x18 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
/* 0x20 */ "clz", "clo", "rsrv", "rsrv", "dclz", "dclo", "rsrv", "rsrv",
/* 0x28 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
/* 0x30 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
/* 0x38 */ "rsrv", "rsrv", "rsrv", "resv", "rsrv", "rsrv", "rsrv", "sdbbp"
};
static const char * const bcond_name[32] = {
/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
};
static const char * const cop1_name[64] = {
/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
"fcmp.ole","fcmp.ule",
/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
"fcmp.le","fcmp.ngt"
};
static const char * const fmt_name[16] = {
"s", "d", "e", "fmt3",
"w", "fmt5", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
#if defined(__mips_n32) || defined(__mips_n64)
static char * const reg_name[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
#else
static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM code
"zero", "at", "r0", "r1", "r2", "r3", "r4", "r5",
"r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13",
"r14", "r15", "at2", "cmp", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char * mips_reg_name[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char ** reg_name = &mips_reg_name[0];
#endif /* __mips_n32 || __mips_n64 */
static const char * const c0_opname[64] = {
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
"eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
};
static const char * const c0_reg[32] = {
"index", "random", "tlblo0", "tlblo1",
"context", "pagemask", "wired", "cp0r7",
"badvaddr", "count", "tlbhi", "compare",
"status", "cause", "epc", "prid",
"config", "lladdr", "watchlo", "watchhi",
"xcontext", "cp0r21", "cp0r22", "debug",
"depc", "perfcnt", "ecc", "cacheerr",
"taglo", "taghi", "errepc", "desave"
};
static void print_addr(db_addr_t);
db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
/*
* Disassemble instruction 'insn' nominally at 'loc'.
* 'loc' may in fact contain a breakpoint instruction.
*/
static db_addr_t
db_disasm_insn(int insn, db_addr_t loc, bool altfmt __unused)
{
bool bdslot = false;
InstFmt i;
i.word = insn;
switch (i.JType.op) {
case OP_SPECIAL:
if (i.word == 0) {
db_printf("nop");
break;
}
if (i.word == 0x0080) {
db_printf("NIY");
break;
}
if (i.word == 0x00c0) {
db_printf("NOT IMPL");
break;
}
/* Special cases --------------------------------------------------
* "addu" is a "move" only in 32-bit mode. What's the correct
* answer - never decode addu/daddu as "move"?
*/
if ( (i.RType.func == OP_ADDU && i.RType.rt == 0) ||
(i.RType.func == OP_OR && i.RType.rt == 0) ) {
db_printf("move\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
}
// mips32r2, rotr & rotrv
if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
reg_name[i.RType.rt], i.RType.shamt);
break;
}
if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rt], reg_name[i.RType.rs]);
break;
}
db_printf("%s", spec_name[i.RType.func]);
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
case OP_SRA:
case OP_DSLL:
case OP_DSRL:
case OP_DSRA:
case OP_DSLL32:
case OP_DSRL32:
case OP_DSRA32:
db_printf("\t%s,%s,%d",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
i.RType.shamt);
break;
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
reg_name[i.RType.rs]);
break;
case OP_MFHI:
case OP_MFLO:
db_printf("\t%s", reg_name[i.RType.rd]);
break;
case OP_JR:
case OP_JALR:
db_printf("\t%s", reg_name[i.RType.rs]);
bdslot = true;
break;
case OP_MTLO:
case OP_MTHI:
db_printf("\t%s", reg_name[i.RType.rs]);
break;
case OP_MULT:
case OP_MULTU:
case OP_DMULT:
case OP_DMULTU:
case OP_DIV:
case OP_DIVU:
case OP_DDIV:
case OP_DDIVU:
db_printf("\t%s,%s",
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
break;
case OP_SYSCALL:
case OP_SYNC:
break;
case OP_BREAK:
db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
break;
default:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
}
break;
case OP_SPECIAL2:
if (i.RType.func == OP_MUL)
db_printf("%s\t%s,%s,%s",
spec2_name[i.RType.func & 0x3f],
reg_name[i.RType.rd],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
else
db_printf("%s\t%s,%s",
spec2_name[i.RType.func & 0x3f],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
break;
case OP_SPECIAL3:
if (i.RType.func == OP_EXT)
db_printf("ext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_INS)
db_printf("ins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
db_printf("wsbh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
db_printf("seb\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
db_printf("seh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else
db_printf("Unknown");
break;
case OP_BCOND:
db_printf("%s\t%s,", bcond_name[i.IType.rt],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BLEZ:
case OP_BLEZL:
case OP_BGTZ:
case OP_BGTZL:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BEQ:
case OP_BEQL:
if (i.IType.rs == 0 && i.IType.rt == 0) {
db_printf("b \t");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
case OP_BNEL:
db_printf("%s\t%s,%s,", op_name[i.IType.op],
reg_name[i.IType.rs],
reg_name[i.IType.rt]);
pr_displ:
print_addr(loc + 4 + ((short)i.IType.imm << 2));
bdslot = true;
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc0%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMT:
db_printf("dmtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_MF:
db_printf("mfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMF:
db_printf("dmfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
default:
db_printf("%s", c0_opname[i.FRType.func]);
}
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc1%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MF:
db_printf("mfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CT:
db_printf("ctc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CF:
db_printf("cfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
default:
db_printf("%s.%s\tf%d,f%d,f%d",
cop1_name[i.FRType.func],
fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs, i.FRType.ft);
}
break;
case OP_J:
case OP_JAL:
db_printf("%s\t", op_name[i.JType.op]);
print_addr((loc & 0xF0000000) | (i.JType.target << 2));
bdslot = true;
break;
case OP_LWC1:
case OP_SWC1:
db_printf("%s\tf%d,", op_name[i.IType.op],
i.IType.rt);
goto loadstore;
case OP_LB:
case OP_LH:
case OP_LW:
case OP_LD:
case OP_LBU:
case OP_LHU:
case OP_LWU:
case OP_SB:
case OP_SH:
case OP_SW:
case OP_SD:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rt]);
loadstore:
db_printf("%d(%s)", (short)i.IType.imm,
reg_name[i.IType.rs]);
break;
case OP_ORI:
case OP_XORI:
if (i.IType.rs == 0) {
db_printf("li\t%s,0x%x",
reg_name[i.IType.rt],
i.IType.imm);
break;
}
/* FALLTHROUGH */
case OP_ANDI:
db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
i.IType.imm);
break;
case OP_LUI:
db_printf("%s\t%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
i.IType.imm);
break;
case OP_CACHE:
db_printf("%s\t0x%x,0x%x(%s)",
op_name[i.IType.op],
i.IType.rt,
i.IType.imm,
reg_name[i.IType.rs]);
break;
case OP_ADDI:
case OP_DADDI:
case OP_ADDIU:
case OP_DADDIU:
if (i.IType.rs == 0) {
db_printf("li\t%s,%d",
reg_name[i.IType.rt],
(short)i.IType.imm);
break;
}
/* FALLTHROUGH */
default:
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
(short)i.IType.imm);
}
// db_printf("\n");
// if (bdslot) {
// db_printf(" bd: ");
// mips_disassem(loc+4);
// return (loc + 8);
// }
return (loc + 4);
}
static void
print_addr(db_addr_t loc)
{
db_printf("0x%08x", loc);
}
static void db_printf(const char* fmt, ...)
{
int cnt;
va_list argp;
va_start(argp, fmt);
if (sprintf_buffer) {
cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
sprintf_buffer += cnt;
sprintf_buf_len -= cnt;
} else {
vprintf(fmt, argp);
}
va_end(argp);
}
/*
* Disassemble instruction at 'loc'.
* Return address of start of next instruction.
* Since this function is used by 'examine' and by 'step'
* "next instruction" does NOT mean the next instruction to
* be executed but the 'linear' next instruction.
*/
db_addr_t
mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
{
u_int32_t instr;
if (alt_dis_format) { // use ARM register names for disassembly
reg_name = &alt_arm_reg_name[0];
}
sprintf_buffer = di_buffer; // quick 'n' dirty printf() vs sprintf()
sprintf_buf_len = 39; // should be passed in
instr = *(u_int32_t *)loc;
return (db_disasm_insn(instr, loc, false));
}

View File

@ -1,66 +0,0 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 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.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#ifndef ANDROID_MIPS_DISASSEM_H
#define ANDROID_MIPS_DISASSEM_H
#include <sys/types.h>
#if __cplusplus
extern "C" {
#endif
// could add an interface like this, but I have not
// typedef struct {
// u_int (*di_readword)(u_int);
// void (*di_printaddr)(u_int);
// void (*di_printf)(const char *, ...);
// } disasm_interface_t;
/* Prototypes for callable functions */
// u_int disasm(const disasm_interface_t *, u_int, int);
void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt);
#if __cplusplus
}
#endif
#endif /* !ANDROID_MIPS_DISASSEM_H */

View File

@ -1,410 +0,0 @@
/* $NetBSD: mips_opcode.h,v 1.12 2005/12/11 12:18:09 christos Exp $ */
/*-
* 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.
*
* @(#)mips_opcode.h 8.1 (Berkeley) 6/10/93
*/
/*
* Define the instruction formats and opcode values for the
* MIPS instruction set.
*/
#include <endian.h>
/*
* Define the instruction formats.
*/
typedef union {
unsigned word;
#if BYTE_ORDER == LITTLE_ENDIAN
struct {
unsigned imm: 16;
unsigned rt: 5;
unsigned rs: 5;
unsigned op: 6;
} IType;
struct {
unsigned target: 26;
unsigned op: 6;
} JType;
struct {
unsigned func: 6;
unsigned shamt: 5;
unsigned rd: 5;
unsigned rt: 5;
unsigned rs: 5;
unsigned op: 6;
} RType;
struct {
unsigned func: 6;
unsigned fd: 5;
unsigned fs: 5;
unsigned ft: 5;
unsigned fmt: 4;
unsigned : 1; /* always '1' */
unsigned op: 6; /* always '0x11' */
} FRType;
#endif
#if BYTE_ORDER == BIG_ENDIAN
struct {
unsigned op: 6;
unsigned rs: 5;
unsigned rt: 5;
unsigned imm: 16;
} IType;
struct {
unsigned op: 6;
unsigned target: 26;
} JType;
struct {
unsigned op: 6;
unsigned rs: 5;
unsigned rt: 5;
unsigned rd: 5;
unsigned shamt: 5;
unsigned func: 6;
} RType;
struct {
unsigned op: 6; /* always '0x11' */
unsigned : 1; /* always '1' */
unsigned fmt: 4;
unsigned ft: 5;
unsigned fs: 5;
unsigned fd: 5;
unsigned func: 6;
} FRType;
#endif
} InstFmt;
/*
* Values for the 'op' field.
*/
#define OP_SPECIAL 000
#define OP_BCOND 001
#define OP_J 002
#define OP_JAL 003
#define OP_BEQ 004
#define OP_BNE 005
#define OP_BLEZ 006
#define OP_BGTZ 007
#if __mips_isa_rev < 6
#define OP_ADDI 010
#else
#define OP_POP10 010
#endif
#define OP_ADDIU 011
#define OP_SLTI 012
#define OP_SLTIU 013
#define OP_ANDI 014
#define OP_ORI 015
#define OP_XORI 016
#if __mips_isa_rev < 6
#define OP_LUI 017
#else
#define OP_AUI 017
#endif
#define OP_COP0 020
#define OP_COP1 021
#define OP_COP2 022
#if __mips_isa_rev < 6
#define OP_COP3 023
#define OP_BEQL 024
#define OP_BNEL 025
#define OP_BLEZL 026
#define OP_BGTZL 027
#define OP_DADDI 030
#else
#define OP_POP26 026
#define OP_POP27 027
#define OP_POP30 030
#endif
#define OP_DADDIU 031
#if __mips_isa_rev < 6
#define OP_LDL 032
#define OP_LDR 033
#define OP_SPECIAL2 034
#else
#define OP_DAUI 035
#endif
#define OP_SPECIAL3 037
#define OP_LB 040
#define OP_LH 041
#if __mips_isa_rev < 6
#define OP_LWL 042
#endif
#define OP_LW 043
#define OP_LBU 044
#define OP_LHU 045
#define OP_LWR 046
#define OP_LHU 045
#if __mips_isa_rev < 6
#define OP_LWR 046
#endif
#define OP_LWU 047
#define OP_SB 050
#define OP_SH 051
#if __mips_isa_rev < 6
#define OP_SWL 052
#endif
#define OP_SW 053
#if __mips_isa_rev < 6
#define OP_SDL 054
#define OP_SDR 055
#define OP_SWR 056
#define OP_CACHE 057
#define OP_LL 060
#define OP_LWC0 OP_LL
#define OP_LWC1 061
#define OP_LWC2 062
#define OP_LWC3 063
#define OP_LLD 064
#else
#define OP_LWC1 061
#define OP_BC 062
#endif
#define OP_LDC1 065
#define OP_LD 067
#if __mips_isa_rev < 6
#define OP_SC 070
#define OP_SWC0 OP_SC
#endif
#define OP_SWC1 071
#if __mips_isa_rev < 6
#define OP_SWC2 072
#define OP_SWC3 073
#define OP_SCD 074
#else
#define OP_BALC 072
#endif
#define OP_SDC1 075
#define OP_SD 077
/*
* Values for the 'func' field when 'op' == OP_SPECIAL.
*/
#define OP_SLL 000
#define OP_SRL 002
#define OP_SRA 003
#define OP_SLLV 004
#define OP_SRLV 006
#define OP_SRAV 007
#if __mips_isa_rev < 6
#define OP_JR 010
#endif
#define OP_JALR 011
#define OP_SYSCALL 014
#define OP_BREAK 015
#define OP_SYNC 017
#if __mips_isa_rev < 6
#define OP_MFHI 020
#define OP_MTHI 021
#define OP_MFLO 022
#define OP_MTLO 023
#else
#define OP_CLZ 020
#define OP_CLO 021
#define OP_DCLZ 022
#define OP_DCLO 023
#endif
#define OP_DSLLV 024
#define OP_DSRLV 026
#define OP_DSRAV 027
#if __mips_isa_rev < 6
#define OP_MULT 030
#define OP_MULTU 031
#define OP_DIV 032
#define OP_DIVU 033
#define OP_DMULT 034
#define OP_DMULTU 035
#define OP_DDIV 036
#define OP_DDIVU 037
#else
#define OP_SOP30 030
#define OP_SOP31 031
#define OP_SOP32 032
#define OP_SOP33 033
#define OP_SOP34 034
#define OP_SOP35 035
#define OP_SOP36 036
#define OP_SOP37 037
#endif
#define OP_ADD 040
#define OP_ADDU 041
#define OP_SUB 042
#define OP_SUBU 043
#define OP_AND 044
#define OP_OR 045
#define OP_XOR 046
#define OP_NOR 047
#define OP_SLT 052
#define OP_SLTU 053
#define OP_DADD 054
#define OP_DADDU 055
#define OP_DSUB 056
#define OP_DSUBU 057
#define OP_TGE 060
#define OP_TGEU 061
#define OP_TLT 062
#define OP_TLTU 063
#define OP_TEQ 064
#define OP_TNE 066
#define OP_DSLL 070
#define OP_DSRL 072
#define OP_DSRA 073
#define OP_DSLL32 074
#define OP_DSRL32 076
#define OP_DSRA32 077
#if __mips_isa_rev < 6
/*
* Values for the 'func' field when 'op' == OP_SPECIAL2.
* OP_SPECIAL2 opcodes are removed in mips32r6
*/
#define OP_MAD 000 /* QED */
#define OP_MADU 001 /* QED */
#define OP_MUL 002 /* QED */
#endif
/*
* Values for the 'func' field when 'op' == OP_SPECIAL3.
*/
#define OP_EXT 000
#define OP_DEXTM 001
#define OP_DEXTU 002
#define OP_DEXT 003
#define OP_INS 004
#define OP_DINSM 005
#define OP_DINSU 006
#define OP_DINS 007
#define OP_BSHFL 040
#define OP_RDHWR 073
/*
* Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL.
*/
#define OP_WSBH 002
#define OP_SEB 020
#define OP_SEH 030
#if __mips_isa_rev == 6
/*
* Values for the 'shamt' field when OP_SOP30.
*/
#define OP_MUL 002
#define OP_MUH 003
#endif
/*
* Values for the 'func' field when 'op' == OP_BCOND.
*/
#define OP_BLTZ 000
#define OP_BGEZ 001
#if __mips_isa_rev < 6
#define OP_BLTZL 002
#define OP_BGEZL 003
#define OP_TGEI 010
#define OP_TGEIU 011
#define OP_TLTI 012
#define OP_TLTIU 013
#define OP_TEQI 014
#define OP_TNEI 016
#define OP_BLTZAL 020
#define OP_BGEZAL 021
#define OP_BLTZALL 022
#define OP_BGEZALL 023
#else
#define OP_NAL 020
#define OP_BAL 021
#endif
/*
* Values for the 'rs' field when 'op' == OP_COPz.
*/
#define OP_MF 000
#define OP_DMF 001
#define OP_MT 004
#define OP_DMT 005
#define OP_BCx 010
#define OP_BCy 014
#define OP_CF 002
#define OP_CT 006
/*
* Values for the 'rt' field when 'op' == OP_COPz.
*/
#define COPz_BC_TF_MASK 0x01
#define COPz_BC_TRUE 0x01
#define COPz_BC_FALSE 0x00
#define COPz_BCL_TF_MASK 0x02
#define COPz_BCL_TRUE 0x02
#define COPz_BCL_FALSE 0x00

File diff suppressed because it is too large Load Diff

View File

@ -1,180 +0,0 @@
/*
* Copyright 2005 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 ANDROID_PIXELFLINGER_SMART_POINTER_H
#define ANDROID_PIXELFLINGER_SMART_POINTER_H
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
// ---------------------------------------------------------------------------
namespace android {
namespace tinyutils {
// ---------------------------------------------------------------------------
#define COMPARE(_op_) \
inline bool operator _op_ (const sp<T>& o) const { \
return m_ptr _op_ o.m_ptr; \
} \
inline bool operator _op_ (const T* o) const { \
return m_ptr _op_ o; \
} \
template<typename U> \
inline bool operator _op_ (const sp<U>& o) const { \
return m_ptr _op_ o.m_ptr; \
} \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
}
// ---------------------------------------------------------------------------
template <typename T>
class sp
{
public:
inline sp() : m_ptr(0) { }
sp(T* other); // NOLINT, implicit
sp(const sp<T>& other);
template<typename U> sp(U* other); // NOLINT, implicit
template<typename U> sp(const sp<U>& other); // NOLINT, implicit
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (U* other);
// Reset
void clear();
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
T* m_ptr;
};
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
if (other) other->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) m_ptr->incStrong(this);
}
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) {
if (other.m_ptr) other.m_ptr->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
m_ptr = other.m_ptr;
return *this;
}
template<typename T>
sp<T>& sp<T>::operator = (T* other)
{
if (other) other->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
m_ptr = other;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other)
{
if (other.m_ptr) other.m_ptr->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
m_ptr = other.m_ptr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
if (other) other->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
m_ptr = other;
return *this;
}
template<typename T>
void sp<T>::clear()
{
if (m_ptr) {
m_ptr->decStrong(this);
m_ptr = 0;
}
}
// ---------------------------------------------------------------------------
} // namespace tinyutils
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_PIXELFLINGER_SMART_POINTER_H

View File

@ -1,77 +0,0 @@
/* libs/pixelflinger/col32cb16blend.S
*
* Copyright (C) 2009 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.
*/
.text
.balign 4
.global scanline_col32cb16blend_arm
//
// This function alpha blends a fixed color into a destination scanline, using
// the formula:
//
// d = s + (((a + (a >> 7)) * d) >> 8)
//
// where d is the destination pixel,
// s is the source color,
// a is the alpha channel of the source color.
//
// r0 = destination buffer pointer
// r1 = color value
// r2 = count
scanline_col32cb16blend_arm:
push {r4-r10, lr} // stack ARM regs
mov r5, r1, lsr #24 // shift down alpha
mov r9, #0xff // create mask
add r5, r5, r5, lsr #7 // add in top bit
rsb r5, r5, #256 // invert alpha
and r10, r1, #0xff // extract red
and r12, r9, r1, lsr #8 // extract green
and r4, r9, r1, lsr #16 // extract blue
mov r10, r10, lsl #5 // prescale red
mov r12, r12, lsl #6 // prescale green
mov r4, r4, lsl #5 // prescale blue
mov r9, r9, lsr #2 // create dest green mask
1:
ldrh r8, [r0] // load dest pixel
subs r2, r2, #1 // decrement loop counter
mov r6, r8, lsr #11 // extract dest red
and r7, r9, r8, lsr #5 // extract dest green
and r8, r8, #0x1f // extract dest blue
smlabb r6, r6, r5, r10 // dest red * alpha + src red
smlabb r7, r7, r5, r12 // dest green * alpha + src green
smlabb r8, r8, r5, r4 // dest blue * alpha + src blue
mov r6, r6, lsr #8 // shift down red
mov r7, r7, lsr #8 // shift down green
mov r6, r6, lsl #11 // shift red into 565
orr r6, r7, lsl #5 // shift green into 565
orr r6, r8, lsr #8 // shift blue into 565
strh r6, [r0], #2 // store pixel to dest, update ptr
bne 1b // if count != 0, loop
pop {r4-r10, pc} // return

View File

@ -1,153 +0,0 @@
/* libs/pixelflinger/col32cb16blend_neon.S
*
* Copyright (C) 2009 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.
*/
.text
.balign 4
.global scanline_col32cb16blend_neon
//
// This function alpha blends a fixed color into a destination scanline, using
// the formula:
//
// d = s + (((a + (a >> 7)) * d) >> 8)
//
// where d is the destination pixel,
// s is the source color,
// a is the alpha channel of the source color.
//
// The NEON implementation processes 16 pixels per iteration. The remaining 0 - 15
// pixels are processed in ARM code.
//
// r0 = destination buffer pointer
// r1 = color pointer
// r2 = count
scanline_col32cb16blend_neon:
push {r4-r11, lr} // stack ARM regs
vmov.u16 q15, #256 // create alpha constant
movs r3, r2, lsr #4 // calc. sixteens iterations
vmov.u16 q14, #0x1f // create blue mask
beq 2f // if r3 == 0, branch to singles
vld4.8 {d0[], d2[], d4[], d6[]}, [r1] // load color into four registers
// split and duplicate them, such that
// d0 = 8 equal red values
// d2 = 8 equal green values
// d4 = 8 equal blue values
// d6 = 8 equal alpha values
vshll.u8 q0, d0, #5 // shift up red and widen
vshll.u8 q1, d2, #6 // shift up green and widen
vshll.u8 q2, d4, #5 // shift up blue and widen
vshr.u8 d7, d6, #7 // extract top bit of alpha
vaddl.u8 q3, d6, d7 // add top bit into alpha
vsub.u16 q3, q15, q3 // invert alpha
1:
// This loop processes 16 pixels per iteration. In the comments, references to
// the first eight pixels are suffixed with "0" (red0, green0, blue0),
// the second eight are suffixed "1".
// q8 = dst red0
// q9 = dst green0
// q10 = dst blue0
// q13 = dst red1
// q12 = dst green1
// q11 = dst blue1
vld1.16 {d20, d21, d22, d23}, [r0] // load 16 dest pixels
vshr.u16 q8, q10, #11 // shift dst red0 to low 5 bits
pld [r0, #63] // preload next dest pixels
vshl.u16 q9, q10, #5 // shift dst green0 to top 6 bits
vand q10, q10, q14 // extract dst blue0
vshr.u16 q9, q9, #10 // shift dst green0 to low 6 bits
vmul.u16 q8, q8, q3 // multiply dst red0 by src alpha
vshl.u16 q12, q11, #5 // shift dst green1 to top 6 bits
vmul.u16 q9, q9, q3 // multiply dst green0 by src alpha
vshr.u16 q13, q11, #11 // shift dst red1 to low 5 bits
vmul.u16 q10, q10, q3 // multiply dst blue0 by src alpha
vshr.u16 q12, q12, #10 // shift dst green1 to low 6 bits
vand q11, q11, q14 // extract dst blue1
vadd.u16 q8, q8, q0 // add src red to dst red0
vmul.u16 q13, q13, q3 // multiply dst red1 by src alpha
vadd.u16 q9, q9, q1 // add src green to dst green0
vmul.u16 q12, q12, q3 // multiply dst green1 by src alpha
vadd.u16 q10, q10, q2 // add src blue to dst blue0
vmul.u16 q11, q11, q3 // multiply dst blue1 by src alpha
vshr.u16 q8, q8, #8 // shift down red0
vadd.u16 q13, q13, q0 // add src red to dst red1
vshr.u16 q9, q9, #8 // shift down green0
vadd.u16 q12, q12, q1 // add src green to dst green1
vshr.u16 q10, q10, #8 // shift down blue0
vadd.u16 q11, q11, q2 // add src blue to dst blue1
vsli.u16 q10, q9, #5 // shift & insert green0 into blue0
vshr.u16 q13, q13, #8 // shift down red1
vsli.u16 q10, q8, #11 // shift & insert red0 into blue0
vshr.u16 q12, q12, #8 // shift down green1
vshr.u16 q11, q11, #8 // shift down blue1
subs r3, r3, #1 // decrement loop counter
vsli.u16 q11, q12, #5 // shift & insert green1 into blue1
vsli.u16 q11, q13, #11 // shift & insert red1 into blue1
vst1.16 {d20, d21, d22, d23}, [r0]! // write 16 pixels back to dst
bne 1b // if count != 0, loop
2:
ands r3, r2, #15 // calc. single iterations
beq 4f // if r3 == 0, exit
ldr r4, [r1] // load source color
mov r5, r4, lsr #24 // shift down alpha
add r5, r5, r5, lsr #7 // add in top bit
rsb r5, r5, #256 // invert alpha
and r11, r4, #0xff // extract red
ubfx r12, r4, #8, #8 // extract green
ubfx r4, r4, #16, #8 // extract blue
mov r11, r11, lsl #5 // prescale red
mov r12, r12, lsl #6 // prescale green
mov r4, r4, lsl #5 // prescale blue
3:
ldrh r8, [r0] // load dest pixel
subs r3, r3, #1 // decrement loop counter
mov r6, r8, lsr #11 // extract dest red
ubfx r7, r8, #5, #6 // extract dest green
and r8, r8, #0x1f // extract dest blue
smlabb r6, r6, r5, r11 // dest red * alpha + src red
smlabb r7, r7, r5, r12 // dest green * alpha + src green
smlabb r8, r8, r5, r4 // dest blue * alpha + src blue
mov r6, r6, lsr #8 // shift down red
mov r7, r7, lsr #8 // shift down green
mov r6, r6, lsl #11 // shift red into 565
orr r6, r7, lsl #5 // shift green into 565
orr r6, r8, lsr #8 // shift blue into 565
strh r6, [r0], #2 // store pixel to dest, update ptr
bne 3b // if count != 0, loop
4:
pop {r4-r11, pc} // return

View File

@ -1,329 +0,0 @@
/* libs/pixelflinger/fixed.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include <private/pixelflinger/ggl_context.h>
#include <private/pixelflinger/ggl_fixed.h>
// ------------------------------------------------------------------------
int32_t gglRecipQNormalized(int32_t x, int* exponent)
{
const int32_t s = x>>31;
uint32_t a = s ? -x : x;
// the result will overflow, so just set it to the biggest/inf value
if (ggl_unlikely(a <= 2LU)) {
*exponent = 0;
return s ? FIXED_MIN : FIXED_MAX;
}
// Newton-Raphson iteration:
// x = r*(2 - a*r)
const int32_t lz = gglClz(a);
a <<= lz; // 0.32
uint32_t r = a;
// note: if a == 0x80000000, this means x was a power-of-2, in this
// case we don't need to compute anything. We get the reciprocal for
// (almost) free.
if (a != 0x80000000) {
r = (0x2E800 << (30-16)) - (r>>(2-1)); // 2.30, r = 2.90625 - 2*a
// 0.32 + 2.30 = 2.62 -> 2.30
// 2.30 + 2.30 = 4.60 -> 2.30
r = (((2LU<<30) - uint32_t((uint64_t(a)*r) >> 32)) * uint64_t(r)) >> 30;
r = (((2LU<<30) - uint32_t((uint64_t(a)*r) >> 32)) * uint64_t(r)) >> 30;
}
// shift right 1-bit to make room for the sign bit
*exponent = 30-lz-1;
r >>= 1;
return s ? -r : r;
}
int32_t gglRecipQ(GGLfixed x, int q)
{
int shift;
x = gglRecipQNormalized(x, &shift);
shift += 16-q;
if (shift > 0)
x += 1L << (shift-1); // rounding
x >>= shift;
return x;
}
// ------------------------------------------------------------------------
static const GGLfixed ggl_sqrt_reciproc_approx_tab[8] = {
// 1/sqrt(x) with x = 1-N/16, N=[8...1]
0x16A09, 0x15555, 0x143D1, 0x134BF, 0x1279A, 0x11C01, 0x111AC, 0x10865
};
GGLfixed gglSqrtRecipx(GGLfixed x)
{
if (x == 0) return FIXED_MAX;
if (x == FIXED_ONE) return x;
const GGLfixed a = x;
const int32_t lz = gglClz(x);
x = ggl_sqrt_reciproc_approx_tab[(a>>(28-lz))&0x7];
const int32_t exp = lz - 16;
if (exp <= 0) x >>= -exp>>1;
else x <<= (exp>>1) + (exp & 1);
if (exp & 1) {
x = gglMulx(x, ggl_sqrt_reciproc_approx_tab[0])>>1;
}
// 2 Newton-Raphson iterations: x = x/2*(3-(a*x)*x)
x = gglMulx((x>>1),(0x30000 - gglMulx(gglMulx(a,x),x)));
x = gglMulx((x>>1),(0x30000 - gglMulx(gglMulx(a,x),x)));
return x;
}
GGLfixed gglSqrtx(GGLfixed a)
{
// Compute a full precision square-root (24 bits accuracy)
GGLfixed r = 0;
GGLfixed bit = 0x800000;
int32_t bshift = 15;
do {
GGLfixed temp = bit + (r<<1);
if (bshift >= 8) temp <<= (bshift-8);
else temp >>= (8-bshift);
if (a >= temp) {
r += bit;
a -= temp;
}
bshift--;
} while (bit>>=1);
return r;
}
// ------------------------------------------------------------------------
static const GGLfixed ggl_log_approx_tab[] = {
// -ln(x)/ln(2) with x = N/16, N=[8...16]
0xFFFF, 0xd47f, 0xad96, 0x8a62, 0x6a3f, 0x4caf, 0x3151, 0x17d6, 0x0000
};
static const GGLfixed ggl_alog_approx_tab[] = { // domain [0 - 1.0]
0xffff, 0xeac0, 0xd744, 0xc567, 0xb504, 0xa5fe, 0x9837, 0x8b95, 0x8000
};
GGLfixed gglPowx(GGLfixed x, GGLfixed y)
{
// prerequisite: 0 <= x <= 1, and y >=0
// pow(x,y) = 2^(y*log2(x))
// = 2^(y*log2(x*(2^exp)*(2^-exp))))
// = 2^(y*(log2(X)-exp))
// = 2^(log2(X)*y - y*exp)
// = 2^( - (-log2(X)*y + y*exp) )
int32_t exp = gglClz(x) - 16;
GGLfixed f = x << exp;
x = (f & 0x0FFF)<<4;
f = (f >> 12) & 0x7;
GGLfixed p = gglMulAddx(
ggl_log_approx_tab[f+1] - ggl_log_approx_tab[f], x,
ggl_log_approx_tab[f]);
p = gglMulAddx(p, y, y*exp);
exp = gglFixedToIntFloor(p);
if (exp < 31) {
p = gglFracx(p);
x = (p & 0x1FFF)<<3;
p >>= 13;
p = gglMulAddx(
ggl_alog_approx_tab[p+1] - ggl_alog_approx_tab[p], x,
ggl_alog_approx_tab[p]);
p >>= exp;
} else {
p = 0;
}
return p;
// ( powf((a*65536.0f), (b*65536.0f)) ) * 65536.0f;
}
// ------------------------------------------------------------------------
int32_t gglDivQ(GGLfixed n, GGLfixed d, int32_t i)
{
//int32_t r =int32_t((int64_t(n)<<i)/d);
const int32_t ds = n^d;
if (n<0) n = -n;
if (d<0) d = -d;
int nd = gglClz(d) - gglClz(n);
i += nd + 1;
if (nd > 0) d <<= nd;
else n <<= -nd;
uint32_t q = 0;
int j = i & 7;
i >>= 3;
// gcc deals with the code below pretty well.
// we get 3.75 cycles per bit in the main loop
// and 8 cycles per bit in the termination loop
if (ggl_likely(i)) {
n -= d;
do {
q <<= 8;
if (n>=0) q |= 128;
else n += d;
n = n*2 - d;
if (n>=0) q |= 64;
else n += d;
n = n*2 - d;
if (n>=0) q |= 32;
else n += d;
n = n*2 - d;
if (n>=0) q |= 16;
else n += d;
n = n*2 - d;
if (n>=0) q |= 8;
else n += d;
n = n*2 - d;
if (n>=0) q |= 4;
else n += d;
n = n*2 - d;
if (n>=0) q |= 2;
else n += d;
n = n*2 - d;
if (n>=0) q |= 1;
else n += d;
if (--i == 0)
goto finish;
n = n*2 - d;
} while(true);
do {
q <<= 1;
n = n*2 - d;
if (n>=0) q |= 1;
else n += d;
finish: ;
} while (j--);
return (ds<0) ? -q : q;
}
n -= d;
if (n>=0) q |= 1;
else n += d;
j--;
goto finish;
}
// ------------------------------------------------------------------------
// assumes that the int32_t values of a, b, and c are all positive
// use when both a and b are larger than c
template <typename T>
static inline void swap(T& a, T& b) {
T t(a);
a = b;
b = t;
}
static __attribute__((noinline))
int32_t slow_muldiv(uint32_t a, uint32_t b, uint32_t c)
{
// first we compute a*b as a 64-bit integer
// (GCC generates umull with the code below)
uint64_t ab = uint64_t(a)*b;
uint32_t hi = ab>>32;
uint32_t lo = ab;
uint32_t result;
// now perform the division
if (hi >= c) {
overflow:
result = 0x7fffffff; // basic overflow
} else if (hi == 0) {
result = lo/c; // note: c can't be 0
if ((result >> 31) != 0) // result must fit in 31 bits
goto overflow;
} else {
uint32_t r = hi;
int bits = 31;
result = 0;
do {
r = (r << 1) | (lo >> 31);
lo <<= 1;
result <<= 1;
if (r >= c) {
r -= c;
result |= 1;
}
} while (bits--);
}
return int32_t(result);
}
// assumes a >= 0 and c >= b >= 0
static inline
int32_t quick_muldiv(int32_t a, int32_t b, int32_t c)
{
int32_t r = 0, q = 0, i;
int leading = gglClz(a);
i = 32 - leading;
a <<= leading;
do {
r <<= 1;
if (a < 0)
r += b;
a <<= 1;
q <<= 1;
if (r >= c) {
r -= c;
q++;
}
asm(""::); // gcc generates better code this way
if (r >= c) {
r -= c;
q++;
}
}
while (--i);
return q;
}
// this function computes a*b/c with 64-bit intermediate accuracy
// overflows (e.g. division by 0) are handled and return INT_MAX
int32_t gglMulDivi(int32_t a, int32_t b, int32_t c)
{
int32_t result;
int32_t sign = a^b^c;
if (a < 0) a = -a;
if (b < 0) b = -b;
if (c < 0) c = -c;
if (a < b) {
swap(a, b);
}
if (b <= c) result = quick_muldiv(a, b, c);
else result = slow_muldiv((uint32_t)a, (uint32_t)b, (uint32_t)c);
if (sign < 0)
result = -result;
return result;
}

View File

@ -1,76 +0,0 @@
/* libs/pixelflinger/format.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include <pixelflinger/format.h>
namespace android {
static GGLFormat const gPixelFormatInfos[] =
{ // Alpha Red Green Blue
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_8888
{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGBX_8888
{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_888
{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_565
{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_RGBA }, // PIXEL_FORMAT_BGRA_8888
{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_5551
{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_4444
{ 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_ALPHA}, // PIXEL_FORMAT_A8
{ 1, 8, {{ 0, 0, 8, 0, 8, 0, 8, 0 }}, GGL_LUMINANCE},//PIXEL_FORMAT_L8
{ 2, 16, {{16, 8, 8, 0, 8, 0, 8, 0 }}, GGL_LUMINANCE_ALPHA},// PIXEL_FORMAT_LA_88
{ 1, 8, {{ 0, 0, 8, 5, 5, 2, 2, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_332
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 2, 16, {{ 0, 0, 16, 0, 0, 0, 0, 0 }}, GGL_DEPTH_COMPONENT},
{ 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX },
{ 4, 24, {{ 0, 0, 24, 0, 0, 0, 0, 0 }}, GGL_DEPTH_COMPONENT},
{ 4, 8, {{ 32,24, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX },
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
};
}; // namespace android
const GGLFormat* gglGetPixelFormatTable(size_t* numEntries)
{
if (numEntries) {
*numEntries = sizeof(android::gPixelFormatInfos)/sizeof(GGLFormat);
}
return android::gPixelFormatInfos;
}

View File

@ -1,136 +0,0 @@
/*
* Copyright (C) 2005 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 ANDROID_PIXELFLINGER_FORMAT_H
#define ANDROID_PIXELFLINGER_FORMAT_H
#include <stdint.h>
#include <sys/types.h>
enum GGLPixelFormat {
// these constants need to match those
// in graphics/PixelFormat.java, ui/PixelFormat.h, BlitHardware.h
GGL_PIXEL_FORMAT_UNKNOWN = 0,
GGL_PIXEL_FORMAT_NONE = 0,
GGL_PIXEL_FORMAT_RGBA_8888 = 1, // 4x8-bit ARGB
GGL_PIXEL_FORMAT_RGBX_8888 = 2, // 3x8-bit RGB stored in 32-bit chunks
GGL_PIXEL_FORMAT_RGB_888 = 3, // 3x8-bit RGB
GGL_PIXEL_FORMAT_RGB_565 = 4, // 16-bit RGB
GGL_PIXEL_FORMAT_BGRA_8888 = 5, // 4x8-bit BGRA
GGL_PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit RGBA
GGL_PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit RGBA
GGL_PIXEL_FORMAT_A_8 = 8, // 8-bit A
GGL_PIXEL_FORMAT_L_8 = 9, // 8-bit L (R=G=B = L)
GGL_PIXEL_FORMAT_LA_88 = 0xA, // 16-bit LA
GGL_PIXEL_FORMAT_RGB_332 = 0xB, // 8-bit RGB (non paletted)
// reserved range. don't use.
GGL_PIXEL_FORMAT_RESERVED_10 = 0x10,
GGL_PIXEL_FORMAT_RESERVED_11 = 0x11,
GGL_PIXEL_FORMAT_RESERVED_12 = 0x12,
GGL_PIXEL_FORMAT_RESERVED_13 = 0x13,
GGL_PIXEL_FORMAT_RESERVED_14 = 0x14,
GGL_PIXEL_FORMAT_RESERVED_15 = 0x15,
GGL_PIXEL_FORMAT_RESERVED_16 = 0x16,
GGL_PIXEL_FORMAT_RESERVED_17 = 0x17,
// reserved/special formats
GGL_PIXEL_FORMAT_Z_16 = 0x18,
GGL_PIXEL_FORMAT_S_8 = 0x19,
GGL_PIXEL_FORMAT_SZ_24 = 0x1A,
GGL_PIXEL_FORMAT_SZ_8 = 0x1B,
// reserved range. don't use.
GGL_PIXEL_FORMAT_RESERVED_20 = 0x20,
GGL_PIXEL_FORMAT_RESERVED_21 = 0x21,
};
enum GGLFormatComponents {
GGL_STENCIL_INDEX = 0x1901,
GGL_DEPTH_COMPONENT = 0x1902,
GGL_ALPHA = 0x1906,
GGL_RGB = 0x1907,
GGL_RGBA = 0x1908,
GGL_LUMINANCE = 0x1909,
GGL_LUMINANCE_ALPHA = 0x190A,
};
enum GGLFormatComponentIndex {
GGL_INDEX_ALPHA = 0,
GGL_INDEX_RED = 1,
GGL_INDEX_GREEN = 2,
GGL_INDEX_BLUE = 3,
GGL_INDEX_STENCIL = 0,
GGL_INDEX_DEPTH = 1,
GGL_INDEX_Y = 0,
GGL_INDEX_CB = 1,
GGL_INDEX_CR = 2,
};
typedef struct GGLFormat {
#ifdef __cplusplus
enum {
ALPHA = GGL_INDEX_ALPHA,
RED = GGL_INDEX_RED,
GREEN = GGL_INDEX_GREEN,
BLUE = GGL_INDEX_BLUE,
STENCIL = GGL_INDEX_STENCIL,
DEPTH = GGL_INDEX_DEPTH,
LUMA = GGL_INDEX_Y,
CHROMAB = GGL_INDEX_CB,
CHROMAR = GGL_INDEX_CR,
};
inline uint32_t mask(int i) const {
return ((1<<(c[i].h-c[i].l))-1)<<c[i].l;
}
inline uint32_t bits(int i) const {
return c[i].h - c[i].l;
}
#endif
uint8_t size; // bytes per pixel
uint8_t bitsPerPixel;
union {
struct {
uint8_t ah; // alpha high bit position + 1
uint8_t al; // alpha low bit position
uint8_t rh; // red high bit position + 1
uint8_t rl; // red low bit position
uint8_t gh; // green high bit position + 1
uint8_t gl; // green low bit position
uint8_t bh; // blue high bit position + 1
uint8_t bl; // blue low bit position
};
struct {
uint8_t h;
uint8_t l;
} __attribute__((__packed__)) c[4];
} __attribute__((__packed__));
uint16_t components; // GGLFormatComponents
} GGLFormat;
#ifdef __cplusplus
extern "C" const GGLFormat* gglGetPixelFormatTable(size_t* numEntries = 0);
#else
const GGLFormat* gglGetPixelFormatTable(size_t* numEntries);
#endif
// ----------------------------------------------------------------------------
#endif // ANDROID_PIXELFLINGER_FORMAT_H

View File

@ -1,330 +0,0 @@
/*
* Copyright (C) 2007 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 ANDROID_PIXELFLINGER_H
#define ANDROID_PIXELFLINGER_H
#include <stdint.h>
#include <sys/types.h>
#include <pixelflinger/format.h>
// GGL types
typedef int8_t GGLbyte; // b
typedef int16_t GGLshort; // s
typedef int32_t GGLint; // i
typedef ssize_t GGLsizei; // i
typedef int32_t GGLfixed; // x
typedef int32_t GGLclampx; // x
typedef float GGLfloat; // f
typedef float GGLclampf; // f
typedef double GGLdouble; // d
typedef double GGLclampd; // d
typedef uint8_t GGLubyte; // ub
typedef uint8_t GGLboolean; // ub
typedef uint16_t GGLushort; // us
typedef uint32_t GGLuint; // ui
typedef unsigned int GGLenum; // ui
typedef unsigned int GGLbitfield; // ui
typedef void GGLvoid;
typedef int32_t GGLfixed32;
typedef int32_t GGLcolor;
typedef int32_t GGLcoord;
// ----------------------------------------------------------------------------
#define GGL_MAX_VIEWPORT_DIMS 4096
#define GGL_MAX_TEXTURE_SIZE 4096
#define GGL_MAX_ALIASED_POINT_SIZE 0x7FFFFFF
#define GGL_MAX_SMOOTH_POINT_SIZE 2048
#define GGL_MAX_SMOOTH_LINE_WIDTH 2048
// ----------------------------------------------------------------------------
// All these names are compatible with their OpenGL equivalents
// some of them are listed only for completeness
enum GGLNames {
GGL_FALSE = 0,
GGL_TRUE = 1,
// enable/disable
GGL_SCISSOR_TEST = 0x0C11,
GGL_TEXTURE_2D = 0x0DE1,
GGL_ALPHA_TEST = 0x0BC0,
GGL_BLEND = 0x0BE2,
GGL_COLOR_LOGIC_OP = 0x0BF2,
GGL_DITHER = 0x0BD0,
GGL_STENCIL_TEST = 0x0B90,
GGL_DEPTH_TEST = 0x0B71,
GGL_AA = 0x80000001,
GGL_W_LERP = 0x80000004,
GGL_POINT_SMOOTH_NICE = 0x80000005,
// buffers, pixel drawing/reading
GGL_COLOR = 0x1800,
// fog
GGL_FOG = 0x0B60,
// shade model
GGL_FLAT = 0x1D00,
GGL_SMOOTH = 0x1D01,
// Texture parameter name
GGL_TEXTURE_MIN_FILTER = 0x2801,
GGL_TEXTURE_MAG_FILTER = 0x2800,
GGL_TEXTURE_WRAP_S = 0x2802,
GGL_TEXTURE_WRAP_T = 0x2803,
GGL_TEXTURE_WRAP_R = 0x2804,
// Texture Filter
GGL_NEAREST = 0x2600,
GGL_LINEAR = 0x2601,
GGL_NEAREST_MIPMAP_NEAREST = 0x2700,
GGL_LINEAR_MIPMAP_NEAREST = 0x2701,
GGL_NEAREST_MIPMAP_LINEAR = 0x2702,
GGL_LINEAR_MIPMAP_LINEAR = 0x2703,
// Texture Wrap Mode
GGL_CLAMP = 0x2900,
GGL_REPEAT = 0x2901,
GGL_CLAMP_TO_EDGE = 0x812F,
// Texture Env Mode
GGL_REPLACE = 0x1E01,
GGL_MODULATE = 0x2100,
GGL_DECAL = 0x2101,
GGL_ADD = 0x0104,
// Texture Env Parameter
GGL_TEXTURE_ENV_MODE = 0x2200,
GGL_TEXTURE_ENV_COLOR = 0x2201,
// Texture Env Target
GGL_TEXTURE_ENV = 0x2300,
// Texture coord generation
GGL_TEXTURE_GEN_MODE = 0x2500,
GGL_S = 0x2000,
GGL_T = 0x2001,
GGL_R = 0x2002,
GGL_Q = 0x2003,
GGL_ONE_TO_ONE = 0x80000002,
GGL_AUTOMATIC = 0x80000003,
// AlphaFunction
GGL_NEVER = 0x0200,
GGL_LESS = 0x0201,
GGL_EQUAL = 0x0202,
GGL_LEQUAL = 0x0203,
GGL_GREATER = 0x0204,
GGL_NOTEQUAL = 0x0205,
GGL_GEQUAL = 0x0206,
GGL_ALWAYS = 0x0207,
// LogicOp
GGL_CLEAR = 0x1500, // 0
GGL_AND = 0x1501, // s & d
GGL_AND_REVERSE = 0x1502, // s & ~d
GGL_COPY = 0x1503, // s
GGL_AND_INVERTED = 0x1504, // ~s & d
GGL_NOOP = 0x1505, // d
GGL_XOR = 0x1506, // s ^ d
GGL_OR = 0x1507, // s | d
GGL_NOR = 0x1508, // ~(s | d)
GGL_EQUIV = 0x1509, // ~(s ^ d)
GGL_INVERT = 0x150A, // ~d
GGL_OR_REVERSE = 0x150B, // s | ~d
GGL_COPY_INVERTED = 0x150C, // ~s
GGL_OR_INVERTED = 0x150D, // ~s | d
GGL_NAND = 0x150E, // ~(s & d)
GGL_SET = 0x150F, // 1
// blending equation & function
GGL_ZERO = 0, // SD
GGL_ONE = 1, // SD
GGL_SRC_COLOR = 0x0300, // D
GGL_ONE_MINUS_SRC_COLOR = 0x0301, // D
GGL_SRC_ALPHA = 0x0302, // SD
GGL_ONE_MINUS_SRC_ALPHA = 0x0303, // SD
GGL_DST_ALPHA = 0x0304, // SD
GGL_ONE_MINUS_DST_ALPHA = 0x0305, // SD
GGL_DST_COLOR = 0x0306, // S
GGL_ONE_MINUS_DST_COLOR = 0x0307, // S
GGL_SRC_ALPHA_SATURATE = 0x0308, // S
// clear bits
GGL_DEPTH_BUFFER_BIT = 0x00000100,
GGL_STENCIL_BUFFER_BIT = 0x00000400,
GGL_COLOR_BUFFER_BIT = 0x00004000,
// errors
GGL_NO_ERROR = 0,
GGL_INVALID_ENUM = 0x0500,
GGL_INVALID_VALUE = 0x0501,
GGL_INVALID_OPERATION = 0x0502,
GGL_STACK_OVERFLOW = 0x0503,
GGL_STACK_UNDERFLOW = 0x0504,
GGL_OUT_OF_MEMORY = 0x0505
};
// ----------------------------------------------------------------------------
typedef struct {
GGLsizei version; // always set to sizeof(GGLSurface)
GGLuint width; // width in pixels
GGLuint height; // height in pixels
GGLint stride; // stride in pixels
GGLubyte* data; // pointer to the bits
GGLubyte format; // pixel format
GGLubyte rfu[3]; // must be zero
// these values are dependent on the used format
union {
GGLint compressedFormat;
GGLint vstride;
};
void* reserved;
} GGLSurface;
typedef struct {
// immediate rendering
void (*pointx)(void *con, const GGLcoord* v, GGLcoord r);
void (*linex)(void *con,
const GGLcoord* v0, const GGLcoord* v1, GGLcoord width);
void (*recti)(void* c, GGLint l, GGLint t, GGLint r, GGLint b);
void (*trianglex)(void* c,
GGLcoord const* v0, GGLcoord const* v1, GGLcoord const* v2);
// scissor
void (*scissor)(void* c, GGLint x, GGLint y, GGLsizei width, GGLsizei height);
// Set the textures and color buffers
void (*activeTexture)(void* c, GGLuint tmu);
void (*bindTexture)(void* c, const GGLSurface* surface);
void (*colorBuffer)(void* c, const GGLSurface* surface);
void (*readBuffer)(void* c, const GGLSurface* surface);
void (*depthBuffer)(void* c, const GGLSurface* surface);
void (*bindTextureLod)(void* c, GGLuint tmu, const GGLSurface* surface);
// enable/disable features
void (*enable)(void* c, GGLenum name);
void (*disable)(void* c, GGLenum name);
void (*enableDisable)(void* c, GGLenum name, GGLboolean en);
// specify the fragment's color
void (*shadeModel)(void* c, GGLenum mode);
void (*color4xv)(void* c, const GGLclampx* color);
// specify color iterators (16.16)
void (*colorGrad12xv)(void* c, const GGLcolor* grad);
// specify Z coordinate iterators (0.32)
void (*zGrad3xv)(void* c, const GGLfixed32* grad);
// specify W coordinate iterators (16.16)
void (*wGrad3xv)(void* c, const GGLfixed* grad);
// specify fog iterator & color (16.16)
void (*fogGrad3xv)(void* c, const GGLfixed* grad);
void (*fogColor3xv)(void* c, const GGLclampx* color);
// specify blending parameters
void (*blendFunc)(void* c, GGLenum src, GGLenum dst);
void (*blendFuncSeparate)(void* c, GGLenum src, GGLenum dst,
GGLenum srcAlpha, GGLenum dstAplha);
// texture environnement (REPLACE / MODULATE / DECAL / BLEND)
void (*texEnvi)(void* c, GGLenum target,
GGLenum pname,
GGLint param);
void (*texEnvxv)(void* c, GGLenum target,
GGLenum pname, const GGLfixed* params);
// texture parameters (Wrapping, filter)
void (*texParameteri)(void* c, GGLenum target,
GGLenum pname,
GGLint param);
// texture iterators (16.16)
void (*texCoord2i)(void* c, GGLint s, GGLint t);
void (*texCoord2x)(void* c, GGLfixed s, GGLfixed t);
// s, dsdx, dsdy, scale, t, dtdx, dtdy, tscale
// This api uses block floating-point for S and T texture coordinates.
// All values are given in 16.16, scaled by 'scale'. In other words,
// set scale to 0, for 16.16 values.
void (*texCoordGradScale8xv)(void* c, GGLint tmu, const int32_t* grad8);
void (*texGeni)(void* c, GGLenum coord, GGLenum pname, GGLint param);
// masking
void (*colorMask)(void* c, GGLboolean red,
GGLboolean green,
GGLboolean blue,
GGLboolean alpha);
void (*depthMask)(void* c, GGLboolean flag);
void (*stencilMask)(void* c, GGLuint mask);
// alpha func
void (*alphaFuncx)(void* c, GGLenum func, GGLclampx ref);
// depth func
void (*depthFunc)(void* c, GGLenum func);
// logic op
void (*logicOp)(void* c, GGLenum opcode);
// clear
void (*clear)(void* c, GGLbitfield mask);
void (*clearColorx)(void* c,
GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a);
void (*clearDepthx)(void* c, GGLclampx depth);
void (*clearStencil)(void* c, GGLint s);
// framebuffer operations
void (*copyPixels)(void* c, GGLint x, GGLint y,
GGLsizei width, GGLsizei height, GGLenum type);
void (*rasterPos2x)(void* c, GGLfixed x, GGLfixed y);
void (*rasterPos2i)(void* c, GGLint x, GGLint y);
} GGLContext;
// ----------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
// construct / destroy the context
ssize_t gglInit(GGLContext** context);
ssize_t gglUninit(GGLContext* context);
GGLint gglBitBlit(
GGLContext* c,
int tmu,
GGLint crop[4],
GGLint where[4]);
#ifdef __cplusplus
};
#endif
// ----------------------------------------------------------------------------
#endif // ANDROID_PIXELFLINGER_H

View File

@ -1,565 +0,0 @@
/*
* Copyright (C) 2006 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 ANDROID_GGL_CONTEXT_H
#define ANDROID_GGL_CONTEXT_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <endian.h>
#include <pixelflinger/pixelflinger.h>
#include <private/pixelflinger/ggl_fixed.h>
namespace android {
// ----------------------------------------------------------------------------
#if BYTE_ORDER == LITTLE_ENDIAN
inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
return v;
}
inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
return v;
}
#else
inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
#if defined(__mips__) && __mips_isa_rev>=2
uint32_t r;
__asm__("wsbh %0, %1;"
"rotr %0, %0, 16"
: "=r" (r)
: "r" (v)
);
return r;
#else
return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
#endif
}
inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
#if defined(__mips__) && __mips_isa_rev>=2
uint32_t r;
__asm__("wsbh %0, %1;"
"rotr %0, %0, 16"
: "=r" (r)
: "r" (v)
);
return r;
#else
return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00);
#endif
}
#endif
// ----------------------------------------------------------------------------
const int GGL_DITHER_BITS = 6; // dither weights stored on 6 bits
const int GGL_DITHER_ORDER_SHIFT= 3;
const int GGL_DITHER_ORDER = (1<<GGL_DITHER_ORDER_SHIFT);
const int GGL_DITHER_SIZE = GGL_DITHER_ORDER * GGL_DITHER_ORDER;
const int GGL_DITHER_MASK = GGL_DITHER_ORDER-1;
// ----------------------------------------------------------------------------
const int GGL_SUBPIXEL_BITS = 4;
// TRI_FRACTION_BITS defines the number of bits we want to use
// for the sub-pixel coordinates during the edge stepping, the
// value shouldn't be more than 7, or bad things are going to
// happen when drawing large triangles (8 doesn't work because
// 32 bit muls will loose the sign bit)
#define TRI_FRACTION_BITS (GGL_SUBPIXEL_BITS)
#define TRI_ONE (1 << TRI_FRACTION_BITS)
#define TRI_HALF (1 << (TRI_FRACTION_BITS-1))
#define TRI_FROM_INT(x) ((x) << TRI_FRACTION_BITS)
#define TRI_FRAC(x) ((x) & (TRI_ONE-1))
#define TRI_FLOOR(x) ((x) & ~(TRI_ONE-1))
#define TRI_CEIL(x) (((x) + (TRI_ONE-1)) & ~(TRI_ONE-1))
#define TRI_ROUND(x) (((x) + TRI_HALF ) & ~(TRI_ONE-1))
#define TRI_ROUDNING (1 << (16 - TRI_FRACTION_BITS - 1))
#define TRI_FROM_FIXED(x) (((x)+TRI_ROUDNING) >> (16-TRI_FRACTION_BITS))
#define TRI_SNAP_NEXT_HALF(x) (TRI_CEIL((x)+TRI_HALF) - TRI_HALF)
#define TRI_SNAP_PREV_HALF(x) (TRI_CEIL((x)-TRI_HALF) - TRI_HALF)
// ----------------------------------------------------------------------------
const int GGL_COLOR_BITS = 24;
// To maintain 8-bits color chanels, with a maximum GGLSurface
// size of 4096 and GGL_SUBPIXEL_BITS=4, we need 8 + 12 + 4 = 24 bits
// for encoding the color iterators
inline GGLcolor gglFixedToIteratedColor(GGLfixed c) {
return (c << 8) - c;
}
// ----------------------------------------------------------------------------
template<bool> struct CTA;
template<> struct CTA<true> { };
#define GGL_CONTEXT(con, c) context_t *(con) = static_cast<context_t *>(c) /* NOLINT */
#define GGL_OFFSETOF(field) uintptr_t(&(((context_t*)0)->field))
#define GGL_INIT_PROC(p, f) p.f = ggl_ ## f;
#define GGL_BETWEEN(x, L, H) (uint32_t((x)-(L)) <= ((H)-(L)))
#define ggl_likely(x) __builtin_expect(!!(x), 1)
#define ggl_unlikely(x) __builtin_expect(!!(x), 0)
const int GGL_TEXTURE_UNIT_COUNT = 2;
const int GGL_TMU_STATE = 0x00000001;
const int GGL_CB_STATE = 0x00000002;
const int GGL_PIXEL_PIPELINE_STATE = 0x00000004;
// ----------------------------------------------------------------------------
#define GGL_RESERVE_NEEDS(name, l, s) \
const uint32_t GGL_NEEDS_##name##_MASK = (((1LU<<(s))-1)<<(l)); \
const uint32_t GGL_NEEDS_##name##_SHIFT = (l);
#define GGL_BUILD_NEEDS(val, name) \
(((val)<<(GGL_NEEDS_##name##_SHIFT)) & GGL_NEEDS_##name##_MASK)
#define GGL_READ_NEEDS(name, n) \
(uint32_t((n) & GGL_NEEDS_##name##_MASK) >> GGL_NEEDS_##name##_SHIFT)
#define GGL_NEED_MASK(name) (uint32_t(GGL_NEEDS_##name##_MASK))
#define GGL_NEED(name, val) GGL_BUILD_NEEDS(val, name)
GGL_RESERVE_NEEDS( CB_FORMAT, 0, 6 )
GGL_RESERVE_NEEDS( SHADE, 6, 1 )
GGL_RESERVE_NEEDS( W, 7, 1 )
GGL_RESERVE_NEEDS( BLEND_SRC, 8, 4 )
GGL_RESERVE_NEEDS( BLEND_DST, 12, 4 )
GGL_RESERVE_NEEDS( BLEND_SRCA, 16, 4 )
GGL_RESERVE_NEEDS( BLEND_DSTA, 20, 4 )
GGL_RESERVE_NEEDS( LOGIC_OP, 24, 4 )
GGL_RESERVE_NEEDS( MASK_ARGB, 28, 4 )
GGL_RESERVE_NEEDS( P_ALPHA_TEST, 0, 3 )
GGL_RESERVE_NEEDS( P_AA, 3, 1 )
GGL_RESERVE_NEEDS( P_DEPTH_TEST, 4, 3 )
GGL_RESERVE_NEEDS( P_MASK_Z, 7, 1 )
GGL_RESERVE_NEEDS( P_DITHER, 8, 1 )
GGL_RESERVE_NEEDS( P_FOG, 9, 1 )
GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 )
GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 )
GGL_RESERVE_NEEDS( T_RESERVED0, 6, 1 )
GGL_RESERVE_NEEDS( T_POT, 7, 1 )
GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 )
GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 )
GGL_RESERVE_NEEDS( T_ENV, 12, 3 )
GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 )
const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE = 0;
const int GGL_NEEDS_WRAP_REPEAT = 1;
const int GGL_NEEDS_WRAP_11 = 2;
inline uint32_t ggl_wrap_to_needs(uint32_t e) {
switch (e) {
case GGL_CLAMP: return GGL_NEEDS_WRAP_CLAMP_TO_EDGE;
case GGL_REPEAT: return GGL_NEEDS_WRAP_REPEAT;
}
return 0;
}
inline uint32_t ggl_blendfactor_to_needs(uint32_t b) {
if (b <= 1) return b;
return (b & 0xF)+2;
}
inline uint32_t ggl_needs_to_blendfactor(uint32_t n) {
if (n <= 1) return n;
return (n - 2) + 0x300;
}
inline uint32_t ggl_env_to_needs(uint32_t e) {
switch (e) {
case GGL_REPLACE: return 0;
case GGL_MODULATE: return 1;
case GGL_DECAL: return 2;
case GGL_BLEND: return 3;
case GGL_ADD: return 4;
}
return 0;
}
inline uint32_t ggl_needs_to_env(uint32_t n) {
const uint32_t envs[] = { GGL_REPLACE, GGL_MODULATE,
GGL_DECAL, GGL_BLEND, GGL_ADD };
return envs[n];
}
// ----------------------------------------------------------------------------
enum {
GGL_ENABLE_BLENDING = 0x00000001,
GGL_ENABLE_SMOOTH = 0x00000002,
GGL_ENABLE_AA = 0x00000004,
GGL_ENABLE_LOGIC_OP = 0x00000008,
GGL_ENABLE_ALPHA_TEST = 0x00000010,
GGL_ENABLE_SCISSOR_TEST = 0x00000020,
GGL_ENABLE_TMUS = 0x00000040,
GGL_ENABLE_DEPTH_TEST = 0x00000080,
GGL_ENABLE_STENCIL_TEST = 0x00000100,
GGL_ENABLE_W = 0x00000200,
GGL_ENABLE_DITHER = 0x00000400,
GGL_ENABLE_FOG = 0x00000800,
GGL_ENABLE_POINT_AA_NICE= 0x00001000
};
// ----------------------------------------------------------------------------
struct needs_filter_t;
struct needs_t {
inline int match(const needs_filter_t& filter);
inline bool operator == (const needs_t& rhs) const {
return (n==rhs.n) &&
(p==rhs.p) &&
(t[0]==rhs.t[0]) &&
(t[1]==rhs.t[1]);
}
inline bool operator != (const needs_t& rhs) const {
return !operator == (rhs);
}
uint32_t n;
uint32_t p;
uint32_t t[GGL_TEXTURE_UNIT_COUNT];
};
inline int compare_type(const needs_t& lhs, const needs_t& rhs) {
return memcmp(&lhs, &rhs, sizeof(needs_t));
}
struct needs_filter_t {
needs_t value;
needs_t mask;
};
int needs_t::match(const needs_filter_t& filter) {
uint32_t result =
((filter.value.n ^ n) & filter.mask.n) |
((filter.value.p ^ p) & filter.mask.p) |
((filter.value.t[0] ^ t[0]) & filter.mask.t[0]) |
((filter.value.t[1] ^ t[1]) & filter.mask.t[1]);
return (result == 0);
}
// ----------------------------------------------------------------------------
struct context_t;
class Assembly;
struct blend_state_t {
uint32_t src;
uint32_t dst;
uint32_t src_alpha;
uint32_t dst_alpha;
uint8_t reserved;
uint8_t alpha_separate;
uint8_t operation;
uint8_t equation;
};
struct mask_state_t {
uint8_t color;
uint8_t depth;
uint32_t stencil;
};
struct clear_state_t {
GGLclampx r;
GGLclampx g;
GGLclampx b;
GGLclampx a;
GGLclampx depth;
GGLint stencil;
uint32_t colorPacked;
uint32_t depthPacked;
uint32_t stencilPacked;
uint32_t dirty;
};
struct fog_state_t {
uint8_t color[4];
};
struct logic_op_state_t {
uint16_t opcode;
};
struct alpha_test_state_t {
uint16_t func;
GGLcolor ref;
};
struct depth_test_state_t {
uint16_t func;
GGLclampx clearValue;
};
struct scissor_t {
uint32_t user_left;
uint32_t user_right;
uint32_t user_top;
uint32_t user_bottom;
uint32_t left;
uint32_t right;
uint32_t top;
uint32_t bottom;
};
struct pixel_t {
uint32_t c[4];
uint8_t s[4];
};
struct surface_t {
union {
GGLSurface s;
// Keep the following struct field types in line with the corresponding
// GGLSurface fields to avoid mismatches leading to errors.
struct {
GGLsizei reserved;
GGLuint width;
GGLuint height;
GGLint stride;
GGLubyte* data;
GGLubyte format;
GGLubyte dirty;
GGLubyte pad[2];
};
};
void (*read) (const surface_t* s, context_t* c,
uint32_t x, uint32_t y, pixel_t* pixel);
void (*write)(const surface_t* s, context_t* c,
uint32_t x, uint32_t y, const pixel_t* pixel);
};
// ----------------------------------------------------------------------------
struct texture_shade_t {
union {
struct {
int32_t is0;
int32_t idsdx;
int32_t idsdy;
int sscale;
int32_t it0;
int32_t idtdx;
int32_t idtdy;
int tscale;
};
struct {
int32_t v;
int32_t dx;
int32_t dy;
int scale;
} st[2];
};
};
struct texture_iterators_t {
// these are not encoded in the same way than in the
// texture_shade_t structure
union {
struct {
GGLfixed ydsdy;
GGLfixed dsdx;
GGLfixed dsdy;
int sscale;
GGLfixed ydtdy;
GGLfixed dtdx;
GGLfixed dtdy;
int tscale;
};
struct {
GGLfixed ydvdy;
GGLfixed dvdx;
GGLfixed dvdy;
int scale;
} st[2];
};
};
struct texture_t {
surface_t surface;
texture_iterators_t iterators;
texture_shade_t shade;
uint32_t s_coord;
uint32_t t_coord;
uint16_t s_wrap;
uint16_t t_wrap;
uint16_t min_filter;
uint16_t mag_filter;
uint16_t env;
uint8_t env_color[4];
uint8_t enable;
uint8_t dirty;
};
struct raster_t {
GGLfixed x;
GGLfixed y;
};
struct framebuffer_t {
surface_t color;
surface_t read;
surface_t depth;
surface_t stencil;
int16_t *coverage;
size_t coverageBufferSize;
};
// ----------------------------------------------------------------------------
struct iterators_t {
int32_t xl;
int32_t xr;
int32_t y;
GGLcolor ydady;
GGLcolor ydrdy;
GGLcolor ydgdy;
GGLcolor ydbdy;
GGLfixed ydzdy;
GGLfixed ydwdy;
GGLfixed ydfdy;
};
struct shade_t {
GGLcolor a0;
GGLcolor dadx;
GGLcolor dady;
GGLcolor r0;
GGLcolor drdx;
GGLcolor drdy;
GGLcolor g0;
GGLcolor dgdx;
GGLcolor dgdy;
GGLcolor b0;
GGLcolor dbdx;
GGLcolor dbdy;
uint32_t z0;
GGLfixed32 dzdx;
GGLfixed32 dzdy;
GGLfixed w0;
GGLfixed dwdx;
GGLfixed dwdy;
uint32_t f0;
GGLfixed dfdx;
GGLfixed dfdy;
};
// these are used in the generated code
// we use this mirror structure to improve
// data locality in the pixel pipeline
struct generated_tex_vars_t {
uint32_t width;
uint32_t height;
uint32_t stride;
uintptr_t data;
int32_t dsdx;
int32_t dtdx;
int32_t spill[2];
};
struct generated_vars_t {
struct {
int32_t c;
int32_t dx;
} argb[4];
int32_t aref;
int32_t dzdx;
int32_t zbase;
int32_t f;
int32_t dfdx;
int32_t spill[3];
generated_tex_vars_t texture[GGL_TEXTURE_UNIT_COUNT];
int32_t rt;
int32_t lb;
};
// ----------------------------------------------------------------------------
struct state_t {
framebuffer_t buffers;
texture_t texture[GGL_TEXTURE_UNIT_COUNT];
scissor_t scissor;
raster_t raster;
blend_state_t blend;
alpha_test_state_t alpha_test;
depth_test_state_t depth_test;
mask_state_t mask;
clear_state_t clear;
fog_state_t fog;
logic_op_state_t logic_op;
uint32_t enables;
uint32_t enabled_tmu;
needs_t needs;
};
// ----------------------------------------------------------------------------
struct context_t {
GGLContext procs;
state_t state;
shade_t shade;
iterators_t iterators;
generated_vars_t generated_vars __attribute__((aligned(32)));
uint8_t ditherMatrix[GGL_DITHER_SIZE] __attribute__((aligned(32)));
uint32_t packed;
uint32_t packed8888;
const GGLFormat* formats;
uint32_t dirty;
texture_t* activeTMU;
uint32_t activeTMUIndex;
void (*init_y)(context_t* c, int32_t y);
void (*step_y)(context_t* c);
void (*scanline)(context_t* c);
void (*span)(context_t* c);
void (*rect)(context_t* c, size_t yc);
void* base;
Assembly* scanline_as;
GGLenum error;
};
// ----------------------------------------------------------------------------
void ggl_init_context(context_t* context);
void ggl_uninit_context(context_t* context);
void ggl_error(context_t* c, GGLenum error);
int64_t ggl_system_time();
// ----------------------------------------------------------------------------
};
#endif // ANDROID_GGL_CONTEXT_H

View File

@ -1,878 +0,0 @@
/*
* Copyright (C) 2005 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 ANDROID_GGL_FIXED_H
#define ANDROID_GGL_FIXED_H
#include <math.h>
#include <pixelflinger/pixelflinger.h>
// ----------------------------------------------------------------------------
#define CONST __attribute__((const))
#define ALWAYS_INLINE __attribute__((always_inline))
const GGLfixed FIXED_BITS = 16;
const GGLfixed FIXED_EPSILON = 1;
const GGLfixed FIXED_ONE = 1L<<FIXED_BITS;
const GGLfixed FIXED_HALF = 1L<<(FIXED_BITS-1);
const GGLfixed FIXED_MIN = 0x80000000L;
const GGLfixed FIXED_MAX = 0x7FFFFFFFL;
inline GGLfixed gglIntToFixed(GGLfixed i) ALWAYS_INLINE ;
inline GGLfixed gglFixedToIntRound(GGLfixed f) ALWAYS_INLINE ;
inline GGLfixed gglFixedToIntFloor(GGLfixed f) ALWAYS_INLINE ;
inline GGLfixed gglFixedToIntCeil(GGLfixed f) ALWAYS_INLINE ;
inline GGLfixed gglFracx(GGLfixed v) ALWAYS_INLINE ;
inline GGLfixed gglFloorx(GGLfixed v) ALWAYS_INLINE ;
inline GGLfixed gglCeilx(GGLfixed v) ALWAYS_INLINE ;
inline GGLfixed gglCenterx(GGLfixed v) ALWAYS_INLINE ;
inline GGLfixed gglRoundx(GGLfixed v) ALWAYS_INLINE ;
GGLfixed gglIntToFixed(GGLfixed i) {
return i<<FIXED_BITS;
}
GGLfixed gglFixedToIntRound(GGLfixed f) {
return (f + FIXED_HALF)>>FIXED_BITS;
}
GGLfixed gglFixedToIntFloor(GGLfixed f) {
return f>>FIXED_BITS;
}
GGLfixed gglFixedToIntCeil(GGLfixed f) {
return (f + ((1<<FIXED_BITS) - 1))>>FIXED_BITS;
}
GGLfixed gglFracx(GGLfixed v) {
return v & ((1<<FIXED_BITS)-1);
}
GGLfixed gglFloorx(GGLfixed v) {
return gglFixedToIntFloor(v)<<FIXED_BITS;
}
GGLfixed gglCeilx(GGLfixed v) {
return gglFixedToIntCeil(v)<<FIXED_BITS;
}
GGLfixed gglCenterx(GGLfixed v) {
return gglFloorx(v + FIXED_HALF) | FIXED_HALF;
}
GGLfixed gglRoundx(GGLfixed v) {
return gglFixedToIntRound(v)<<FIXED_BITS;
}
// conversion from (unsigned) int, short, byte to fixed...
#define GGL_B_TO_X(_x) GGLfixed( ((int32_t(_x)+1)>>1)<<10 )
#define GGL_S_TO_X(_x) GGLfixed( ((int32_t(_x)+1)>>1)<<2 )
#define GGL_I_TO_X(_x) GGLfixed( ((int32_t(_x)>>1)+1)>>14 )
#define GGL_UB_TO_X(_x) GGLfixed( uint32_t(_x) + \
(uint32_t(_x)<<8) + \
(uint32_t(_x)>>7) )
#define GGL_US_TO_X(_x) GGLfixed( (_x) + ((_x)>>15) )
#define GGL_UI_TO_X(_x) GGLfixed( (((_x)>>1)+1)>>15 )
// ----------------------------------------------------------------------------
GGLfixed gglPowx(GGLfixed x, GGLfixed y) CONST;
GGLfixed gglSqrtx(GGLfixed a) CONST;
GGLfixed gglSqrtRecipx(GGLfixed x) CONST;
int32_t gglMulDivi(int32_t a, int32_t b, int32_t c);
int32_t gglRecipQNormalized(int32_t x, int* exponent);
int32_t gglRecipQ(GGLfixed x, int q) CONST;
inline GGLfixed gglRecip(GGLfixed x) CONST;
inline GGLfixed gglRecip(GGLfixed x) {
return gglRecipQ(x, 16);
}
inline GGLfixed gglRecip28(GGLfixed x) CONST;
int32_t gglRecip28(GGLfixed x) {
return gglRecipQ(x, 28);
}
// ----------------------------------------------------------------------------
#if defined(__arm__) && !defined(__thumb__)
// inline ARM implementations
inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
__attribute__((always_inline)) inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) {
GGLfixed result, t;
if (__builtin_constant_p(shift)) {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"movs %[lo], %[lo], lsr %[rshift] \n"
"adc %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=r"(result), [hi]"=r"(t), [x]"=r"(x)
: "%[x]"(x), [y]"r"(y), [lshift] "I"(32-shift), [rshift] "I"(shift)
: "cc"
);
} else {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"movs %[lo], %[lo], lsr %[rshift] \n"
"adc %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
: "%[x]"(x), [y]"r"(y), [lshift] "r"(32-shift), [rshift] "r"(shift)
: "cc"
);
}
return result;
}
inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
__attribute__((always_inline)) inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a,
int shift) {
GGLfixed result, t;
if (__builtin_constant_p(shift)) {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"add %[lo], %[a], %[lo], lsr %[rshift] \n"
"add %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
: "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
);
} else {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"add %[lo], %[a], %[lo], lsr %[rshift] \n"
"add %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
: "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
);
}
return result;
}
inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
GGLfixed result, t;
if (__builtin_constant_p(shift)) {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"rsb %[lo], %[a], %[lo], lsr %[rshift] \n"
"add %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
: "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
);
} else {
asm("smull %[lo], %[hi], %[x], %[y] \n"
"rsb %[lo], %[a], %[lo], lsr %[rshift] \n"
"add %[lo], %[lo], %[hi], lsl %[lshift] \n"
: [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
: "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
);
}
return result;
}
inline int64_t gglMulii(int32_t x, int32_t y) CONST;
inline int64_t gglMulii(int32_t x, int32_t y)
{
// 64-bits result: r0=low, r1=high
union {
struct {
int32_t lo;
int32_t hi;
} s;
int64_t res;
};
asm("smull %0, %1, %2, %3 \n"
: "=r"(s.lo), "=&r"(s.hi)
: "%r"(x), "r"(y)
:
);
return res;
}
#elif defined(__mips__) && __mips_isa_rev < 6
/*inline MIPS implementations*/
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
GGLfixed result,tmp,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mult %[a], %[b] \t\n"
"mflo %[res] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp)
: [a]"r"(a),[b]"r"(b)
: "%hi","%lo"
);
} else if (shift == 32)
{
asm ("mult %[a], %[b] \t\n"
"li %[tmp],1\t\n"
"sll %[tmp],%[tmp],0x1f\t\n"
"mflo %[res] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp]\t\n" /*obit*/
"sra %[tmp],%[tmp],0x1f \t\n"
"mfhi %[res] \t\n"
"addu %[res],%[res],%[tmp]\t\n"
"addu %[res],%[res],%[tmp1]\t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
: [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
: "%hi","%lo"
);
} else if ((shift >0) && (shift < 32))
{
asm ("mult %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"mflo %[res] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"addu %[res],%[res],%[tmp] \t\n"
"mfhi %[tmp] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n"
"sll %[tmp],%[tmp],%[lshift] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
: "%hi","%lo"
);
} else {
asm ("mult %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"mflo %[res] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"mfhi %[tmp] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"movz %[res],%[tmp],%[bit5] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
: "%hi","%lo"
);
}
} else {
asm ("mult %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"mflo %[res] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"mfhi %[tmp] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"movz %[res],%[tmp],%[bit5] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
: "%hi","%lo"
);
}
return result;
}
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mult %[a], %[b] \t\n"
"mflo %[lo] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
: "%hi","%lo"
);
} else if (shift == 32) {
asm ("mult %[a], %[b] \t\n"
"mfhi %[lo] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
: "%hi","%lo"
);
} else if ((shift>0) && (shift<32)) {
asm ("mult %[a], %[b] \t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
: "%hi","%lo"
);
} else {
asm ("mult %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"movz %[res],%[tmp1],%[tmp2]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
: "%hi","%lo"
);
}
} else {
asm ("mult %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"movz %[res],%[tmp1],%[tmp2]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
: "%hi","%lo"
);
}
return result;
}
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mult %[a], %[b] \t\n"
"mflo %[lo] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
: "%hi","%lo"
);
} else if (shift == 32) {
asm ("mult %[a], %[b] \t\n"
"mfhi %[lo] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
: "%hi","%lo"
);
} else if ((shift>0) && (shift<32)) {
asm ("mult %[a], %[b] \t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
: "%hi","%lo"
);
} else {
asm ("mult %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"movz %[res],%[tmp1],%[tmp2]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
: "%hi","%lo"
);
}
} else {
asm ("mult %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"mflo %[res] \t\n"
"mfhi %[t] \t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"movz %[res],%[tmp1],%[tmp2]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
: "%hi","%lo"
);
}
return result;
}
inline int64_t gglMulii(int32_t x, int32_t y) CONST;
inline int64_t gglMulii(int32_t x, int32_t y) {
union {
struct {
#if defined(__MIPSEL__)
int32_t lo;
int32_t hi;
#elif defined(__MIPSEB__)
int32_t hi;
int32_t lo;
#endif
} s;
int64_t res;
}u;
asm("mult %2, %3 \t\n"
"mfhi %1 \t\n"
"mflo %0 \t\n"
: "=r"(u.s.lo), "=&r"(u.s.hi)
: "%r"(x), "r"(y)
: "%hi","%lo"
);
return u.res;
}
#elif defined(__aarch64__)
// inline AArch64 implementations
inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
inline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift)
{
GGLfixed result;
GGLfixed round;
asm("mov %x[round], #1 \n"
"lsl %x[round], %x[round], %x[shift] \n"
"lsr %x[round], %x[round], #1 \n"
"smaddl %x[result], %w[x], %w[y],%x[round] \n"
"lsr %x[result], %x[result], %x[shift] \n"
: [round]"=&r"(round), [result]"=&r"(result) \
: [x]"r"(x), [y]"r"(y), [shift] "r"(shift) \
:
);
return result;
}
inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
inline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
{
GGLfixed result;
asm("smull %x[result], %w[x], %w[y] \n"
"lsr %x[result], %x[result], %x[shift] \n"
"add %w[result], %w[result], %w[a] \n"
: [result]"=&r"(result) \
: [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
:
);
return result;
}
inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
{
GGLfixed result;
asm("smull %x[result], %w[x], %w[y] \n"
"lsr %x[result], %x[result], %x[shift] \n"
"sub %w[result], %w[result], %w[a] \n"
: [result]"=&r"(result) \
: [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
:
);
return result;
}
inline int64_t gglMulii(int32_t x, int32_t y) CONST;
inline int64_t gglMulii(int32_t x, int32_t y)
{
int64_t res;
asm("smull %x0, %w1, %w2 \n"
: "=r"(res)
: "%r"(x), "r"(y)
:
);
return res;
}
#elif defined(__mips__) && __mips_isa_rev == 6
/*inline MIPS implementations*/
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
GGLfixed result,tmp,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[res], %[a], %[b] \t\n"
: [res]"=&r"(result)
: [a]"r"(a),[b]"r"(b)
);
} else if (shift == 32)
{
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1\t\n"
"sll %[tmp],%[tmp],0x1f\t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"muh %[res], %[a], %[b] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp]\t\n" /*obit*/
"sra %[tmp],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp]\t\n"
"addu %[res],%[res],%[tmp1]\t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
: [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
);
} else if ((shift >0) && (shift < 32))
{
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n"
"sll %[tmp],%[tmp],%[lshift] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"seleqz %[tmp],%[tmp],%[bit5] \t\n"
"selnez %[res],%[res],%[bit5] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"seleqz %[tmp],%[tmp],%[bit5] \t\n"
"selnez %[res],%[res],%[bit5] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
);
}
return result;
}
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[lo], %[a], %[b] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if (shift == 32) {
asm ("muh %[lo], %[a], %[b] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if ((shift>0) && (shift<32)) {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
);
}
return result;
}
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[lo], %[a], %[b] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if (shift == 32) {
asm ("muh %[lo], %[a], %[b] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if ((shift>0) && (shift<32)) {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
);
}
return result;
}
inline int64_t gglMulii(int32_t x, int32_t y) CONST;
inline int64_t gglMulii(int32_t x, int32_t y) {
union {
struct {
#if defined(__MIPSEL__)
int32_t lo;
int32_t hi;
#elif defined(__MIPSEB__)
int32_t hi;
int32_t lo;
#endif
} s;
int64_t res;
}u;
asm("mul %0, %2, %3 \t\n"
"muh %1, %2, %3 \t\n"
: "=r"(u.s.lo), "=&r"(u.s.hi)
: "%r"(x), "r"(y)
);
return u.res;
}
#else // ----------------------------------------------------------------------
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
return GGLfixed((int64_t(a)*b + (1<<(shift-1)))>>shift);
}
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
return GGLfixed((int64_t(a)*b)>>shift) + c;
}
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
return GGLfixed((int64_t(a)*b)>>shift) - c;
}
inline int64_t gglMulii(int32_t a, int32_t b) CONST;
inline int64_t gglMulii(int32_t a, int32_t b) {
return int64_t(a)*b;
}
#endif
// ------------------------------------------------------------------------
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b) CONST;
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b) {
return gglMulx(a, b, 16);
}
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) {
return gglMulAddx(a, b, c, 16);
}
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) {
return gglMulSubx(a, b, c, 16);
}
// ------------------------------------------------------------------------
inline int32_t gglClz(int32_t x) CONST;
inline int32_t gglClz(int32_t x)
{
#if (defined(__arm__) && !defined(__thumb__)) || defined(__mips__) || defined(__aarch64__)
return __builtin_clz(x);
#else
if (!x) return 32;
int32_t exp = 31;
if (x & 0xFFFF0000) { exp -=16; x >>= 16; }
if (x & 0x0000ff00) { exp -= 8; x >>= 8; }
if (x & 0x000000f0) { exp -= 4; x >>= 4; }
if (x & 0x0000000c) { exp -= 2; x >>= 2; }
if (x & 0x00000002) { exp -= 1; }
return exp;
#endif
}
// ------------------------------------------------------------------------
int32_t gglDivQ(GGLfixed n, GGLfixed d, int32_t i) CONST;
inline int32_t gglDivQ16(GGLfixed n, GGLfixed d) CONST;
inline int32_t gglDivQ16(GGLfixed n, GGLfixed d) {
return gglDivQ(n, d, 16);
}
inline int32_t gglDivx(GGLfixed n, GGLfixed d) CONST;
inline int32_t gglDivx(GGLfixed n, GGLfixed d) {
return gglDivQ(n, d, 16);
}
// ------------------------------------------------------------------------
inline GGLfixed gglRecipFast(GGLfixed x) CONST;
inline GGLfixed gglRecipFast(GGLfixed x)
{
// This is a really bad approximation of 1/x, but it's also
// very fast. x must be strictly positive.
// if x between [0.5, 1[ , then 1/x = 3-2*x
// (we use 2.30 fixed-point)
const int32_t lz = gglClz(x);
return (0xC0000000 - (x << (lz - 1))) >> (30-lz);
}
// ------------------------------------------------------------------------
inline GGLfixed gglClampx(GGLfixed c) CONST;
inline GGLfixed gglClampx(GGLfixed c)
{
#if defined(__thumb__)
// clamp without branches
c &= ~(c>>31); c = FIXED_ONE - c;
c &= ~(c>>31); c = FIXED_ONE - c;
#else
#if defined(__arm__)
// I don't know why gcc thinks its smarter than me! The code below
// clamps to zero in one instruction, but gcc won't generate it and
// replace it by a cmp + movlt (it's quite amazing actually).
asm("bic %0, %1, %1, asr #31\n" : "=r"(c) : "r"(c));
#elif defined(__aarch64__)
asm("bic %w0, %w1, %w1, asr #31\n" : "=r"(c) : "r"(c));
#else
c &= ~(c>>31);
#endif
if (c>FIXED_ONE)
c = FIXED_ONE;
#endif
return c;
}
// ------------------------------------------------------------------------
#endif // ANDROID_GGL_FIXED_H

View File

@ -1,173 +0,0 @@
/* libs/pixelflinger/picker.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include "buffer.h"
#include "scanline.h"
#include "picker.h"
namespace android {
// ----------------------------------------------------------------------------
void ggl_init_picker(context_t* /*c*/)
{
}
void ggl_pick(context_t* c)
{
if (ggl_likely(!c->dirty))
return;
// compute needs, see if they changed...
const uint32_t enables = c->state.enables;
needs_t new_needs(c->state.needs);
if (c->dirty & GGL_CB_STATE) {
new_needs.n &= ~GGL_NEEDS_CB_FORMAT_MASK;
new_needs.n |= GGL_BUILD_NEEDS(c->state.buffers.color.format, CB_FORMAT);
if (enables & GGL_ENABLE_BLENDING)
c->dirty |= GGL_PIXEL_PIPELINE_STATE;
}
if (c->dirty & GGL_PIXEL_PIPELINE_STATE) {
uint32_t n = GGL_BUILD_NEEDS(c->state.buffers.color.format, CB_FORMAT);
uint32_t p = 0;
if (enables & GGL_ENABLE_BLENDING) {
uint32_t src = c->state.blend.src;
uint32_t dst = c->state.blend.dst;
uint32_t src_alpha = c->state.blend.src_alpha;
uint32_t dst_alpha = c->state.blend.dst_alpha;
const GGLFormat& cbf = c->formats[ c->state.buffers.color.format ];
if (!cbf.c[GGLFormat::ALPHA].h) {
if ((src == GGL_ONE_MINUS_DST_ALPHA) ||
(src == GGL_DST_ALPHA)) {
src = GGL_ONE;
}
if ((src_alpha == GGL_ONE_MINUS_DST_ALPHA) ||
(src_alpha == GGL_DST_ALPHA)) {
src_alpha = GGL_ONE;
}
if ((dst == GGL_ONE_MINUS_DST_ALPHA) ||
(dst == GGL_DST_ALPHA)) {
dst = GGL_ONE;
}
if ((dst_alpha == GGL_ONE_MINUS_DST_ALPHA) ||
(dst_alpha == GGL_DST_ALPHA)) {
dst_alpha = GGL_ONE;
}
}
src = ggl_blendfactor_to_needs(src);
dst = ggl_blendfactor_to_needs(dst);
src_alpha = ggl_blendfactor_to_needs(src_alpha);
dst_alpha = ggl_blendfactor_to_needs(dst_alpha);
n |= GGL_BUILD_NEEDS( src, BLEND_SRC );
n |= GGL_BUILD_NEEDS( dst, BLEND_DST );
if (c->state.blend.alpha_separate) {
n |= GGL_BUILD_NEEDS( src_alpha, BLEND_SRCA );
n |= GGL_BUILD_NEEDS( dst_alpha, BLEND_DSTA );
} else {
n |= GGL_BUILD_NEEDS( src, BLEND_SRCA );
n |= GGL_BUILD_NEEDS( dst, BLEND_DSTA );
}
} else {
n |= GGL_BUILD_NEEDS( GGL_ONE, BLEND_SRC );
n |= GGL_BUILD_NEEDS( GGL_ZERO, BLEND_DST );
n |= GGL_BUILD_NEEDS( GGL_ONE, BLEND_SRCA );
n |= GGL_BUILD_NEEDS( GGL_ZERO, BLEND_DSTA );
}
n |= GGL_BUILD_NEEDS(c->state.mask.color^0xF, MASK_ARGB);
n |= GGL_BUILD_NEEDS((enables & GGL_ENABLE_SMOOTH) ?1:0, SHADE);
if (enables & GGL_ENABLE_TMUS) {
n |= GGL_BUILD_NEEDS((enables & GGL_ENABLE_W) ?1:0, W);
}
p |= GGL_BUILD_NEEDS((enables & GGL_ENABLE_DITHER) ?1:0, P_DITHER);
p |= GGL_BUILD_NEEDS((enables & GGL_ENABLE_AA) ?1:0, P_AA);
p |= GGL_BUILD_NEEDS((enables & GGL_ENABLE_FOG) ?1:0, P_FOG);
if (enables & GGL_ENABLE_LOGIC_OP) {
n |= GGL_BUILD_NEEDS(c->state.logic_op.opcode, LOGIC_OP);
} else {
n |= GGL_BUILD_NEEDS(GGL_COPY, LOGIC_OP);
}
if (enables & GGL_ENABLE_ALPHA_TEST) {
p |= GGL_BUILD_NEEDS(c->state.alpha_test.func, P_ALPHA_TEST);
} else {
p |= GGL_BUILD_NEEDS(GGL_ALWAYS, P_ALPHA_TEST);
}
if (enables & GGL_ENABLE_DEPTH_TEST) {
p |= GGL_BUILD_NEEDS(c->state.depth_test.func, P_DEPTH_TEST);
p |= GGL_BUILD_NEEDS(c->state.mask.depth&1, P_MASK_Z);
} else {
p |= GGL_BUILD_NEEDS(GGL_ALWAYS, P_DEPTH_TEST);
// writing to the z-buffer is always disabled if depth-test
// is disabled.
}
new_needs.n = n;
new_needs.p = p;
}
if (c->dirty & GGL_TMU_STATE) {
int idx = 0;
for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) {
const texture_t& tx = c->state.texture[i];
if (tx.enable) {
uint32_t t = 0;
t |= GGL_BUILD_NEEDS(tx.surface.format, T_FORMAT);
t |= GGL_BUILD_NEEDS(ggl_env_to_needs(tx.env), T_ENV);
t |= GGL_BUILD_NEEDS(0, T_POT); // XXX: not used yet
if (tx.s_coord==GGL_ONE_TO_ONE && tx.t_coord==GGL_ONE_TO_ONE) {
// we encode 1-to-1 into the wrap mode
t |= GGL_BUILD_NEEDS(GGL_NEEDS_WRAP_11, T_S_WRAP);
t |= GGL_BUILD_NEEDS(GGL_NEEDS_WRAP_11, T_T_WRAP);
} else {
t |= GGL_BUILD_NEEDS(ggl_wrap_to_needs(tx.s_wrap), T_S_WRAP);
t |= GGL_BUILD_NEEDS(ggl_wrap_to_needs(tx.t_wrap), T_T_WRAP);
}
if (tx.mag_filter == GGL_LINEAR) {
t |= GGL_BUILD_NEEDS(1, T_LINEAR);
}
if (tx.min_filter == GGL_LINEAR) {
t |= GGL_BUILD_NEEDS(1, T_LINEAR);
}
new_needs.t[idx++] = t;
} else {
new_needs.t[i] = 0;
}
}
}
if (new_needs != c->state.needs) {
c->state.needs = new_needs;
ggl_pick_texture(c);
ggl_pick_cb(c);
ggl_pick_scanline(c);
}
c->dirty = 0;
}
// ----------------------------------------------------------------------------
}; // namespace android

View File

@ -1,31 +0,0 @@
/* libs/pixelflinger/picker.h
**
** Copyright 2006, 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 ANDROID_PICKER_H
#define ANDROID_PICKER_H
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_picker(context_t* c);
void ggl_pick(context_t* c);
}; // namespace android
#endif

View File

@ -1,836 +0,0 @@
/* libs/pixelflinger/pixelflinger.cpp
**
** Copyright 2006, 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/time.h>
#include <pixelflinger/pixelflinger.h>
#include <private/pixelflinger/ggl_context.h>
#include "buffer.h"
#include "clear.h"
#include "picker.h"
#include "raster.h"
#include "scanline.h"
#include "trap.h"
#include "codeflinger/GGLAssembler.h"
#include "codeflinger/CodeCache.h"
#include <stdio.h>
namespace android {
// ----------------------------------------------------------------------------
// 8x8 Bayer dither matrix
static const uint8_t gDitherMatrix[GGL_DITHER_SIZE] = {
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
static void ggl_init_procs(context_t* c);
static void ggl_set_scissor(context_t* c);
static void ggl_enable_blending(context_t* c, int enable);
static void ggl_enable_scissor_test(context_t* c, int enable);
static void ggl_enable_alpha_test(context_t* c, int enable);
static void ggl_enable_logic_op(context_t* c, int enable);
static void ggl_enable_dither(context_t* c, int enable);
static void ggl_enable_stencil_test(context_t* c, int enable);
static void ggl_enable_depth_test(context_t* c, int enable);
static void ggl_enable_aa(context_t* c, int enable);
static void ggl_enable_point_aa_nice(context_t* c, int enable);
static void ggl_enable_texture2d(context_t* c, int enable);
static void ggl_enable_w_lerp(context_t* c, int enable);
static void ggl_enable_fog(context_t* c, int enable);
static inline int min(int a, int b) CONST;
static inline int min(int a, int b) {
return a < b ? a : b;
}
static inline int max(int a, int b) CONST;
static inline int max(int a, int b) {
return a < b ? b : a;
}
// ----------------------------------------------------------------------------
void ggl_error(context_t* c, GGLenum error)
{
if (c->error == GGL_NO_ERROR)
c->error = error;
}
// ----------------------------------------------------------------------------
static void ggl_bindTexture(void* con, const GGLSurface* surface)
{
GGL_CONTEXT(c, con);
if (surface->format != c->activeTMU->surface.format)
ggl_state_changed(c, GGL_TMU_STATE);
ggl_set_surface(c, &(c->activeTMU->surface), surface);
}
static void ggl_bindTextureLod(void* con, GGLuint tmu,const GGLSurface* surface)
{
GGL_CONTEXT(c, con);
// All LODs must have the same format
ggl_set_surface(c, &c->state.texture[tmu].surface, surface);
}
static void ggl_colorBuffer(void* con, const GGLSurface* surface)
{
GGL_CONTEXT(c, con);
if (surface->format != c->state.buffers.color.format)
ggl_state_changed(c, GGL_CB_STATE);
if (surface->width > c->state.buffers.coverageBufferSize) {
// allocate the coverage factor buffer
free(c->state.buffers.coverage);
c->state.buffers.coverage = (int16_t*)malloc(surface->width * 2);
c->state.buffers.coverageBufferSize =
c->state.buffers.coverage ? surface->width : 0;
}
ggl_set_surface(c, &(c->state.buffers.color), surface);
if (c->state.buffers.read.format == 0) {
ggl_set_surface(c, &(c->state.buffers.read), surface);
}
ggl_set_scissor(c);
}
static void ggl_readBuffer(void* con, const GGLSurface* surface)
{
GGL_CONTEXT(c, con);
ggl_set_surface(c, &(c->state.buffers.read), surface);
}
static void ggl_depthBuffer(void* con, const GGLSurface* surface)
{
GGL_CONTEXT(c, con);
if (surface->format == GGL_PIXEL_FORMAT_Z_16) {
ggl_set_surface(c, &(c->state.buffers.depth), surface);
} else {
c->state.buffers.depth.format = GGL_PIXEL_FORMAT_NONE;
ggl_enable_depth_test(c, 0);
}
}
static void ggl_scissor(void* con, GGLint x, GGLint y,
GGLsizei width, GGLsizei height)
{
GGL_CONTEXT(c, con);
c->state.scissor.user_left = x;
c->state.scissor.user_top = y;
c->state.scissor.user_right = x + width;
c->state.scissor.user_bottom = y + height;
ggl_set_scissor(c);
}
// ----------------------------------------------------------------------------
static void enable_disable(context_t* c, GGLenum name, int en)
{
switch (name) {
case GGL_BLEND: ggl_enable_blending(c, en); break;
case GGL_SCISSOR_TEST: ggl_enable_scissor_test(c, en); break;
case GGL_ALPHA_TEST: ggl_enable_alpha_test(c, en); break;
case GGL_COLOR_LOGIC_OP: ggl_enable_logic_op(c, en); break;
case GGL_DITHER: ggl_enable_dither(c, en); break;
case GGL_STENCIL_TEST: ggl_enable_stencil_test(c, en); break;
case GGL_DEPTH_TEST: ggl_enable_depth_test(c, en); break;
case GGL_AA: ggl_enable_aa(c, en); break;
case GGL_TEXTURE_2D: ggl_enable_texture2d(c, en); break;
case GGL_W_LERP: ggl_enable_w_lerp(c, en); break;
case GGL_FOG: ggl_enable_fog(c, en); break;
case GGL_POINT_SMOOTH_NICE: ggl_enable_point_aa_nice(c, en); break;
}
}
static void ggl_enable(void* con, GGLenum name)
{
GGL_CONTEXT(c, con);
enable_disable(c, name, 1);
}
static void ggl_disable(void* con, GGLenum name)
{
GGL_CONTEXT(c, con);
enable_disable(c, name, 0);
}
static void ggl_enableDisable(void* con, GGLenum name, GGLboolean en)
{
GGL_CONTEXT(c, con);
enable_disable(c, name, en ? 1 : 0);
}
// ----------------------------------------------------------------------------
static void ggl_shadeModel(void* con, GGLenum mode)
{
GGL_CONTEXT(c, con);
switch (mode) {
case GGL_FLAT:
if (c->state.enables & GGL_ENABLE_SMOOTH) {
c->state.enables &= ~GGL_ENABLE_SMOOTH;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
break;
case GGL_SMOOTH:
if (!(c->state.enables & GGL_ENABLE_SMOOTH)) {
c->state.enables |= GGL_ENABLE_SMOOTH;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
break;
default:
ggl_error(c, GGL_INVALID_ENUM);
}
}
static void ggl_color4xv(void* con, const GGLclampx* color)
{
GGL_CONTEXT(c, con);
c->shade.r0 = gglFixedToIteratedColor(color[0]);
c->shade.g0 = gglFixedToIteratedColor(color[1]);
c->shade.b0 = gglFixedToIteratedColor(color[2]);
c->shade.a0 = gglFixedToIteratedColor(color[3]);
}
static void ggl_colorGrad12xv(void* con, const GGLcolor* grad)
{
GGL_CONTEXT(c, con);
// it is very important to round the iterated value here because
// the rasterizer doesn't clamp them, therefore the iterated value
//must absolutely be correct.
// GGLColor is encoded as 8.16 value
const int32_t round = 0x8000;
c->shade.r0 = grad[ 0] + round;
c->shade.drdx = grad[ 1];
c->shade.drdy = grad[ 2];
c->shade.g0 = grad[ 3] + round;
c->shade.dgdx = grad[ 4];
c->shade.dgdy = grad[ 5];
c->shade.b0 = grad[ 6] + round;
c->shade.dbdx = grad[ 7];
c->shade.dbdy = grad[ 8];
c->shade.a0 = grad[ 9] + round;
c->shade.dadx = grad[10];
c->shade.dady = grad[11];
}
static void ggl_zGrad3xv(void* con, const GGLfixed32* grad)
{
GGL_CONTEXT(c, con);
// z iterators are encoded as 0.32 fixed point and the z-buffer
// holds 16 bits, the rounding value is 0x8000.
const uint32_t round = 0x8000;
c->shade.z0 = grad[0] + round;
c->shade.dzdx = grad[1];
c->shade.dzdy = grad[2];
}
static void ggl_wGrad3xv(void* con, const GGLfixed* grad)
{
GGL_CONTEXT(c, con);
c->shade.w0 = grad[0];
c->shade.dwdx = grad[1];
c->shade.dwdy = grad[2];
}
// ----------------------------------------------------------------------------
static void ggl_fogGrad3xv(void* con, const GGLfixed* grad)
{
GGL_CONTEXT(c, con);
c->shade.f0 = grad[0];
c->shade.dfdx = grad[1];
c->shade.dfdy = grad[2];
}
static void ggl_fogColor3xv(void* con, const GGLclampx* color)
{
GGL_CONTEXT(c, con);
const int32_t r = gglClampx(color[0]);
const int32_t g = gglClampx(color[1]);
const int32_t b = gglClampx(color[2]);
c->state.fog.color[GGLFormat::ALPHA]= 0xFF; // unused
c->state.fog.color[GGLFormat::RED] = (r - (r>>8))>>8;
c->state.fog.color[GGLFormat::GREEN]= (g - (g>>8))>>8;
c->state.fog.color[GGLFormat::BLUE] = (b - (b>>8))>>8;
}
static void ggl_enable_fog(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_FOG)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_FOG;
else c->state.enables &= ~GGL_ENABLE_FOG;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
static void ggl_blendFunc(void* con, GGLenum src, GGLenum dst)
{
GGL_CONTEXT(c, con);
c->state.blend.src = src;
c->state.blend.src_alpha = src;
c->state.blend.dst = dst;
c->state.blend.dst_alpha = dst;
c->state.blend.alpha_separate = 0;
if (c->state.enables & GGL_ENABLE_BLENDING) {
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
static void ggl_blendFuncSeparate(void* con,
GGLenum src, GGLenum dst,
GGLenum srcAlpha, GGLenum dstAplha)
{
GGL_CONTEXT(c, con);
c->state.blend.src = src;
c->state.blend.src_alpha = srcAlpha;
c->state.blend.dst = dst;
c->state.blend.dst_alpha = dstAplha;
c->state.blend.alpha_separate = 1;
if (c->state.enables & GGL_ENABLE_BLENDING) {
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
static void ggl_texEnvi(void* con, GGLenum target,
GGLenum pname,
GGLint param)
{
GGL_CONTEXT(c, con);
if (target != GGL_TEXTURE_ENV || pname != GGL_TEXTURE_ENV_MODE) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
switch (param) {
case GGL_REPLACE:
case GGL_MODULATE:
case GGL_DECAL:
case GGL_BLEND:
case GGL_ADD:
if (c->activeTMU->env != param) {
c->activeTMU->env = param;
ggl_state_changed(c, GGL_TMU_STATE);
}
break;
default:
ggl_error(c, GGL_INVALID_ENUM);
}
}
static void ggl_texEnvxv(void* con, GGLenum target,
GGLenum pname, const GGLfixed* params)
{
GGL_CONTEXT(c, con);
if (target != GGL_TEXTURE_ENV) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
switch (pname) {
case GGL_TEXTURE_ENV_MODE:
ggl_texEnvi(con, target, pname, params[0]);
break;
case GGL_TEXTURE_ENV_COLOR: {
uint8_t* const color = c->activeTMU->env_color;
const GGLclampx r = gglClampx(params[0]);
const GGLclampx g = gglClampx(params[1]);
const GGLclampx b = gglClampx(params[2]);
const GGLclampx a = gglClampx(params[3]);
color[0] = (a-(a>>8))>>8;
color[1] = (r-(r>>8))>>8;
color[2] = (g-(g>>8))>>8;
color[3] = (b-(b>>8))>>8;
break;
}
default:
ggl_error(c, GGL_INVALID_ENUM);
return;
}
}
static void ggl_texParameteri(void* con,
GGLenum target,
GGLenum pname,
GGLint param)
{
GGL_CONTEXT(c, con);
if (target != GGL_TEXTURE_2D) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
if (param == GGL_CLAMP_TO_EDGE)
param = GGL_CLAMP;
uint16_t* what = 0;
switch (pname) {
case GGL_TEXTURE_WRAP_S:
if ((param == GGL_CLAMP) ||
(param == GGL_REPEAT)) {
what = &c->activeTMU->s_wrap;
}
break;
case GGL_TEXTURE_WRAP_T:
if ((param == GGL_CLAMP) ||
(param == GGL_REPEAT)) {
what = &c->activeTMU->t_wrap;
}
break;
case GGL_TEXTURE_MIN_FILTER:
if ((param == GGL_NEAREST) ||
(param == GGL_NEAREST_MIPMAP_NEAREST) ||
(param == GGL_NEAREST_MIPMAP_LINEAR)) {
what = &c->activeTMU->min_filter;
param = GGL_NEAREST;
}
if ((param == GGL_LINEAR) ||
(param == GGL_LINEAR_MIPMAP_NEAREST) ||
(param == GGL_LINEAR_MIPMAP_LINEAR)) {
what = &c->activeTMU->min_filter;
param = GGL_LINEAR;
}
break;
case GGL_TEXTURE_MAG_FILTER:
if ((param == GGL_NEAREST) ||
(param == GGL_LINEAR)) {
what = &c->activeTMU->mag_filter;
}
break;
}
if (!what) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
if (*what != param) {
*what = param;
ggl_state_changed(c, GGL_TMU_STATE);
}
}
static void ggl_texCoordGradScale8xv(void* con, GGLint tmu, const int32_t* grad)
{
GGL_CONTEXT(c, con);
texture_t& u = c->state.texture[tmu];
u.shade.is0 = grad[0];
u.shade.idsdx = grad[1];
u.shade.idsdy = grad[2];
u.shade.it0 = grad[3];
u.shade.idtdx = grad[4];
u.shade.idtdy = grad[5];
u.shade.sscale= grad[6];
u.shade.tscale= grad[7];
}
static void ggl_texCoord2x(void* con, GGLfixed s, GGLfixed t)
{
GGL_CONTEXT(c, con);
c->activeTMU->shade.is0 = s;
c->activeTMU->shade.it0 = t;
c->activeTMU->shade.sscale= 0;
c->activeTMU->shade.tscale= 0;
}
static void ggl_texCoord2i(void* con, GGLint s, GGLint t)
{
ggl_texCoord2x(con, s<<16, t<<16);
}
static void ggl_texGeni(void* con, GGLenum coord, GGLenum pname, GGLint param)
{
GGL_CONTEXT(c, con);
if (pname != GGL_TEXTURE_GEN_MODE) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
uint32_t* coord_ptr = 0;
if (coord == GGL_S) coord_ptr = &(c->activeTMU->s_coord);
else if (coord == GGL_T) coord_ptr = &(c->activeTMU->t_coord);
if (coord_ptr) {
if (*coord_ptr != uint32_t(param)) {
*coord_ptr = uint32_t(param);
ggl_state_changed(c, GGL_TMU_STATE);
}
} else {
ggl_error(c, GGL_INVALID_ENUM);
}
}
static void ggl_activeTexture(void* con, GGLuint tmu)
{
GGL_CONTEXT(c, con);
if (tmu >= GGLuint(GGL_TEXTURE_UNIT_COUNT)) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
c->activeTMUIndex = tmu;
c->activeTMU = &(c->state.texture[tmu]);
}
// ----------------------------------------------------------------------------
static void ggl_colorMask(void* con, GGLboolean r,
GGLboolean g,
GGLboolean b,
GGLboolean a)
{
GGL_CONTEXT(c, con);
int mask = 0;
if (a) mask |= 1 << GGLFormat::ALPHA;
if (r) mask |= 1 << GGLFormat::RED;
if (g) mask |= 1 << GGLFormat::GREEN;
if (b) mask |= 1 << GGLFormat::BLUE;
if (c->state.mask.color != mask) {
c->state.mask.color = mask;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
static void ggl_depthMask(void* con, GGLboolean flag)
{
GGL_CONTEXT(c, con);
if (c->state.mask.depth != flag?1:0) {
c->state.mask.depth = flag?1:0;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
static void ggl_stencilMask(void* con, GGLuint mask)
{
GGL_CONTEXT(c, con);
if (c->state.mask.stencil != mask) {
c->state.mask.stencil = mask;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
static void ggl_alphaFuncx(void* con, GGLenum func, GGLclampx ref)
{
GGL_CONTEXT(c, con);
if ((func < GGL_NEVER) || (func > GGL_ALWAYS)) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
c->state.alpha_test.ref = gglFixedToIteratedColor(gglClampx(ref));
if (c->state.alpha_test.func != func) {
c->state.alpha_test.func = func;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
static void ggl_depthFunc(void* con, GGLenum func)
{
GGL_CONTEXT(c, con);
if ((func < GGL_NEVER) || (func > GGL_ALWAYS)) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
if (c->state.depth_test.func != func) {
c->state.depth_test.func = func;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
static void ggl_logicOp(void* con, GGLenum opcode)
{
GGL_CONTEXT(c, con);
if ((opcode < GGL_CLEAR) || (opcode > GGL_SET)) {
ggl_error(c, GGL_INVALID_ENUM);
return;
}
if (c->state.logic_op.opcode != opcode) {
c->state.logic_op.opcode = opcode;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
// ----------------------------------------------------------------------------
void ggl_set_scissor(context_t* c)
{
if (c->state.enables & GGL_ENABLE_SCISSOR_TEST) {
const int32_t l = c->state.scissor.user_left;
const int32_t t = c->state.scissor.user_top;
const int32_t r = c->state.scissor.user_right;
const int32_t b = c->state.scissor.user_bottom;
c->state.scissor.left = max(0, l);
c->state.scissor.right = min(c->state.buffers.color.width, r);
c->state.scissor.top = max(0, t);
c->state.scissor.bottom = min(c->state.buffers.color.height, b);
} else {
c->state.scissor.left = 0;
c->state.scissor.top = 0;
c->state.scissor.right = c->state.buffers.color.width;
c->state.scissor.bottom = c->state.buffers.color.height;
}
}
void ggl_enable_blending(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_BLENDING)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_BLENDING;
else c->state.enables &= ~GGL_ENABLE_BLENDING;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_scissor_test(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_SCISSOR_TEST)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_SCISSOR_TEST;
else c->state.enables &= ~GGL_ENABLE_SCISSOR_TEST;
ggl_set_scissor(c);
}
}
void ggl_enable_alpha_test(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_ALPHA_TEST)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_ALPHA_TEST;
else c->state.enables &= ~GGL_ENABLE_ALPHA_TEST;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_logic_op(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_LOGIC_OP)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_LOGIC_OP;
else c->state.enables &= ~GGL_ENABLE_LOGIC_OP;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_dither(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_DITHER)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_DITHER;
else c->state.enables &= ~GGL_ENABLE_DITHER;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_stencil_test(context_t* /*c*/, int /*enable*/)
{
}
void ggl_enable_depth_test(context_t* c, int enable)
{
if (c->state.buffers.depth.format == 0)
enable = 0;
const int e = (c->state.enables & GGL_ENABLE_DEPTH_TEST)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_DEPTH_TEST;
else c->state.enables &= ~GGL_ENABLE_DEPTH_TEST;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_aa(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_AA)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_AA;
else c->state.enables &= ~GGL_ENABLE_AA;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_point_aa_nice(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_POINT_AA_NICE)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_POINT_AA_NICE;
else c->state.enables &= ~GGL_ENABLE_POINT_AA_NICE;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_w_lerp(context_t* c, int enable)
{
const int e = (c->state.enables & GGL_ENABLE_W)?1:0;
if (e != enable) {
if (enable) c->state.enables |= GGL_ENABLE_W;
else c->state.enables &= ~GGL_ENABLE_W;
ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE);
}
}
void ggl_enable_texture2d(context_t* c, int enable)
{
if (c->activeTMU->enable != enable) {
const uint32_t tmu = c->activeTMUIndex;
c->activeTMU->enable = enable;
const uint32_t mask = 1UL << tmu;
if (enable) c->state.enabled_tmu |= mask;
else c->state.enabled_tmu &= ~mask;
if (c->state.enabled_tmu) c->state.enables |= GGL_ENABLE_TMUS;
else c->state.enables &= ~GGL_ENABLE_TMUS;
ggl_state_changed(c, GGL_TMU_STATE);
}
}
// ----------------------------------------------------------------------------
int64_t ggl_system_time()
{
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t);
return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
// ----------------------------------------------------------------------------
void ggl_init_procs(context_t* c)
{
GGLContext& procs = *(GGLContext*)c;
GGL_INIT_PROC(procs, scissor);
GGL_INIT_PROC(procs, activeTexture);
GGL_INIT_PROC(procs, bindTexture);
GGL_INIT_PROC(procs, bindTextureLod);
GGL_INIT_PROC(procs, colorBuffer);
GGL_INIT_PROC(procs, readBuffer);
GGL_INIT_PROC(procs, depthBuffer);
GGL_INIT_PROC(procs, enable);
GGL_INIT_PROC(procs, disable);
GGL_INIT_PROC(procs, enableDisable);
GGL_INIT_PROC(procs, shadeModel);
GGL_INIT_PROC(procs, color4xv);
GGL_INIT_PROC(procs, colorGrad12xv);
GGL_INIT_PROC(procs, zGrad3xv);
GGL_INIT_PROC(procs, wGrad3xv);
GGL_INIT_PROC(procs, fogGrad3xv);
GGL_INIT_PROC(procs, fogColor3xv);
GGL_INIT_PROC(procs, blendFunc);
GGL_INIT_PROC(procs, blendFuncSeparate);
GGL_INIT_PROC(procs, texEnvi);
GGL_INIT_PROC(procs, texEnvxv);
GGL_INIT_PROC(procs, texParameteri);
GGL_INIT_PROC(procs, texCoord2i);
GGL_INIT_PROC(procs, texCoord2x);
GGL_INIT_PROC(procs, texCoordGradScale8xv);
GGL_INIT_PROC(procs, texGeni);
GGL_INIT_PROC(procs, colorMask);
GGL_INIT_PROC(procs, depthMask);
GGL_INIT_PROC(procs, stencilMask);
GGL_INIT_PROC(procs, alphaFuncx);
GGL_INIT_PROC(procs, depthFunc);
GGL_INIT_PROC(procs, logicOp);
ggl_init_clear(c);
}
void ggl_init_context(context_t* c)
{
memset(c, 0, sizeof(context_t));
ggl_init_procs(c);
ggl_init_trap(c);
ggl_init_scanline(c);
ggl_init_texture(c);
ggl_init_picker(c);
ggl_init_raster(c);
c->formats = gglGetPixelFormatTable();
c->state.blend.src = GGL_ONE;
c->state.blend.dst = GGL_ZERO;
c->state.blend.src_alpha = GGL_ONE;
c->state.blend.dst_alpha = GGL_ZERO;
c->state.mask.color = 0xF;
c->state.mask.depth = 0;
c->state.mask.stencil = 0xFFFFFFFF;
c->state.logic_op.opcode = GGL_COPY;
c->state.alpha_test.func = GGL_ALWAYS;
c->state.depth_test.func = GGL_LESS;
c->state.depth_test.clearValue = FIXED_ONE;
c->shade.w0 = FIXED_ONE;
memcpy(c->ditherMatrix, gDitherMatrix, sizeof(gDitherMatrix));
}
void ggl_uninit_context(context_t* c)
{
ggl_uninit_scanline(c);
}
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
using namespace android;
ssize_t gglInit(GGLContext** context)
{
void* const base = malloc(sizeof(context_t) + 32);
if (base) {
// always align the context on cache lines
context_t *c = (context_t *)((ptrdiff_t(base)+31) & ~0x1FL);
ggl_init_context(c);
c->base = base;
*context = (GGLContext*)c;
} else {
return -1;
}
return 0;
}
ssize_t gglUninit(GGLContext* con)
{
GGL_CONTEXT(c, (void*)con);
ggl_uninit_context(c);
free(c->base);
return 0;
}

View File

@ -1,216 +0,0 @@
/* libs/pixelflinger/raster.cpp
**
** Copyright 2006, 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 <string.h>
#include "raster.h"
#include "trap.h"
namespace android {
static void ggl_rasterPos2x(void* con, GGLfixed x, GGLfixed y);
static void ggl_rasterPos2i(void* con, GGLint x, GGLint y);
static void ggl_copyPixels(void* con, GGLint xs, GGLint ys,
GGLsizei width, GGLsizei height, GGLenum type);
void ggl_init_raster(context_t* c)
{
GGLContext& procs = *(GGLContext*)c;
GGL_INIT_PROC(procs, copyPixels);
GGL_INIT_PROC(procs, rasterPos2x);
GGL_INIT_PROC(procs, rasterPos2i);
}
void ggl_rasterPos2x(void* con, GGLfixed x, GGLfixed y)
{
GGL_CONTEXT(c, con);
// raster pos should be processed just like glVertex
c->state.raster.x = x;
c->state.raster.y = y;
}
void ggl_rasterPos2i(void* con, GGLint x, GGLint y)
{
ggl_rasterPos2x(con, gglIntToFixed(x), gglIntToFixed(y));
}
void ggl_copyPixels(void* con, GGLint xs, GGLint ys,
GGLsizei width, GGLsizei height, GGLenum /*type*/)
{
GGL_CONTEXT(c, con);
// color-buffer
surface_t* cb = &(c->state.buffers.color);
// undefined behaviour if we try to copy from outside the surface
if (uint32_t(xs) > cb->width)
return;
if (uint32_t(ys) > cb->height)
return;
if (uint32_t(xs + width) > cb->width)
return;
if (uint32_t(ys + height) > cb->height)
return;
// copy to current raster position
GGLint xd = gglFixedToIntRound(c->state.raster.x);
GGLint yd = gglFixedToIntRound(c->state.raster.y);
// clip to scissor
if (xd < GGLint(c->state.scissor.left)) {
GGLint offset = GGLint(c->state.scissor.left) - xd;
xd = GGLint(c->state.scissor.left);
xs += offset;
width -= offset;
}
if (yd < GGLint(c->state.scissor.top)) {
GGLint offset = GGLint(c->state.scissor.top) - yd;
yd = GGLint(c->state.scissor.top);
ys += offset;
height -= offset;
}
if ((xd + width) > GGLint(c->state.scissor.right)) {
width = GGLint(c->state.scissor.right) - xd;
}
if ((yd + height) > GGLint(c->state.scissor.bottom)) {
height = GGLint(c->state.scissor.bottom) - yd;
}
if (width<=0 || height<=0) {
return; // nothing to copy
}
if (xs==xd && ys==yd) {
// nothing to do, but be careful, this might not be true when we support
// gglPixelTransfer, gglPixelMap and gglPixelZoom
return;
}
const GGLFormat* fp = &(c->formats[cb->format]);
uint8_t* src = reinterpret_cast<uint8_t*>(cb->data)
+ (xs + (cb->stride * ys)) * fp->size;
uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data)
+ (xd + (cb->stride * yd)) * fp->size;
const size_t bpr = cb->stride * fp->size;
const size_t rowsize = width * fp->size;
size_t yc = height;
if (ys < yd) {
// bottom to top
src += height * bpr;
dst += height * bpr;
do {
dst -= bpr;
src -= bpr;
memcpy(dst, src, rowsize);
} while (--yc);
} else {
if (ys == yd) {
// might be right to left
do {
memmove(dst, src, rowsize);
dst += bpr;
src += bpr;
} while (--yc);
} else {
// top to bottom
do {
memcpy(dst, src, rowsize);
dst += bpr;
src += bpr;
} while (--yc);
}
}
}
}; // namespace android
using namespace android;
GGLint gglBitBlit(GGLContext* con, int tmu, GGLint crop[4], GGLint where[4])
{
GGL_CONTEXT(c, (void*)con);
GGLint x = where[0];
GGLint y = where[1];
GGLint w = where[2];
GGLint h = where[3];
// exclsively enable this tmu
c->procs.activeTexture(c, tmu);
c->procs.disable(c, GGL_W_LERP);
uint32_t tmus = 1UL<<tmu;
if (c->state.enabled_tmu != tmus) {
c->activeTMU->enable = 1;
c->state.enabled_tmu = tmus;
c->state.enables |= GGL_ENABLE_TMUS;
ggl_state_changed(c, GGL_TMU_STATE);
}
const GGLint Wcr = crop[2];
const GGLint Hcr = crop[3];
if ((w == Wcr) && (h == Hcr)) {
c->procs.texGeni(c, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
c->procs.texGeni(c, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
const GGLint Ucr = crop[0];
const GGLint Vcr = crop[1];
const GGLint s0 = Ucr - x;
const GGLint t0 = Vcr - y;
c->procs.texCoord2i(c, s0, t0);
c->procs.recti(c, x, y, x+w, y+h);
} else {
int32_t texcoords[8];
x = gglIntToFixed(x);
y = gglIntToFixed(y);
// we CLAMP here, which works with premultiplied (s,t)
c->procs.texParameteri(c, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP);
c->procs.texParameteri(c, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
c->procs.texGeni(c, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
c->procs.texGeni(c, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
const GGLint Ucr = crop[0] << 16;
const GGLint Vcr = crop[1] << 16;
const GGLint Wcr = crop[2] << 16;
const GGLint Hcr = crop[3] << 16;
// computes texture coordinates (pre-multiplied)
int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt
int32_t dtdy = Hcr / h; // dtdy = ((Hcr/h)/Ht)*Ht
int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx
int32_t t0 = Vcr - gglMulx(dtdy, y); // t0 = Vcr - y * dtdy
texcoords[0] = s0;
texcoords[1] = dsdx;
texcoords[2] = 0;
texcoords[3] = t0;
texcoords[4] = 0;
texcoords[5] = dtdy;
texcoords[6] = 0;
texcoords[7] = 0;
c->procs.texCoordGradScale8xv(c, tmu, texcoords);
c->procs.recti(c,
gglFixedToIntRound(x),
gglFixedToIntRound(y),
gglFixedToIntRound(x)+w,
gglFixedToIntRound(y)+h);
}
return 0;
}

View File

@ -1,33 +0,0 @@
/* libs/pixelflinger/raster.h
**
** Copyright 2006, 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 ANDROID_GGL_RASTER_H
#define ANDROID_GGL_RASTER_H
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_raster(context_t* c);
void gglCopyPixels(void* c, GGLint x, GGLint y, GGLsizei width, GGLsizei height, GGLenum type);
void gglRasterPos2d(void* c, GGLint x, GGLint y);
}; // namespace android
#endif // ANDROID_GGL_RASTER_H

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
/* libs/pixelflinger/scanline.h
**
** Copyright 2006, 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 ANDROID_SCANLINE_H
#define ANDROID_SCANLINE_H
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_scanline(context_t* c);
void ggl_uninit_scanline(context_t* c);
void ggl_pick_scanline(context_t* c);
}; // namespace android
#endif

View File

@ -1,203 +0,0 @@
/* libs/pixelflinger/t32cb16blend.S
**
** Copyright 2006, 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.
*/
.text
.syntax unified
.balign 4
.global scanline_t32cb16blend_arm
/*
* .macro pixel
*
* \DREG is a 32-bit register containing *two* original destination RGB565
* pixels, with the even one in the low-16 bits, and the odd one in the
* high 16 bits.
*
* \SRC is a 32-bit 0xAABBGGRR pixel value, with pre-multiplied colors.
*
* \FB is a target register that will contain the blended pixel values.
*
* \ODD is either 0 or 1 and indicates if we're blending the lower or
* upper 16-bit pixels in DREG into FB
*
*
* clobbered: r6, r7, lr
*
*/
.macro pixel, DREG, SRC, FB, ODD
// SRC = 0xAABBGGRR
mov r7, \SRC, lsr #24 // sA
add r7, r7, r7, lsr #7 // sA + (sA >> 7)
rsb r7, r7, #0x100 // sA = 0x100 - (sA+(sA>>7))
1:
.if \ODD
// red
mov lr, \DREG, lsr #(16 + 11)
smulbb lr, r7, lr
mov r6, \SRC, lsr #3
and r6, r6, #0x1F
add lr, r6, lr, lsr #8
cmp lr, #0x1F
orrhs \FB, \FB, #(0x1F<<(16 + 11))
orrlo \FB, \FB, lr, lsl #(16 + 11)
// green
and r6, \DREG, #(0x3F<<(16 + 5))
smulbt r6, r7, r6
mov lr, \SRC, lsr #(8+2)
and lr, lr, #0x3F
add r6, lr, r6, lsr #(5+8)
cmp r6, #0x3F
orrhs \FB, \FB, #(0x3F<<(16 + 5))
orrlo \FB, \FB, r6, lsl #(16 + 5)
// blue
and lr, \DREG, #(0x1F << 16)
smulbt lr, r7, lr
mov r6, \SRC, lsr #(8+8+3)
and r6, r6, #0x1F
add lr, r6, lr, lsr #8
cmp lr, #0x1F
orrhs \FB, \FB, #(0x1F << 16)
orrlo \FB, \FB, lr, lsl #16
.else
// red
mov lr, \DREG, lsr #11
and lr, lr, #0x1F
smulbb lr, r7, lr
mov r6, \SRC, lsr #3
and r6, r6, #0x1F
add lr, r6, lr, lsr #8
cmp lr, #0x1F
movhs \FB, #(0x1F<<11)
movlo \FB, lr, lsl #11
// green
and r6, \DREG, #(0x3F<<5)
smulbb r6, r7, r6
mov lr, \SRC, lsr #(8+2)
and lr, lr, #0x3F
add r6, lr, r6, lsr #(5+8)
cmp r6, #0x3F
orrhs \FB, \FB, #(0x3F<<5)
orrlo \FB, \FB, r6, lsl #5
// blue
and lr, \DREG, #0x1F
smulbb lr, r7, lr
mov r6, \SRC, lsr #(8+8+3)
and r6, r6, #0x1F
add lr, r6, lr, lsr #8
cmp lr, #0x1F
orrhs \FB, \FB, #0x1F
orrlo \FB, \FB, lr
.endif
.endm
// r0: dst ptr
// r1: src ptr
// r2: count
// r3: d
// r4: s0
// r5: s1
// r6: pixel
// r7: pixel
// r8: free
// r9: free
// r10: free
// r11: free
// r12: scratch
// r14: pixel
scanline_t32cb16blend_arm:
stmfd sp!, {r4-r7, lr}
pld [r0]
pld [r1]
// align DST to 32 bits
tst r0, #0x3
beq aligned
subs r2, r2, #1
ldmfdlo sp!, {r4-r7, lr} // return
bxlo lr
last:
ldr r4, [r1], #4
ldrh r3, [r0]
pixel r3, r4, r12, 0
strh r12, [r0], #2
aligned:
subs r2, r2, #2
blo 9f
// The main loop is unrolled twice and processes 4 pixels
8: ldmia r1!, {r4, r5}
// stream the source
pld [r1, #32]
add r0, r0, #4
// it's all zero, skip this pixel
orrs r3, r4, r5
beq 7f
// load the destination
ldr r3, [r0, #-4]
// stream the destination
pld [r0, #32]
pixel r3, r4, r12, 0
pixel r3, r5, r12, 1
// effectively, we're getting write-combining by virtue of the
// cpu's write-back cache.
str r12, [r0, #-4]
// 2nd iterration of the loop, don't stream anything
subs r2, r2, #2
movlt r4, r5
blt 9f
ldmia r1!, {r4, r5}
add r0, r0, #4
orrs r3, r4, r5
beq 7f
ldr r3, [r0, #-4]
pixel r3, r4, r12, 0
pixel r3, r5, r12, 16
str r12, [r0, #-4]
7: subs r2, r2, #2
bhs 8b
mov r4, r5
9: adds r2, r2, #1
ldmfdlo sp!, {r4-r7, lr} // return
bxlo lr
b last

View File

@ -1,17 +0,0 @@
cc_defaults {
name: "pixelflinger-tests",
cflags: [
"-Wall",
"-Werror",
],
header_libs: ["libpixelflinger_internal"],
static_libs: [
"libbase",
"libcutils",
"liblog",
"libpixelflinger",
"libutils",
],
}

View File

@ -1,11 +0,0 @@
cc_defaults {
name: "pixelflinger-tests-arm64",
defaults: ["pixelflinger-tests"],
enabled: false,
arch: {
arm64: {
enabled: true,
},
},
}

View File

@ -1,9 +0,0 @@
cc_test {
name: "test-pixelflinger-arm64-assembler-test",
defaults: ["pixelflinger-tests-arm64"],
srcs: [
"arm64_assembler_test.cpp",
"asm_test_jacket.S",
],
}

View File

@ -1,782 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "codeflinger/ARMAssemblerInterface.h"
#include "codeflinger/Arm64Assembler.h"
using namespace android;
#define TESTS_DATAOP_ENABLE 1
#define TESTS_DATATRANSFER_ENABLE 1
#define TESTS_LDMSTM_ENABLE 1
#define TESTS_REG_CORRUPTION_ENABLE 0
void *instrMem;
uint32_t instrMemSize = 128 * 1024;
char dataMem[8192];
typedef void (*asm_function_t)();
extern "C" void asm_test_jacket(asm_function_t function,
int64_t regs[], int32_t flags[]);
#define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1)
const uint32_t NA = 0;
const uint32_t NUM_REGS = 32;
const uint32_t NUM_FLAGS = 16;
enum instr_t
{
INSTR_ADD,
INSTR_SUB,
INSTR_AND,
INSTR_ORR,
INSTR_RSB,
INSTR_BIC,
INSTR_CMP,
INSTR_MOV,
INSTR_MVN,
INSTR_MUL,
INSTR_MLA,
INSTR_SMULBB,
INSTR_SMULBT,
INSTR_SMULTB,
INSTR_SMULTT,
INSTR_SMULWB,
INSTR_SMULWT,
INSTR_SMLABB,
INSTR_UXTB16,
INSTR_UBFX,
INSTR_ADDR_ADD,
INSTR_ADDR_SUB,
INSTR_LDR,
INSTR_LDRB,
INSTR_LDRH,
INSTR_ADDR_LDR,
INSTR_LDM,
INSTR_STR,
INSTR_STRB,
INSTR_STRH,
INSTR_ADDR_STR,
INSTR_STM
};
enum shift_t
{
SHIFT_LSL,
SHIFT_LSR,
SHIFT_ASR,
SHIFT_ROR,
SHIFT_NONE
};
enum offset_t
{
REG_SCALE_OFFSET,
REG_OFFSET,
IMM8_OFFSET,
IMM12_OFFSET,
NO_OFFSET
};
enum cond_t
{
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
HS = CS,
LO = CC
};
const char * cc_code[] =
{
"EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
"HI", "LS","GE","LT", "GT", "LE", "AL", "NV"
};
struct dataOpTest_t
{
uint32_t id;
instr_t op;
uint32_t preFlag;
cond_t cond;
bool setFlags;
uint64_t RnValue;
uint64_t RsValue;
bool immediate;
uint32_t immValue;
uint64_t RmValue;
uint32_t shiftMode;
uint32_t shiftAmount;
uint64_t RdValue;
bool checkRd;
uint64_t postRdValue;
bool checkFlag;
uint32_t postFlag;
};
struct dataTransferTest_t
{
uint32_t id;
instr_t op;
uint32_t preFlag;
cond_t cond;
bool setMem;
uint64_t memOffset;
uint64_t memValue;
uint64_t RnValue;
offset_t offsetType;
uint64_t RmValue;
uint32_t immValue;
bool writeBack;
bool preIndex;
bool postIndex;
uint64_t RdValue;
uint64_t postRdValue;
uint64_t postRnValue;
bool checkMem;
uint64_t postMemOffset;
uint32_t postMemLength;
uint64_t postMemValue;
};
dataOpTest_t dataOpTests [] =
{
{0xA000,INSTR_ADD,AL,AL,0,1,NA,1,MAX_32BIT ,NA,NA,NA,NA,1,0,0,0},
{0xA001,INSTR_ADD,AL,AL,0,1,NA,1,MAX_32BIT -1,NA,NA,NA,NA,1,MAX_32BIT,0,0},
{0xA002,INSTR_ADD,AL,AL,0,1,NA,0,NA,MAX_32BIT ,NA,NA,NA,1,0,0,0},
{0xA003,INSTR_ADD,AL,AL,0,1,NA,0,NA,MAX_32BIT -1,NA,NA,NA,1,MAX_32BIT,0,0},
{0xA004,INSTR_ADD,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,0,NA,1,0,0,0},
{0xA005,INSTR_ADD,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,NA,1,0x80000001,0,0},
{0xA006,INSTR_ADD,AL,AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2,0,0},
{0xA007,INSTR_ADD,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,1,2,0,0},
{0xA008,INSTR_ADD,AL,AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1,0,0},
{0xA009,INSTR_ADD,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,1,0,0,0},
{0xA010,INSTR_AND,AL,AL,0,1,NA,1,MAX_32BIT ,0,0,0,NA,1,1,0,0},
{0xA011,INSTR_AND,AL,AL,0,1,NA,1,MAX_32BIT -1,0,0,0,NA,1,0,0,0},
{0xA012,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT ,0,0,NA,1,1,0,0},
{0xA013,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT -1,0,0,NA,1,0,0,0},
{0xA014,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,0,NA,1,1,0,0},
{0xA015,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,NA,1,0,0,0},
{0xA016,INSTR_AND,AL,AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1,0,0},
{0xA017,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,1,1,0,0},
{0xA018,INSTR_AND,AL,AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0,0,0},
{0xA019,INSTR_AND,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,1,1,0,0},
{0xA020,INSTR_ORR,AL,AL,0,3,NA,1,MAX_32BIT ,0,0,0,NA,1,MAX_32BIT,0,0},
{0xA021,INSTR_ORR,AL,AL,0,2,NA,1,MAX_32BIT -1,0,0,0,NA,1,MAX_32BIT-1,0,0},
{0xA022,INSTR_ORR,AL,AL,0,3,NA,0,0,MAX_32BIT ,0,0,NA,1,MAX_32BIT,0,0},
{0xA023,INSTR_ORR,AL,AL,0,2,NA,0,0,MAX_32BIT -1,0,0,NA,1,MAX_32BIT-1,0,0},
{0xA024,INSTR_ORR,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,0,NA,1,MAX_32BIT,0,0},
{0xA025,INSTR_ORR,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,NA,1,0x80000001,0,0},
{0xA026,INSTR_ORR,AL,AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1,0,0},
{0xA027,INSTR_ORR,AL,AL,0,0,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,1,1,0,0},
{0xA028,INSTR_ORR,AL,AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1,0,0},
{0xA029,INSTR_ORR,AL,AL,0,1,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,1,MAX_32BIT ,0,0},
{0xA030,INSTR_CMP,AL,AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0,1,HS},
{0xA031,INSTR_CMP,AL,AL,1,0x00000,NA,1,0x10000,0,0,0,NA,0,0,1,CC},
{0xA032,INSTR_CMP,AL,AL,1,0x00000,NA,0,0,0x10000,0,0,NA,0,0,1,LT},
{0xA033,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x10000,0,0,NA,0,0,1,EQ},
{0xA034,INSTR_CMP,AL,AL,1,0x00000,NA,0,0,0x10000,0,0,NA,0,0,1,LS},
{0xA035,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x10000,0,0,NA,0,0,1,LS},
{0xA036,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x00000,0,0,NA,0,0,1,HI},
{0xA037,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x10000,0,0,NA,0,0,1,HS},
{0xA038,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x00000,0,0,NA,0,0,1,HS},
{0xA039,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x00000,0,0,NA,0,0,1,NE},
{0xA040,INSTR_CMP,AL,AL,1,0,NA,0,0,MAX_32BIT ,SHIFT_LSR,1,NA,0,0,1,LT},
{0xA041,INSTR_CMP,AL,AL,1,1,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,0,0,1,EQ},
{0xA042,INSTR_CMP,AL,AL,1,0,NA,0,0,0x10000,SHIFT_LSR,31,NA,0,0,1,LS},
{0xA043,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x30000,SHIFT_LSR,1,NA,0,0,1,LS},
{0xA044,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x00000,SHIFT_LSR,31,NA,0,0,1,HI},
{0xA045,INSTR_CMP,AL,AL,1,1,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,0,0,1,HS},
{0xA046,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x2000,SHIFT_LSR,1,NA,0,0,1,HS},
{0xA047,INSTR_CMP,AL,AL,1,0,NA,0,0,MAX_32BIT ,SHIFT_LSR,1,NA,0,0,1,NE},
{0xA048,INSTR_CMP,AL,AL,1,0,NA,0,0,0x10000,SHIFT_ASR,2,NA,0,0,1,LT},
{0xA049,INSTR_CMP,AL,AL,1,MAX_32BIT ,NA,0,0,MAX_32BIT ,SHIFT_ASR,1,NA,0,0,1,EQ},
{0xA050,INSTR_CMP,AL,AL,1,MAX_32BIT ,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,0,0,1,LS},
{0xA051,INSTR_CMP,AL,AL,1,0,NA,0,0,0x10000,SHIFT_ASR,1,NA,0,0,1,LS},
{0xA052,INSTR_CMP,AL,AL,1,0x10000,NA,0,0,0x10000,SHIFT_ASR,1,NA,0,0,1,HI},
{0xA053,INSTR_CMP,AL,AL,1,1,NA,0,0,0x10000,SHIFT_ASR,31,NA,0,0,1,HS},
{0xA054,INSTR_CMP,AL,AL,1,1,NA,0,0,0x10000,SHIFT_ASR,16,NA,0,0,1,HS},
{0xA055,INSTR_CMP,AL,AL,1,1,NA,0,0,MAX_32BIT ,SHIFT_ASR,1,NA,0,0,1,NE},
{0xA056,INSTR_MUL,AL,AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0,0,0},
{0xA057,INSTR_MUL,AL,AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000,0,0},
{0xA058,INSTR_MUL,AL,AL,0,0,MAX_32BIT ,0,0,1,0,0,NA,1,MAX_32BIT ,0,0},
{0xA059,INSTR_MLA,AL,AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000,0,0},
{0xA060,INSTR_MLA,AL,AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000,0,0},
{0xA061,INSTR_MLA,AL,AL,1,1,MAX_32BIT ,0,0,1,0,0,NA,1,0,1,PL},
{0xA062,INSTR_MLA,AL,AL,1,0,MAX_32BIT ,0,0,1,0,0,NA,1,MAX_32BIT ,1,MI},
{0xA063,INSTR_SUB,AL,AL,1,1 << 16,NA,1,1 << 16,NA,NA,NA,NA,1,0,1,PL},
{0xA064,INSTR_SUB,AL,AL,1,(1 << 16) + 1,NA,1,1 << 16,NA,NA,NA,NA,1,1,1,PL},
{0xA065,INSTR_SUB,AL,AL,1,0,NA,1,1 << 16,NA,NA,NA,NA,1,(uint32_t)(0 - (1<<16)),1,MI},
{0xA066,INSTR_SUB,MI,MI,0,2,NA,0,NA,1,NA,NA,2,1,1,0,NA},
{0xA067,INSTR_SUB,EQ,MI,0,2,NA,0,NA,1,NA,NA,2,1,2,0,NA},
{0xA068,INSTR_SUB,GT,GE,0,2,NA,1,1,NA,NA,NA,2,1,1,0,NA},
{0xA069,INSTR_SUB,LT,GE,0,2,NA,1,1,NA,NA,NA,2,1,2,0,NA},
{0xA070,INSTR_SUB,CS,HS,0,2,NA,1,1,NA,NA,NA,2,1,1,0,NA},
{0xA071,INSTR_SUB,CC,HS,0,2,NA,1,1,NA,NA,NA,2,1,2,0,NA},
{0xA072,INSTR_SUB,AL,AL,0,1,NA,1,1 << 16,0,0,0,NA,1,(uint32_t)(1 - (1 << 16)),0,NA},
{0xA073,INSTR_SUB,AL,AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_32BIT - 1,0,NA},
{0xA074,INSTR_SUB,AL,AL,0,1,NA,1,1,0,0,0,NA,1,0,0,NA},
{0xA075,INSTR_SUB,AL,AL,0,1,NA,0,NA,1 << 16,0,0,NA,1,(uint32_t)(1 - (1 << 16)),0,NA},
{0xA076,INSTR_SUB,AL,AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_32BIT - 1,0,NA},
{0xA077,INSTR_SUB,AL,AL,0,1,NA,0,NA,1,0,0,NA,1,0,0,NA},
{0xA078,INSTR_SUB,AL,AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(uint32_t)(1 - (1 << 16)),0,NA},
{0xA079,INSTR_SUB,AL,AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,1,0,NA},
{0xA080,INSTR_SUB,AL,AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0,0,NA},
{0xA081,INSTR_SUB,AL,AL,0,1,NA,0,NA,MAX_32BIT ,SHIFT_LSR,31,NA,1,0,0,NA},
{0xA082,INSTR_RSB,GT,GE,0,2,NA,1,0,NA,NA,NA,2,1,(uint32_t)-2,0,NA},
{0xA083,INSTR_RSB,LT,GE,0,2,NA,1,0,NA,NA,NA,2,1,2,0,NA},
{0xA084,INSTR_RSB,AL,AL,0,1,NA,1,1 << 16,NA,NA,NA,NA,1,(1 << 16) - 1,0,NA},
{0xA085,INSTR_RSB,AL,AL,0,MAX_32BIT,NA,1,1,NA,NA,NA,NA,1,(uint32_t) (1 - MAX_32BIT),0,NA},
{0xA086,INSTR_RSB,AL,AL,0,1,NA,1,1,NA,NA,NA,NA,1,0,0,NA},
{0xA087,INSTR_RSB,AL,AL,0,1,NA,0,NA,1 << 16,0,0,NA,1,(1 << 16) - 1,0,NA},
{0xA088,INSTR_RSB,AL,AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,(uint32_t) (1 - MAX_32BIT),0,NA},
{0xA089,INSTR_RSB,AL,AL,0,1,NA,0,NA,1,0,0,NA,1,0,0,NA},
{0xA090,INSTR_RSB,AL,AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1 << 16) - 1,0,NA},
{0xA091,INSTR_RSB,AL,AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,(uint32_t)-1,0,NA},
{0xA092,INSTR_RSB,AL,AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0,0,NA},
{0xA093,INSTR_RSB,AL,AL,0,1,NA,0,NA,MAX_32BIT ,SHIFT_LSR,31,NA,1,0,0,NA},
{0xA094,INSTR_MOV,AL,AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0x80000001,0,0},
{0xA095,INSTR_MOV,AL,AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0x80000001,0,0},
{0xA096,INSTR_MOV,AL,AL,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,NA,1,MAX_32BIT -1,0,0},
{0xA097,INSTR_MOV,AL,AL,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,NA,1,0x80000000,0,0},
{0xA098,INSTR_MOV,AL,AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1,0,0},
{0xA099,INSTR_MOV,AL,AL,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSR,31,NA,1,1,0,0},
{0xA100,INSTR_MOV,AL,AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1,0,0},
{0xA101,INSTR_MOV,AL,AL,0,NA,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,1,MAX_32BIT ,0,0},
{0xA102,INSTR_MOV,AL,AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0x80000001,0,0},
{0xA103,INSTR_MOV,AL,AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3,0,0},
{0xA104,INSTR_MOV,AL,AL,1,NA,NA,0,0,MAX_32BIT -1,SHIFT_ASR,1,NA,1,MAX_32BIT,1,MI},
{0xA105,INSTR_MOV,AL,AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1,1,PL},
{0xA106,INSTR_MOV,PL,MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2,0,0},
{0xA107,INSTR_MOV,MI,MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0x80000001,0,0},
{0xA108,INSTR_MOV,EQ,LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2,0,0},
{0xA109,INSTR_MOV,LT,LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0x80000001,0,0},
{0xA110,INSTR_MOV,GT,GE,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,MAX_32BIT -1,0,0},
{0xA111,INSTR_MOV,EQ,GE,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,2,1,0x80000000,0,0},
{0xA112,INSTR_MOV,LT,GE,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,2,1,2,0,0},
{0xA113,INSTR_MOV,GT,LE,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2,0,0},
{0xA114,INSTR_MOV,EQ,LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0x80000001,0,0},
{0xA115,INSTR_MOV,LT,LE,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,31,2,1,0x80000000,0,0},
{0xA116,INSTR_MOV,EQ,GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2,0,0},
{0xA117,INSTR_MOV,GT,GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0x80000001,0,0},
{0xA118,INSTR_MOV,LE,GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2,0,0},
{0xA119,INSTR_MOV,EQ,GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2,0,0},
{0xA120,INSTR_MOV,GT,GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0x80000001,0,0},
{0xA121,INSTR_MOV,LE,GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2,0,0},
{0xA122,INSTR_MOV,EQ,GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2,0,0},
{0xA123,INSTR_MOV,GT,GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,MAX_32BIT -1,0,0},
{0xA124,INSTR_MOV,LE,GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2,0,0},
{0xA125,INSTR_MOV,LO,HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2,0,0},
{0xA126,INSTR_MOV,HS,HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0x80000001,0,0},
{0xA127,INSTR_MVN,LO,HS,0,NA,NA,1,MAX_32BIT -1,NA,NA,NA,2,1,2,0,0},
{0xA128,INSTR_MVN,HS,HS,0,NA,NA,1,MAX_32BIT -1,NA,NA,NA,2,1,1,0,0},
{0xA129,INSTR_MVN,AL,AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_32BIT,0,NA},
{0xA130,INSTR_MVN,AL,AL,0,NA,NA,0,NA,MAX_32BIT -1,NA,0,2,1,1,0,NA},
{0xA131,INSTR_MVN,AL,AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE,0,NA},
{0xA132,INSTR_BIC,AL,AL,0,1,NA,1,MAX_32BIT ,NA,NA,NA,NA,1,0,0,0},
{0xA133,INSTR_BIC,AL,AL,0,1,NA,1,MAX_32BIT -1,NA,NA,NA,NA,1,1,0,0},
{0xA134,INSTR_BIC,AL,AL,0,1,NA,0,0,MAX_32BIT ,0,0,NA,1,0,0,0},
{0xA135,INSTR_BIC,AL,AL,0,1,NA,0,0,MAX_32BIT -1,0,0,NA,1,1,0,0},
{0xA136,INSTR_BIC,AL,AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0,0,0},
{0xA137,INSTR_BIC,AL,AL,0,0xF0,NA,0,0,MAX_32BIT ,SHIFT_ASR,31,NA,1,0,0,0},
{0xA138,INSTR_SMULBB,AL,AL,0,NA,0xABCDFFFF,0,NA,0xABCD0001,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA139,INSTR_SMULBB,AL,AL,0,NA,0xABCD0001,0,NA,0xABCD0FFF,NA,NA,NA,1,0x00000FFF,0,0},
{0xA140,INSTR_SMULBB,AL,AL,0,NA,0xABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA141,INSTR_SMULBB,AL,AL,0,NA,0xABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,1,0,0},
{0xA142,INSTR_SMULBT,AL,AL,0,NA,0xFFFFABCD,0,NA,0xABCD0001,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA143,INSTR_SMULBT,AL,AL,0,NA,0x0001ABCD,0,NA,0xABCD0FFF,NA,NA,NA,1,0x00000FFF,0,0},
{0xA144,INSTR_SMULBT,AL,AL,0,NA,0x0001ABCD,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA145,INSTR_SMULBT,AL,AL,0,NA,0xFFFFABCD,0,NA,0xABCDFFFF,NA,NA,NA,1,1,0,0},
{0xA146,INSTR_SMULTB,AL,AL,0,NA,0xABCDFFFF,0,NA,0x0001ABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA147,INSTR_SMULTB,AL,AL,0,NA,0xABCD0001,0,NA,0x0FFFABCD,NA,NA,NA,1,0x00000FFF,0,0},
{0xA148,INSTR_SMULTB,AL,AL,0,NA,0xABCD0001,0,NA,0xFFFFABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA149,INSTR_SMULTB,AL,AL,0,NA,0xABCDFFFF,0,NA,0xFFFFABCD,NA,NA,NA,1,1,0,0},
{0xA150,INSTR_SMULTT,AL,AL,0,NA,0xFFFFABCD,0,NA,0x0001ABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA151,INSTR_SMULTT,AL,AL,0,NA,0x0001ABCD,0,NA,0x0FFFABCD,NA,NA,NA,1,0x00000FFF,0,0},
{0xA152,INSTR_SMULTT,AL,AL,0,NA,0x0001ABCD,0,NA,0xFFFFABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA153,INSTR_SMULTT,AL,AL,0,NA,0xFFFFABCD,0,NA,0xFFFFABCD,NA,NA,NA,1,1,0,0},
{0xA154,INSTR_SMULWB,AL,AL,0,NA,0xABCDFFFF,0,NA,0x0001ABCD,NA,NA,NA,1,0xFFFFFFFE,0,0},
{0xA155,INSTR_SMULWB,AL,AL,0,NA,0xABCD0001,0,NA,0x0FFFABCD,NA,NA,NA,1,0x00000FFF,0,0},
{0xA156,INSTR_SMULWB,AL,AL,0,NA,0xABCD0001,0,NA,0xFFFFABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA157,INSTR_SMULWB,AL,AL,0,NA,0xABCDFFFF,0,NA,0xFFFFABCD,NA,NA,NA,1,0,0,0},
{0xA158,INSTR_SMULWT,AL,AL,0,NA,0xFFFFABCD,0,NA,0x0001ABCD,NA,NA,NA,1,0xFFFFFFFE,0,0},
{0xA159,INSTR_SMULWT,AL,AL,0,NA,0x0001ABCD,0,NA,0x0FFFABCD,NA,NA,NA,1,0x00000FFF,0,0},
{0xA160,INSTR_SMULWT,AL,AL,0,NA,0x0001ABCD,0,NA,0xFFFFABCD,NA,NA,NA,1,0xFFFFFFFF,0,0},
{0xA161,INSTR_SMULWT,AL,AL,0,NA,0xFFFFABCD,0,NA,0xFFFFABCD,NA,NA,NA,1,0,0,0},
{0xA162,INSTR_SMLABB,AL,AL,0,1,0xABCDFFFF,0,NA,0xABCD0001,NA,NA,NA,1,0,0,0},
{0xA163,INSTR_SMLABB,AL,AL,0,1,0xABCD0001,0,NA,0xABCD0FFF,NA,NA,NA,1,0x00001000,0,0},
{0xA164,INSTR_SMLABB,AL,AL,0,0xFFFFFFFF,0xABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFE,0,0},
{0xA165,INSTR_SMLABB,AL,AL,0,0xFFFFFFFF,0xABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0,0,0},
{0xA166,INSTR_UXTB16,AL,AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001,0,0},
{0xA167,INSTR_UXTB16,AL,AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF,0,0},
{0xA168,INSTR_UXTB16,AL,AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD,0,0},
{0xA169,INSTR_UXTB16,AL,AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB,0,0},
{0xA170,INSTR_UBFX,AL,AL,0,0xABCDEF01,4,0,NA,24,NA,NA,NA,1,0x00BCDEF0,0,0},
{0xA171,INSTR_UBFX,AL,AL,0,0xABCDEF01,1,0,NA,2,NA,NA,NA,1,0,0,0},
{0xA172,INSTR_UBFX,AL,AL,0,0xABCDEF01,16,0,NA,8,NA,NA,NA,1,0xCD,0,0},
{0xA173,INSTR_UBFX,AL,AL,0,0xABCDEF01,31,0,NA,1,NA,NA,NA,1,1,0,0},
{0xA174,INSTR_ADDR_ADD,AL,AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001,0,0},
{0xA175,INSTR_ADDR_ADD,AL,AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5,0,0},
{0xA176,INSTR_ADDR_ADD,AL,AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000,0,0},
{0xA177,INSTR_ADDR_SUB,AL,AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF,0,0},
{0xA178,INSTR_ADDR_SUB,AL,AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB,0,0},
{0xA179,INSTR_ADDR_SUB,AL,AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1,0,0},
};
dataTransferTest_t dataTransferTests [] =
{
{0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA},
{0xB001,INSTR_LDR,AL,AL,1,4064,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4068,0,1,0,NA,0xABCDEF01,0,0,NA,NA,NA},
{0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA},
{0xB003,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA},
{0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA},
{0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4065,0,1,0,NA,0x67,0,0,NA,NA,NA},
{0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA},
{0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA},
{0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA},
{0xB009,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA},
{0xB010,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA},
{0xB011,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA},
{0xB012,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA},
{0xB013,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA},
{0xB014,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA},
{0xB015,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA},
{0xB016,INSTR_ADDR_LDR,AL,AL,1,4064,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4064,0,1,0,NA,0xABCDEF0123456789,0,0,NA,NA,NA},
{0xB017,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF},
{0xB018,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF},
{0xB019,INSTR_STR,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4064,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,4066,8,0xDEAD23456789BEEF},
{0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
{0xB021,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF},
{0xB022,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF},
{0xB023,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF},
{0xB024,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
{0xB025,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM12_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF},
{0xB026,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB027,INSTR_STRH,EQ,NE,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB028,INSTR_STRH,NE,NE,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB029,INSTR_STRH,NE,EQ,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB030,INSTR_STRH,EQ,EQ,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB031,INSTR_STRH,HI,LS,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB032,INSTR_STRH,LS,LS,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB033,INSTR_STRH,LS,HI,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB034,INSTR_STRH,HI,HI,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB035,INSTR_STRH,CC,HS,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB036,INSTR_STRH,CS,HS,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB037,INSTR_STRH,GE,LT,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEADBEEFDEADBEEF},
{0xB038,INSTR_STRH,LT,LT,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
{0xB039,INSTR_ADDR_STR,AL,AL,1,4064,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4060,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,4064,8,0xABCDEF0123456789},
};
void flushcache()
{
const long base = long(instrMem);
const long curr = base + long(instrMemSize);
__builtin___clear_cache((char*)base, (char*)curr);
}
void dataOpTest(dataOpTest_t test, ARMAssemblerInterface *a64asm, uint32_t Rd = 0,
uint32_t Rn = 1, uint32_t Rm = 2, uint32_t Rs = 3)
{
int64_t regs[NUM_REGS] = {0};
int32_t flags[NUM_FLAGS] = {0};
int64_t savedRegs[NUM_REGS] = {0};
uint32_t i;
uint32_t op2;
for(i = 0; i < NUM_REGS; ++i)
{
regs[i] = i;
}
regs[Rd] = test.RdValue;
regs[Rn] = test.RnValue;
regs[Rs] = test.RsValue;
flags[test.preFlag] = 1;
a64asm->reset();
a64asm->prolog();
if(test.immediate == true)
{
op2 = a64asm->imm(test.immValue);
}
else if(test.immediate == false && test.shiftAmount == 0)
{
op2 = Rm;
regs[Rm] = test.RmValue;
}
else
{
op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount);
regs[Rm] = test.RmValue;
}
switch(test.op)
{
case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break;
case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break;
case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break;
case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break;
case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break;
case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break;
case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break;
case INSTR_UBFX:
{
int32_t lsb = test.RsValue;
int32_t width = test.RmValue;
a64asm->UBFX(test.cond, Rd,Rn,lsb, width);
break;
}
case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
default: printf("Error"); return;
}
a64asm->epilog(0);
flushcache();
asm_function_t asm_function = (asm_function_t)(instrMem);
for(i = 0; i < NUM_REGS; ++i)
savedRegs[i] = regs[i];
asm_test_jacket(asm_function, regs, flags);
/* Check if all regs except Rd is same */
for(i = 0; i < NUM_REGS; ++i)
{
if(i == Rd) continue;
if(regs[i] != savedRegs[i])
{
printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 "),"
"Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i],
regs[i]);
return;
}
}
if(test.checkRd == 1 && (uint64_t)regs[Rd] != test.postRdValue)
{
printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n",
test.id, test.postRdValue, regs[Rd]);
}
else if(test.checkFlag == 1 && flags[test.postFlag] == 0)
{
printf("Test %x failed Flag(%s) NOT set\n",
test.id,cc_code[test.postFlag]);
}
else
{
printf("Test %x passed\n", test.id);
}
}
void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm,
uint32_t Rd = 0, uint32_t Rn = 1,uint32_t Rm = 2)
{
int64_t regs[NUM_REGS] = {0};
int64_t savedRegs[NUM_REGS] = {0};
int32_t flags[NUM_FLAGS] = {0};
uint32_t i;
for(i = 0; i < NUM_REGS; ++i)
{
regs[i] = i;
}
uint32_t op2;
regs[Rd] = test.RdValue;
regs[Rn] = (uint64_t)(&dataMem[test.RnValue]);
regs[Rm] = test.RmValue;
flags[test.preFlag] = 1;
if(test.setMem == true)
{
unsigned char *mem = (unsigned char *)&dataMem[test.memOffset];
uint64_t value = test.memValue;
for(int j = 0; j < 8; ++j)
{
mem[j] = value & 0x00FF;
value >>= 8;
}
}
a64asm->reset();
a64asm->prolog();
if(test.offsetType == REG_SCALE_OFFSET)
{
op2 = a64asm->reg_scale_pre(Rm);
}
else if(test.offsetType == REG_OFFSET)
{
op2 = a64asm->reg_pre(Rm);
}
else if(test.offsetType == IMM12_OFFSET && test.preIndex == true)
{
op2 = a64asm->immed12_pre(test.immValue, test.writeBack);
}
else if(test.offsetType == IMM12_OFFSET && test.postIndex == true)
{
op2 = a64asm->immed12_post(test.immValue);
}
else if(test.offsetType == IMM8_OFFSET && test.preIndex == true)
{
op2 = a64asm->immed8_pre(test.immValue, test.writeBack);
}
else if(test.offsetType == IMM8_OFFSET && test.postIndex == true)
{
op2 = a64asm->immed8_post(test.immValue);
}
else if(test.offsetType == NO_OFFSET)
{
op2 = a64asm->__immed12_pre(0);
}
else
{
printf("Error - Unknown offset\n"); return;
}
switch(test.op)
{
case INSTR_LDR: a64asm->LDR(test.cond, Rd,Rn,op2); break;
case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break;
case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break;
case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break;
case INSTR_STR: a64asm->STR(test.cond, Rd,Rn,op2); break;
case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break;
case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break;
case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break;
default: printf("Error"); return;
}
a64asm->epilog(0);
flushcache();
asm_function_t asm_function = (asm_function_t)(instrMem);
for(i = 0; i < NUM_REGS; ++i)
savedRegs[i] = regs[i];
asm_test_jacket(asm_function, regs, flags);
/* Check if all regs except Rd/Rn are same */
for(i = 0; i < NUM_REGS; ++i)
{
if(i == Rd || i == Rn) continue;
if(regs[i] != savedRegs[i])
{
printf("Test %x failed Reg(%d) tampered"
" Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n",
test.id, i, savedRegs[i], regs[i]);
return;
}
}
if((uint64_t)regs[Rd] != test.postRdValue)
{
printf("Test %x failed, "
"Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postRdValue, regs[Rd]);
}
else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue]))
{
printf("Test %x failed, "
"Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem);
}
else if(test.checkMem == true)
{
unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset];
uint64_t value;
value = 0;
for(uint32_t j = 0; j < test.postMemLength; ++j)
value = (value << 8) | addr[test.postMemLength-j-1];
if(value != test.postMemValue)
{
printf("Test %x failed, "
"Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postMemValue, value);
}
else
{
printf("Test %x passed\n", test.id);
}
}
else
{
printf("Test %x passed\n", test.id);
}
}
void dataTransferLDMSTM(ARMAssemblerInterface *a64asm)
{
int64_t regs[NUM_REGS] = {0};
int32_t flags[NUM_FLAGS] = {0};
const uint32_t numArmv7Regs = 16;
uint32_t Rn = ARMAssemblerInterface::SP;
uint32_t patterns[] =
{
0x5A03,
0x4CF0,
0x1EA6,
0x0DBF,
};
uint32_t i, j;
for(i = 0; i < sizeof(patterns)/sizeof(uint32_t); ++i)
{
for(j = 0; j < NUM_REGS; ++j)
{
regs[j] = j;
}
a64asm->reset();
a64asm->prolog();
a64asm->STM(AL,ARMAssemblerInterface::DB,Rn,1,patterns[i]);
for(j = 0; j < numArmv7Regs; ++j)
{
uint32_t op2 = a64asm->imm(0x31);
a64asm->MOV(AL, 0,j,op2);
}
a64asm->LDM(AL,ARMAssemblerInterface::IA,Rn,1,patterns[i]);
a64asm->epilog(0);
flushcache();
asm_function_t asm_function = (asm_function_t)(instrMem);
asm_test_jacket(asm_function, regs, flags);
for(j = 0; j < numArmv7Regs; ++j)
{
if((1 << j) & patterns[i])
{
if(regs[j] != j)
{
printf("LDM/STM Test %x failed "
"Reg%d expected(0x%x) Actual(0x%" PRIx64 ") \n",
patterns[i], j, j, regs[j]);
break;
}
}
}
if(j == numArmv7Regs)
printf("LDM/STM Test %x passed\n", patterns[i]);
}
}
int main(void)
{
uint32_t i;
/* Allocate memory to store instructions generated by ArmToArm64Assembler */
{
int fd = ashmem_create_region("code cache", instrMemSize);
if(fd < 0)
printf("Creating code cache, ashmem_create_region "
"failed with error '%s'", strerror(errno));
instrMem = mmap(NULL, instrMemSize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE, fd, 0);
}
ArmToArm64Assembler a64asm(instrMem);
if(TESTS_DATAOP_ENABLE)
{
printf("Running data processing tests\n");
for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i)
dataOpTest(dataOpTests[i], &a64asm);
}
if(TESTS_DATATRANSFER_ENABLE)
{
printf("Running data transfer tests\n");
for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i)
dataTransferTest(dataTransferTests[i], &a64asm);
}
if(TESTS_LDMSTM_ENABLE)
{
printf("Running LDM/STM tests\n");
dataTransferLDMSTM(&a64asm);
}
if(TESTS_REG_CORRUPTION_ENABLE)
{
uint32_t reg_list[] = {0,1,12,14};
uint32_t Rd, Rm, Rs, Rn;
uint32_t i;
uint32_t numRegs = sizeof(reg_list)/sizeof(uint32_t);
printf("Running Register corruption tests\n");
for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i)
{
for(Rd = 0; Rd < numRegs; ++Rd)
{
for(Rn = 0; Rn < numRegs; ++Rn)
{
for(Rm = 0; Rm < numRegs; ++Rm)
{
for(Rs = 0; Rs < numRegs;++Rs)
{
if(Rd == Rn || Rd == Rm || Rd == Rs) continue;
if(Rn == Rm || Rn == Rs) continue;
if(Rm == Rs) continue;
printf("Testing combination Rd(%d), Rn(%d),"
" Rm(%d), Rs(%d): ",
reg_list[Rd], reg_list[Rn], reg_list[Rm], reg_list[Rs]);
dataOpTest(dataOpTests[i], &a64asm, reg_list[Rd],
reg_list[Rn], reg_list[Rm], reg_list[Rs]);
}
}
}
}
}
}
return 0;
}

View File

@ -1,221 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
.text
.balign 0
.global asm_test_jacket
// Set the register and flag values
// Calls the asm function
// Reads the register/flag values to output register
// Parameters
// X0 - Function to jump
// X1 - register values array
// X2 - flag values array
asm_test_jacket:
// Save registers to stack
stp x29, x30, [sp,#-16]!
stp x27, x28, [sp,#-16]!
mov x30, x0
mov x28, x1
mov x27, x2
//Set the flags based on flag array
//EQ
ldr w0, [x27,#0]
cmp w0, #1
b.ne bt_aeq
cmp w0,#1
b bt_end
bt_aeq:
//NE
ldr w0, [x27,#4]
cmp w0, #1
b.ne bt_ane
cmp w0,#2
b bt_end
bt_ane:
//CS
ldr w0, [x27,#8]
cmp w0, #1
b.ne bt_acs
cmp w0,#0
b bt_end
bt_acs:
//CC
ldr w0, [x27,#12]
cmp w0, #1
b.ne bt_acc
cmp w0,#2
b bt_end
bt_acc:
//MI
ldr w0, [x27,#16]
cmp w0, #1
b.ne bt_ami
subs w0,w0,#2
b bt_end
bt_ami:
//PL
ldr w0, [x27,#20]
cmp w0, #1
b.ne bt_apl
subs w0,w0,#0
b bt_end
bt_apl:
//HI - (C==1) && (Z==0)
ldr w0, [x27,#32]
cmp w0, #1
b.ne bt_ahi
cmp w0,#0
b bt_end
bt_ahi:
//LS - (C==0) || (Z==1)
ldr w0, [x27,#36]
cmp w0, #1
b.ne bt_als
cmp w0,#1
b bt_end
bt_als:
//GE
ldr w0, [x27,#40]
cmp w0, #1
b.ne bt_age
cmp w0,#0
b bt_end
bt_age:
//LT
ldr w0, [x27,#44]
cmp w0, #1
b.ne bt_alt
cmp w0,#2
b bt_end
bt_alt:
//GT
ldr w0, [x27,#48]
cmp w0, #1
b.ne bt_agt
cmp w0,#0
b bt_end
bt_agt:
//LE
ldr w0, [x27,#52]
cmp w0, #1
b.ne bt_ale
cmp w0,#2
b bt_end
bt_ale:
bt_end:
// Load the registers from reg array
ldr x0, [x28,#0]
ldr x1, [x28,#8]
ldr x2, [x28,#16]
ldr x3, [x28,#24]
ldr x4, [x28,#32]
ldr x5, [x28,#40]
ldr x6, [x28,#48]
ldr x7, [x28,#56]
ldr x8, [x28,#64]
ldr x9, [x28,#72]
ldr x10, [x28,#80]
ldr x11, [x28,#88]
ldr x12, [x28,#96]
ldr x14, [x28,#112]
// Call the function
blr X30
// Save the registers to reg array
str x0, [x28,#0]
str x1, [x28,#8]
str x2, [x28,#16]
str x3, [x28,#24]
str x4, [x28,#32]
str x5, [x28,#40]
str x6, [x28,#48]
str x7, [x28,#56]
str x8, [x28,#64]
str x9, [x28,#72]
str x10, [x28,#80]
str x11, [x28,#88]
str x12, [x28,#96]
str x14, [x28,#112]
//Set the flags array based on result flags
movz w0, #0
movz w1, #1
csel w2, w1, w0, EQ
str w2, [x27,#0]
csel w2, w1, w0, NE
str w2, [x27,#4]
csel w2, w1, w0, CS
str w2, [x27,#8]
csel w2, w1, w0, CC
str w2, [x27,#12]
csel w2, w1, w0, MI
str w2, [x27,#16]
csel w2, w1, w0, PL
str w2, [x27,#20]
csel w2, w1, w0, VS
str w2, [x27,#24]
csel w2, w1, w0, VC
str w2, [x27,#28]
csel w2, w1, w0, HI
str w2, [x27,#32]
csel w2, w1, w0, LS
str w2, [x27,#36]
csel w2, w1, w0, GE
str w2, [x27,#40]
csel w2, w1, w0, LT
str w2, [x27,#44]
csel w2, w1, w0, GT
str w2, [x27,#48]
csel w2, w1, w0, LE
str w2, [x27,#52]
// Restore registers from stack
ldp x27, x28, [sp],#16
ldp x29, x30, [sp],#16
ret

View File

@ -1,6 +0,0 @@
cc_test {
name: "test-pixelflinger-arm64-col32cb16blend",
defaults: ["pixelflinger-tests-arm64"],
srcs: ["col32cb16blend_test.c"],
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define ARGB_8888_MAX 0xFFFFFFFF
#define ARGB_8888_MIN 0x00000000
#define RGB_565_MAX 0xFFFF
#define RGB_565_MIN 0x0000
struct test_t
{
char name[256];
uint32_t dst_color;
uint32_t src_color;
size_t count;
};
struct test_t tests[] =
{
{"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
{"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
{"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
{"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
{"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
{"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
{"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
{"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
{"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
{"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
};
void scanline_col32cb16blend_arm64(uint16_t *dst, int32_t src, size_t count);
void scanline_col32cb16blend_c(uint16_t * dst, int32_t src, size_t count)
{
int srcAlpha = (src>>24);
int f = 0x100 - (srcAlpha + (srcAlpha>>7));
while (count--)
{
uint16_t d = *dst;
int dstR = (d>>11)&0x1f;
int dstG = (d>>5)&0x3f;
int dstB = (d)&0x1f;
int srcR = (src >> ( 3))&0x1F;
int srcG = (src >> ( 8+2))&0x3F;
int srcB = (src >> (16+3))&0x1F;
srcR += (f*dstR)>>8;
srcG += (f*dstG)>>8;
srcB += (f*dstB)>>8;
*dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
}
}
void scanline_col32cb16blend_test()
{
uint16_t dst_c[16], dst_asm[16];
uint32_t i, j;
for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
{
struct test_t test = tests[i];
printf("Testing - %s:",test.name);
memset(dst_c, 0, sizeof(dst_c));
memset(dst_asm, 0, sizeof(dst_asm));
for(j = 0; j < test.count; ++j)
{
dst_c[j] = test.dst_color;
dst_asm[j] = test.dst_color;
}
scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
scanline_col32cb16blend_arm64(dst_asm, test.src_color, test.count);
if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
printf("Passed\n");
else
printf("Failed\n");
for(j = 0; j < test.count; ++j)
{
printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
}
}
}
int main()
{
scanline_col32cb16blend_test();
return 0;
}

View File

@ -1,6 +0,0 @@
cc_test {
name: "test-pixelflinger-arm64-disassembler-test",
defaults: ["pixelflinger-tests-arm64"],
srcs: ["arm64_diassembler_test.cpp"],
}

View File

@ -1,321 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
int arm64_disassemble(uint32_t code, char* instr);
struct test_table_entry_t
{
uint32_t code;
const char *instr;
};
static test_table_entry_t test_table [] =
{
{ 0x91000240, "add x0, x18, #0x0, lsl #0" },
{ 0x9140041f, "add sp, x0, #0x1, lsl #12" },
{ 0x917ffff2, "add x18, sp, #0xfff, lsl #12" },
{ 0xd13ffe40, "sub x0, x18, #0xfff, lsl #0" },
{ 0xd140001f, "sub sp, x0, #0x0, lsl #12" },
{ 0xd14007f2, "sub x18, sp, #0x1, lsl #12" },
{ 0x8b1e0200, "add x0, x16, x30, lsl #0" },
{ 0x8b507fdf, "add xzr, x30, x16, lsr #31" },
{ 0x8b8043f0, "add x16, xzr, x0, asr #16" },
{ 0x8b5f401e, "add x30, x0, xzr, lsr #16" },
{ 0x4b1e0200, "sub w0, w16, w30, lsl #0" },
{ 0x4b507fdf, "sub wzr, w30, w16, lsr #31" },
{ 0x4b8043f0, "sub w16, wzr, w0, asr #16" },
{ 0x4b5f401e, "sub w30, w0, wzr, lsr #16" },
{ 0x6b1e0200, "subs w0, w16, w30, lsl #0" },
{ 0x6b507fdf, "subs wzr, w30, w16, lsr #31" },
{ 0x6b8043f0, "subs w16, wzr, w0, asr #16" },
{ 0x6b5f401e, "subs w30, w0, wzr, lsr #16" },
{ 0x0a1e0200, "and w0, w16, w30, lsl #0" },
{ 0x0a507fdf, "and wzr, w30, w16, lsr #31" },
{ 0x0a8043f0, "and w16, wzr, w0, asr #16" },
{ 0x0adf401e, "and w30, w0, wzr, ror #16" },
{ 0x2a1e0200, "orr w0, w16, w30, lsl #0" },
{ 0x2a507fdf, "orr wzr, w30, w16, lsr #31" },
{ 0x2a8043f0, "orr w16, wzr, w0, asr #16" },
{ 0x2adf401e, "orr w30, w0, wzr, ror #16" },
{ 0x2a3e0200, "orn w0, w16, w30, lsl #0" },
{ 0x2a707fdf, "orn wzr, w30, w16, lsr #31" },
{ 0x2aa043f0, "orn w16, wzr, w0, asr #16" },
{ 0x2aff401e, "orn w30, w0, wzr, ror #16" },
{ 0x729fffe0, "movk w0, #0xffff, lsl #0" },
{ 0x72a0000f, "movk w15, #0x0, lsl #16" },
{ 0x7281fffe, "movk w30, #0xfff, lsl #0" },
{ 0x72a0003f, "movk wzr, #0x1, lsl #16" },
{ 0x529fffe0, "movz w0, #0xffff, lsl #0" },
{ 0x52a0000f, "movz w15, #0x0, lsl #16" },
{ 0x5281fffe, "movz w30, #0xfff, lsl #0" },
{ 0x52a0003f, "movz wzr, #0x1, lsl #16" },
{ 0xd29fffe0, "movz x0, #0xffff, lsl #0" },
{ 0xd2a0000f, "movz x15, #0x0, lsl #16" },
{ 0xd2c1fffe, "movz x30, #0xfff, lsl #32" },
{ 0xd2e0003f, "movz xzr, #0x1, lsl #48" },
{ 0x1a8003e0, "csel w0, wzr, w0, eq" },
{ 0x1a831001, "csel w1, w0, w3, ne" },
{ 0x1a9e2022, "csel w2, w1, w30, cs" },
{ 0x1a8a3083, "csel w3, w4, w10, cc" },
{ 0x1a8b40e4, "csel w4, w7, w11, mi" },
{ 0x1a9b5105, "csel w5, w8, w27, pl" },
{ 0x1a846167, "csel w7, w11, w4, vs" },
{ 0x1a8671c8, "csel w8, w14, w6, vc" },
{ 0x1a878289, "csel w9, w20, w7, hi" },
{ 0x1a8c92aa, "csel w10, w21, w12, ls" },
{ 0x1a8ea2ce, "csel w14, w22, w14, ge" },
{ 0x1a9fb3b2, "csel w18, w29, wzr, lt" },
{ 0x1a9fc3d8, "csel w24, w30, wzr, gt" },
{ 0x1a82d17e, "csel w30, w11, w2, le" },
{ 0x1a81e19f, "csel wzr, w12, w1, al" },
{ 0x9a8003e0, "csel x0, xzr, x0, eq" },
{ 0x9a831001, "csel x1, x0, x3, ne" },
{ 0x9a9e2022, "csel x2, x1, x30, cs" },
{ 0x9a8a3083, "csel x3, x4, x10, cc" },
{ 0x9a8b40e4, "csel x4, x7, x11, mi" },
{ 0x9a9b5105, "csel x5, x8, x27, pl" },
{ 0x9a846167, "csel x7, x11, x4, vs" },
{ 0x9a8671c8, "csel x8, x14, x6, vc" },
{ 0x9a878289, "csel x9, x20, x7, hi" },
{ 0x9a8c92aa, "csel x10, x21, x12, ls" },
{ 0x9a8ea2ce, "csel x14, x22, x14, ge" },
{ 0x9a9fb3b2, "csel x18, x29, xzr, lt" },
{ 0x9a9fc3d8, "csel x24, x30, xzr, gt" },
{ 0x9a82d17e, "csel x30, x11, x2, le" },
{ 0x9a81e19f, "csel xzr, x12, x1, al" },
{ 0x5a8003e0, "csinv w0, wzr, w0, eq" },
{ 0x5a831001, "csinv w1, w0, w3, ne" },
{ 0x5a9e2022, "csinv w2, w1, w30, cs" },
{ 0x5a8a3083, "csinv w3, w4, w10, cc" },
{ 0x5a8b40e4, "csinv w4, w7, w11, mi" },
{ 0x5a9b5105, "csinv w5, w8, w27, pl" },
{ 0x5a846167, "csinv w7, w11, w4, vs" },
{ 0x5a8671c8, "csinv w8, w14, w6, vc" },
{ 0x5a878289, "csinv w9, w20, w7, hi" },
{ 0x5a8c92aa, "csinv w10, w21, w12, ls" },
{ 0x5a8ea2ce, "csinv w14, w22, w14, ge" },
{ 0x5a9fb3b2, "csinv w18, w29, wzr, lt" },
{ 0x5a9fc3d8, "csinv w24, w30, wzr, gt" },
{ 0x5a82d17e, "csinv w30, w11, w2, le" },
{ 0x5a81e19f, "csinv wzr, w12, w1, al" },
{ 0x1b1f3fc0, "madd w0, w30, wzr, w15" },
{ 0x1b0079ef, "madd w15, w15, w0, w30" },
{ 0x1b0f7ffe, "madd w30, wzr, w15, wzr" },
{ 0x1b1e001f, "madd wzr, w0, w30, w0" },
{ 0x9b3f3fc0, "smaddl x0, w30, wzr, x15" },
{ 0x9b2079ef, "smaddl x15, w15, w0, x30" },
{ 0x9b2f7ffe, "smaddl x30, wzr, w15, xzr" },
{ 0x9b3e001f, "smaddl xzr, w0, w30, x0" },
{ 0xd65f0000, "ret x0" },
{ 0xd65f01e0, "ret x15" },
{ 0xd65f03c0, "ret x30" },
{ 0xd65f03e0, "ret xzr" },
{ 0xb87f4be0, "ldr w0, [sp, wzr, uxtw #0]" },
{ 0xb87ed80f, "ldr w15, [x0, w30, sxtw #2]" },
{ 0xb86fc9fe, "ldr w30, [x15, w15, sxtw #0]" },
{ 0xb8605bdf, "ldr wzr, [x30, w0, uxtw #2]" },
{ 0xb87febe0, "ldr w0, [sp, xzr, sxtx #0]" },
{ 0xb87e780f, "ldr w15, [x0, x30, lsl #2]" },
{ 0xb86f69fe, "ldr w30, [x15, x15, lsl #0]" },
{ 0xb860fbdf, "ldr wzr, [x30, x0, sxtx #2]" },
{ 0xb83f4be0, "str w0, [sp, wzr, uxtw #0]" },
{ 0xb83ed80f, "str w15, [x0, w30, sxtw #2]" },
{ 0xb82fc9fe, "str w30, [x15, w15, sxtw #0]" },
{ 0xb8205bdf, "str wzr, [x30, w0, uxtw #2]" },
{ 0xb83febe0, "str w0, [sp, xzr, sxtx #0]" },
{ 0xb83e780f, "str w15, [x0, x30, lsl #2]" },
{ 0xb82f69fe, "str w30, [x15, x15, lsl #0]" },
{ 0xb820fbdf, "str wzr, [x30, x0, sxtx #2]" },
{ 0x787f4be0, "ldrh w0, [sp, wzr, uxtw #0]" },
{ 0x787ed80f, "ldrh w15, [x0, w30, sxtw #1]" },
{ 0x786fc9fe, "ldrh w30, [x15, w15, sxtw #0]" },
{ 0x78605bdf, "ldrh wzr, [x30, w0, uxtw #1]" },
{ 0x787febe0, "ldrh w0, [sp, xzr, sxtx #0]" },
{ 0x787e780f, "ldrh w15, [x0, x30, lsl #1]" },
{ 0x786f69fe, "ldrh w30, [x15, x15, lsl #0]" },
{ 0x7860fbdf, "ldrh wzr, [x30, x0, sxtx #1]" },
{ 0x783f4be0, "strh w0, [sp, wzr, uxtw #0]" },
{ 0x783ed80f, "strh w15, [x0, w30, sxtw #1]" },
{ 0x782fc9fe, "strh w30, [x15, w15, sxtw #0]" },
{ 0x78205bdf, "strh wzr, [x30, w0, uxtw #1]" },
{ 0x783febe0, "strh w0, [sp, xzr, sxtx #0]" },
{ 0x783e780f, "strh w15, [x0, x30, lsl #1]" },
{ 0x782f69fe, "strh w30, [x15, x15, lsl #0]" },
{ 0x7820fbdf, "strh wzr, [x30, x0, sxtx #1]" },
{ 0x387f5be0, "ldrb w0, [sp, wzr, uxtw #0]" },
{ 0x387ec80f, "ldrb w15, [x0, w30, sxtw ]" },
{ 0x386fd9fe, "ldrb w30, [x15, w15, sxtw #0]" },
{ 0x38604bdf, "ldrb wzr, [x30, w0, uxtw ]" },
{ 0x387ffbe0, "ldrb w0, [sp, xzr, sxtx #0]" },
{ 0x387e780f, "ldrb w15, [x0, x30, lsl #0]" },
{ 0x386f79fe, "ldrb w30, [x15, x15, lsl #0]" },
{ 0x3860ebdf, "ldrb wzr, [x30, x0, sxtx ]" },
{ 0x383f5be0, "strb w0, [sp, wzr, uxtw #0]" },
{ 0x383ec80f, "strb w15, [x0, w30, sxtw ]" },
{ 0x382fd9fe, "strb w30, [x15, w15, sxtw #0]" },
{ 0x38204bdf, "strb wzr, [x30, w0, uxtw ]" },
{ 0x383ffbe0, "strb w0, [sp, xzr, sxtx #0]" },
{ 0x383e780f, "strb w15, [x0, x30, lsl #0]" },
{ 0x382f79fe, "strb w30, [x15, x15, lsl #0]" },
{ 0x3820ebdf, "strb wzr, [x30, x0, sxtx ]" },
{ 0xf87f4be0, "ldr x0, [sp, wzr, uxtw #0]" },
{ 0xf87ed80f, "ldr x15, [x0, w30, sxtw #3]" },
{ 0xf86fc9fe, "ldr x30, [x15, w15, sxtw #0]" },
{ 0xf8605bdf, "ldr xzr, [x30, w0, uxtw #3]" },
{ 0xf87febe0, "ldr x0, [sp, xzr, sxtx #0]" },
{ 0xf87e780f, "ldr x15, [x0, x30, lsl #3]" },
{ 0xf86f69fe, "ldr x30, [x15, x15, lsl #0]" },
{ 0xf860fbdf, "ldr xzr, [x30, x0, sxtx #3]" },
{ 0xf83f4be0, "str x0, [sp, wzr, uxtw #0]" },
{ 0xf83ed80f, "str x15, [x0, w30, sxtw #3]" },
{ 0xf82fc9fe, "str x30, [x15, w15, sxtw #0]" },
{ 0xf8205bdf, "str xzr, [x30, w0, uxtw #3]" },
{ 0xf83febe0, "str x0, [sp, xzr, sxtx #0]" },
{ 0xf83e780f, "str x15, [x0, x30, lsl #3]" },
{ 0xf82f69fe, "str x30, [x15, x15, lsl #0]" },
{ 0xf820fbdf, "str xzr, [x30, x0, sxtx #3]" },
{ 0xb85007e0, "ldr w0, [sp], #-256" },
{ 0xb840040f, "ldr w15, [x0], #0" },
{ 0xb84015fe, "ldr w30, [x15], #1" },
{ 0xb84ff7df, "ldr wzr, [x30], #255" },
{ 0xb8100fe0, "str w0, [sp, #-256]!" },
{ 0xb8000c0f, "str w15, [x0, #0]!" },
{ 0xb8001dfe, "str w30, [x15, #1]!" },
{ 0xb80fffdf, "str wzr, [x30, #255]!" },
{ 0x13017be0, "sbfm w0, wzr, #1, #30" },
{ 0x131e7fcf, "sbfm w15, w30, #30, #31" },
{ 0x131f01fe, "sbfm w30, w15, #31, #0" },
{ 0x1300041f, "sbfm wzr, w0, #0, #1" },
{ 0x53017be0, "ubfm w0, wzr, #1, #30" },
{ 0x531e7fcf, "ubfm w15, w30, #30, #31" },
{ 0x531f01fe, "ubfm w30, w15, #31, #0" },
{ 0x5300041f, "ubfm wzr, w0, #0, #1" },
{ 0xd3417fe0, "ubfm x0, xzr, #1, #31" },
{ 0xd35fffcf, "ubfm x15, x30, #31, #63" },
{ 0xd35f01fe, "ubfm x30, x15, #31, #0" },
{ 0xd340041f, "ubfm xzr, x0, #0, #1" },
{ 0x139e7be0, "extr w0, wzr, w30, #30" },
{ 0x138f7fcf, "extr w15, w30, w15, #31" },
{ 0x138001fe, "extr w30, w15, w0, #0" },
{ 0x139f041f, "extr wzr, w0, wzr, #1" },
{ 0x54000020, "b.eq #.+4" },
{ 0x54000201, "b.ne #.+64" },
{ 0x54000802, "b.cs #.+256" },
{ 0x54002003, "b.cc #.+1024" },
{ 0x54008004, "b.mi #.+4096" },
{ 0x54ffffe5, "b.pl #.-4" },
{ 0x54ffff06, "b.vs #.-32" },
{ 0x54fffc07, "b.vc #.-128" },
{ 0x54fff008, "b.hi #.-512" },
{ 0x54000049, "b.ls #.+8" },
{ 0x5400006a, "b.ge #.+12" },
{ 0x5400008b, "b.lt #.+16" },
{ 0x54ffffcc, "b.gt #.-8" },
{ 0x54ffffad, "b.le #.-12" },
{ 0x54ffff8e, "b.al #.-16" },
{ 0x8b2001e0, "add x0, x15, w0, uxtb #0" },
{ 0x8b2f27cf, "add x15, x30, w15, uxth #1" },
{ 0x8b3e4bfe, "add x30, sp, w30, uxtw #2" },
{ 0x8b3f6c1f, "add sp, x0, xzr, uxtx #3" },
{ 0x8b2091e0, "add x0, x15, w0, sxtb #4" },
{ 0x8b2fa3cf, "add x15, x30, w15, sxth #0" },
{ 0x8b3ec7fe, "add x30, sp, w30, sxtw #1" },
{ 0x8b3fe81f, "add sp, x0, xzr, sxtx #2" },
{ 0xcb2001e0, "sub x0, x15, w0, uxtb #0" },
{ 0xcb2f27cf, "sub x15, x30, w15, uxth #1" },
{ 0xcb3e4bfe, "sub x30, sp, w30, uxtw #2" },
{ 0xcb3f6c1f, "sub sp, x0, xzr, uxtx #3" },
{ 0xcb2091e0, "sub x0, x15, w0, sxtb #4" },
{ 0xcb2fa3cf, "sub x15, x30, w15, sxth #0" },
{ 0xcb3ec7fe, "sub x30, sp, w30, sxtw #1" },
{ 0xcb3fe81f, "sub sp, x0, xzr, sxtx #2" }
};
int main()
{
char instr[256];
uint32_t failed = 0;
for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
{
test_table_entry_t *test;
test = &test_table[i];
arm64_disassemble(test->code, instr);
if(strcmp(instr, test->instr) != 0)
{
printf("Test Failed \n"
"Code : 0x%0x\n"
"Expected : %s\n"
"Actual : %s\n", test->code, test->instr, instr);
failed++;
}
}
if(failed == 0)
{
printf("All tests PASSED\n");
return 0;
}
else
{
printf("%d tests FAILED\n", failed);
return -1;
}
}

View File

@ -1,6 +0,0 @@
cc_test {
name: "test-pixelflinger-arm64-t32cb16blend",
defaults: ["pixelflinger-tests-arm64"],
srcs: ["t32cb16blend_test.c"],
}

View File

@ -1,134 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define ARGB_8888_MAX 0xFFFFFFFF
#define ARGB_8888_MIN 0x00000000
#define RGB_565_MAX 0xFFFF
#define RGB_565_MIN 0x0000
struct test_t
{
char name[256];
uint32_t src_color;
uint16_t dst_color;
size_t count;
};
struct test_t tests[] =
{
{"Count 0", 0, 0, 0},
{"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
{"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
{"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
{"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
{"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
{"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
{"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
{"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
{"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
{"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
};
void scanline_t32cb16blend_arm64(uint16_t*, uint32_t*, size_t);
void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count)
{
while (count--)
{
uint16_t d = *dst;
uint32_t s = *src++;
int dstR = (d>>11)&0x1f;
int dstG = (d>>5)&0x3f;
int dstB = (d)&0x1f;
int srcR = (s >> ( 3))&0x1F;
int srcG = (s >> ( 8+2))&0x3F;
int srcB = (s >> (16+3))&0x1F;
int srcAlpha = (s>>24) & 0xFF;
int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1));
srcR += (f*dstR)>>8;
srcG += (f*dstG)>>8;
srcB += (f*dstB)>>8;
srcR = srcR > 0x1F? 0x1F: srcR;
srcG = srcG > 0x3F? 0x3F: srcG;
srcB = srcB > 0x1F? 0x1F: srcB;
*dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
}
}
void scanline_t32cb16blend_test()
{
uint16_t dst_c[16], dst_asm[16];
uint32_t src[16];
uint32_t i;
uint32_t j;
for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
{
struct test_t test = tests[i];
printf("Testing - %s:",test.name);
memset(dst_c, 0, sizeof(dst_c));
memset(dst_asm, 0, sizeof(dst_asm));
for(j = 0; j < test.count; ++j)
{
dst_c[j] = test.dst_color;
dst_asm[j] = test.dst_color;
src[j] = test.src_color;
}
scanline_t32cb16blend_c(dst_c,src,test.count);
scanline_t32cb16blend_arm64(dst_asm,src,test.count);
if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
printf("Passed\n");
else
printf("Failed\n");
for(j = 0; j < test.count; ++j)
{
printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
}
}
}
int main()
{
scanline_t32cb16blend_test();
return 0;
}

View File

@ -1,12 +0,0 @@
cc_test {
name: "test-opengl-codegen",
defaults: ["pixelflinger-tests"],
srcs: ["codegen.cpp"],
arch: {
arm: {
instruction_set: "arm",
},
},
}

View File

@ -1,96 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include "private/pixelflinger/ggl_context.h"
#include "buffer.h"
#include "scanline.h"
#include "codeflinger/CodeCache.h"
#include "codeflinger/GGLAssembler.h"
#include "codeflinger/ARMAssembler.h"
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#include "codeflinger/MIPSAssembler.h"
#elif defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
#include "codeflinger/MIPS64Assembler.h"
#endif
#include "codeflinger/Arm64Assembler.h"
#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))) || defined(__aarch64__)
# define ANDROID_ARM_CODEGEN 1
#else
# define ANDROID_ARM_CODEGEN 0
#endif
#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))
#define ASSEMBLY_SCRATCH_SIZE 4096
#elif defined(__aarch64__)
#define ASSEMBLY_SCRATCH_SIZE 8192
#else
#define ASSEMBLY_SCRATCH_SIZE 2048
#endif
using namespace android;
class ScanlineAssembly : public Assembly {
AssemblyKey<needs_t> mKey;
public:
ScanlineAssembly(needs_t needs, size_t size)
: Assembly(size), mKey(needs) { }
const AssemblyKey<needs_t>& key() const { return mKey; }
};
#if ANDROID_ARM_CODEGEN
static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1)
{
GGLContext* c;
gglInit(&c);
needs_t needs;
needs.n = n;
needs.p = p;
needs.t[0] = t0;
needs.t[1] = t1;
sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
#if defined(__arm__)
GGLAssembler assembler( new ARMAssembler(a) );
#endif
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
GGLAssembler assembler( new ArmToMipsAssembler(a) );
#endif
#if defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
GGLAssembler assembler( new ArmToMips64Assembler(a) );
#endif
#if defined(__aarch64__)
GGLAssembler assembler( new ArmToArm64Assembler(a) );
#endif
int err = assembler.scanline(needs, (context_t*)c);
if (err != 0) {
printf("error %08x (%s)\n", err, strerror(-err));
}
gglUninit(c);
}
#else
static void ggl_test_codegen(uint32_t, uint32_t, uint32_t, uint32_t) {
printf("This test runs only on ARM, Arm64 or MIPS\n");
}
#endif
int main(int argc, char** argv)
{
if (argc != 2) {
printf("usage: %s 00000117:03454504_00001501_00000000\n", argv[0]);
return 0;
}
uint32_t n;
uint32_t p;
uint32_t t0;
uint32_t t1;
sscanf(argv[1], "%08x:%08x_%08x_%08x", &p, &n, &t0, &t1);
ggl_test_codegen(n, p, t0, t1);
return 0;
}

View File

@ -1,12 +0,0 @@
cc_test {
name: "test-pixelflinger-gglmul",
srcs: ["gglmul_test.cpp"],
header_libs: ["libpixelflinger_internal"],
cflags: [
"-Wall",
"-Werror",
],
}

View File

@ -1,278 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include "private/pixelflinger/ggl_fixed.h"
// gglClampx() tests
struct gglClampx_test_t
{
GGLfixed input;
GGLfixed output;
};
gglClampx_test_t gglClampx_tests[] =
{
{FIXED_ONE + 1, FIXED_ONE},
{FIXED_ONE, FIXED_ONE},
{FIXED_ONE - 1, FIXED_ONE - 1},
{1, 1},
{0, 0},
{FIXED_MIN,0}
};
void gglClampx_test()
{
uint32_t i;
printf("Testing gglClampx\n");
for(i = 0; i < sizeof(gglClampx_tests)/sizeof(gglClampx_test_t); ++i)
{
gglClampx_test_t *test = &gglClampx_tests[i];
printf("Test input=0x%08x output=0x%08x :",
test->input, test->output);
if(gglClampx(test->input) == test->output)
printf("Passed\n");
else
printf("Failed\n");
}
}
// gglClz() tests
struct gglClz_test_t
{
GGLfixed input;
GGLfixed output;
};
gglClz_test_t gglClz_tests[] =
{
{0, 32},
{1, 31},
{-1,0}
};
void gglClz_test()
{
uint32_t i;
printf("Testing gglClz\n");
for(i = 0; i < sizeof(gglClz_tests)/sizeof(gglClz_test_t); ++i)
{
gglClz_test_t *test = &gglClz_tests[i];
printf("Test input=0x%08x output=%2d :", test->input, test->output);
if(gglClz(test->input) == test->output)
printf("Passed\n");
else
printf("Failed\n");
}
}
// gglMulx() tests
struct gglMulx_test_t
{
GGLfixed x;
GGLfixed y;
int shift;
};
gglMulx_test_t gglMulx_tests[] =
{
{1,1,1},
{0,1,1},
{FIXED_ONE,FIXED_ONE,16},
{FIXED_MIN,FIXED_MAX,16},
{FIXED_MAX,FIXED_MAX,16},
{FIXED_MIN,FIXED_MIN,16},
{FIXED_HALF,FIXED_ONE,16},
{FIXED_MAX,FIXED_MAX,31},
{FIXED_ONE,FIXED_MAX,31}
};
void gglMulx_test()
{
uint32_t i;
GGLfixed actual, expected;
printf("Testing gglMulx\n");
for(i = 0; i < sizeof(gglMulx_tests)/sizeof(gglMulx_test_t); ++i)
{
gglMulx_test_t *test = &gglMulx_tests[i];
printf("Test x=0x%08x y=0x%08x shift=%2d :",
test->x, test->y, test->shift);
actual = gglMulx(test->x, test->y, test->shift);
expected =
((int64_t)test->x * test->y + (1 << (test->shift-1))) >> test->shift;
if(actual == expected)
printf(" Passed\n");
else
printf(" Failed Actual(0x%08x) Expected(0x%08x)\n",
actual, expected);
}
}
// gglMulAddx() tests
struct gglMulAddx_test_t
{
GGLfixed x;
GGLfixed y;
int shift;
GGLfixed a;
};
gglMulAddx_test_t gglMulAddx_tests[] =
{
{1,2,1,1},
{0,1,1,1},
{FIXED_ONE,FIXED_ONE,16, 0},
{FIXED_MIN,FIXED_MAX,16, FIXED_HALF},
{FIXED_MAX,FIXED_MAX,16, FIXED_MIN},
{FIXED_MIN,FIXED_MIN,16, FIXED_MAX},
{FIXED_HALF,FIXED_ONE,16,FIXED_ONE},
{FIXED_MAX,FIXED_MAX,31, FIXED_HALF},
{FIXED_ONE,FIXED_MAX,31, FIXED_HALF}
};
void gglMulAddx_test()
{
uint32_t i;
GGLfixed actual, expected;
printf("Testing gglMulAddx\n");
for(i = 0; i < sizeof(gglMulAddx_tests)/sizeof(gglMulAddx_test_t); ++i)
{
gglMulAddx_test_t *test = &gglMulAddx_tests[i];
printf("Test x=0x%08x y=0x%08x shift=%2d a=0x%08x :",
test->x, test->y, test->shift, test->a);
actual = gglMulAddx(test->x, test->y,test->a, test->shift);
expected = (((int64_t)test->x * test->y) >> test->shift) + test->a;
if(actual == expected)
printf(" Passed\n");
else
printf(" Failed Actual(0x%08x) Expected(0x%08x)\n",
actual, expected);
}
}
// gglMulSubx() tests
struct gglMulSubx_test_t
{
GGLfixed x;
GGLfixed y;
int shift;
GGLfixed a;
};
gglMulSubx_test_t gglMulSubx_tests[] =
{
{1,2,1,1},
{0,1,1,1},
{FIXED_ONE,FIXED_ONE,16, 0},
{FIXED_MIN,FIXED_MAX,16, FIXED_HALF},
{FIXED_MAX,FIXED_MAX,16, FIXED_MIN},
{FIXED_MIN,FIXED_MIN,16, FIXED_MAX},
{FIXED_HALF,FIXED_ONE,16,FIXED_ONE},
{FIXED_MAX,FIXED_MAX,31, FIXED_HALF},
{FIXED_ONE,FIXED_MAX,31, FIXED_HALF}
};
void gglMulSubx_test()
{
uint32_t i;
GGLfixed actual, expected;
printf("Testing gglMulSubx\n");
for(i = 0; i < sizeof(gglMulSubx_tests)/sizeof(gglMulSubx_test_t); ++i)
{
gglMulSubx_test_t *test = &gglMulSubx_tests[i];
printf("Test x=0x%08x y=0x%08x shift=%2d a=0x%08x :",
test->x, test->y, test->shift, test->a);
actual = gglMulSubx(test->x, test->y, test->a, test->shift);
expected = (((int64_t)test->x * test->y) >> test->shift) - test->a;
if(actual == expected)
printf(" Passed\n");
else
printf(" Failed Actual(0x%08x) Expected(0x%08x)\n",
actual, expected);
}
}
// gglMulii() tests
struct gglMulii_test_t
{
int32_t x;
int32_t y;
};
gglMulii_test_t gglMulii_tests[] =
{
{1,INT32_MIN},
{1,INT32_MAX},
{0,INT32_MIN},
{0,INT32_MAX},
{INT32_MIN, INT32_MAX},
{INT32_MAX, INT32_MIN},
{INT32_MIN, INT32_MIN},
{INT32_MAX, INT32_MAX}
};
void gglMulii_test()
{
uint32_t i;
int64_t actual, expected;
printf("Testing gglMulii\n");
for(i = 0; i < sizeof(gglMulii_tests)/sizeof(gglMulii_test_t); ++i)
{
gglMulii_test_t *test = &gglMulii_tests[i];
printf("Test x=0x%08x y=0x%08x :", test->x, test->y);
actual = gglMulii(test->x, test->y);
expected = ((int64_t)test->x * test->y);
if(actual == expected)
printf(" Passed\n");
else
printf(" Failed Actual(%" PRId64 ") Expected(%" PRId64 ")\n",
actual, expected);
}
}
int main(int /*argc*/, char** /*argv*/)
{
gglClampx_test();
gglClz_test();
gglMulx_test();
gglMulAddx_test();
gglMulSubx_test();
gglMulii_test();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
/* libs/pixelflinger/trap.h
**
** Copyright 2006, 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 ANDROID_TRAP_H
#define ANDROID_TRAP_H
#include <private/pixelflinger/ggl_context.h>
namespace android {
void ggl_init_trap(context_t* c);
void ggl_state_changed(context_t* c, int flags);
}; // namespace android
#endif

110
libstats/pull/Android.bp Normal file
View File

@ -0,0 +1,110 @@
//
// Copyright (C) 2019 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.
//
// ==========================================================
// Native library to register a pull atom callback with statsd
// ==========================================================
cc_defaults {
name: "libstatspull_defaults",
srcs: [
"stats_pull_atom_callback.cpp",
],
cflags: [
"-Wall",
"-Werror",
],
export_include_dirs: ["include"],
shared_libs: [
"libbinder_ndk",
"liblog",
"libstatssocket",
],
static_libs: [
"libutils",
"statsd-aidl-ndk_platform",
],
}
cc_library_shared {
name: "libstatspull",
defaults: [
"libstatspull_defaults"
],
// enumerate stable entry points for APEX use
stubs: {
symbol_file: "libstatspull.map.txt",
versions: [
"30",
],
},
apex_available: [
"com.android.os.statsd",
"test_com.android.os.statsd",
],
stl: "libc++_static",
// TODO(b/151102177): Enable it when the build error is fixed.
header_abi_checker: {
enabled: false,
},
}
// ONLY USE IN TESTS.
cc_library_static {
name: "libstatspull_private",
defaults: [
"libstatspull_defaults",
],
visibility: [
"//frameworks/base/apex/statsd/tests/libstatspull",
],
}
// Note: These unit tests only test PullAtomMetadata.
// For full E2E tests of libstatspull, use LibStatsPullTests
cc_test {
name: "libstatspull_test",
srcs: [
"tests/pull_atom_metadata_test.cpp",
],
shared_libs: [
"libstatspull",
"libstatssocket",
],
test_suites: ["general-tests", "mts"],
test_config: "libstatspull_test.xml",
//TODO(b/153588990): Remove when the build system properly separates
//32bit and 64bit architectures.
compile_multilib: "both",
multilib: {
lib64: {
suffix: "64",
},
lib32: {
suffix: "32",
},
},
cflags: [
"-Wall",
"-Werror",
"-Wno-missing-field-initializers",
"-Wno-unused-variable",
"-Wno-unused-function",
"-Wno-unused-parameter",
],
require_root: true,
}

7
libstats/pull/OWNERS Normal file
View File

@ -0,0 +1,7 @@
joeo@google.com
muhammadq@google.com
ruchirr@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
yro@google.com

View File

@ -0,0 +1,7 @@
{
"presubmit" : [
{
"name" : "libstatspull_test"
}
]
}

View File

@ -0,0 +1,170 @@
/*
* Copyright (C) 2019, 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.
*/
#pragma once
#include <stats_event.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Opaque struct representing the metadata for registering an AStatsManager_PullAtomCallback.
*/
struct AStatsManager_PullAtomMetadata;
typedef struct AStatsManager_PullAtomMetadata AStatsManager_PullAtomMetadata;
/**
* Allocate and initialize new PullAtomMetadata.
*
* Must call AStatsManager_PullAtomMetadata_release to free the memory.
*/
AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain();
/**
* Frees the memory held by this PullAtomMetadata
*
* After calling this, the PullAtomMetadata must not be used or modified in any way.
*/
void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata);
/**
* Set the cool down time of the pull in milliseconds. If two successive pulls are issued
* within the cool down, a cached version of the first will be used for the second. The minimum
* allowed cool down is one second.
*/
void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
int64_t cool_down_millis);
/**
* Get the cool down time of the pull in milliseconds.
*/
int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata);
/**
* Set the maximum time the pull can take in milliseconds.
* The maximum allowed timeout is 10 seconds.
*/
void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
int64_t timeout_millis);
/**
* Get the maximum time the pull can take in milliseconds.
*/
int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata);
/**
* Set the additive fields of this pulled atom.
*
* This is only applicable for atoms which have a uid field. When tasks are run in
* isolated processes, the data will be attributed to the host uid. Additive fields
* will be combined when the non-additive fields are the same.
*/
void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
int32_t* additive_fields, int32_t num_fields);
/**
* Get the number of additive fields for this pulled atom. This is intended to be called before
* AStatsManager_PullAtomMetadata_getAdditiveFields to determine the size of the array.
*/
int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields(
AStatsManager_PullAtomMetadata* metadata);
/**
* Get the additive fields of this pulled atom.
*
* \param fields an output parameter containing the additive fields for this PullAtomMetadata.
* Fields is an array and it is assumed that it is at least as large as the number of
* additive fields, which can be obtained by calling
* AStatsManager_PullAtomMetadata_getNumAdditiveFields.
*/
void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
int32_t* fields);
/**
* Return codes for the result of a pull.
*/
typedef int32_t AStatsManager_PullAtomCallbackReturn;
enum {
// Value indicating that this pull was successful and that the result should be used.
AStatsManager_PULL_SUCCESS = 0,
// Value indicating that this pull was unsuccessful and that the result should not be used.
AStatsManager_PULL_SKIP = 1,
};
/**
* Opaque struct representing a list of AStatsEvent objects.
*/
struct AStatsEventList;
typedef struct AStatsEventList AStatsEventList;
/**
* Appends and returns an AStatsEvent to the end of the AStatsEventList.
*
* If an AStatsEvent is obtained in this manner, the memory is internally managed and
* AStatsEvent_release does not need to be called. The lifetime of the AStatsEvent is that of the
* AStatsEventList.
*
* The AStatsEvent does still need to be built by calling AStatsEvent_build.
*/
AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data);
/**
* Callback interface for pulling atoms requested by the stats service.
*
* \param atom_tag the tag of the atom to pull.
* \param data an output parameter in which the caller should fill the results of the pull. This
* param cannot be NULL and it's lifetime is as long as the execution of the callback.
* It must not be accessed or modified after returning from the callback.
* \param cookie the opaque pointer passed in AStatsManager_registerPullAtomCallback.
* \return AStatsManager_PULL_SUCCESS if the pull was successful, or AStatsManager_PULL_SKIP if not.
*/
typedef AStatsManager_PullAtomCallbackReturn (*AStatsManager_PullAtomCallback)(
int32_t atom_tag, AStatsEventList* data, void* cookie);
/**
* Sets a callback for an atom when that atom is to be pulled. The stats service will
* invoke the callback when the stats service determines that this atom needs to be
* pulled.
*
* Requires the REGISTER_STATS_PULL_ATOM permission.
*
* \param atom_tag The tag of the atom for this pull atom callback.
* \param metadata Optional metadata specifying the timeout, cool down time, and
* additive fields for mapping isolated to host uids.
* This param is nullable, in which case defaults will be used.
* \param callback The callback to be invoked when the stats service pulls the atom.
* \param cookie A pointer that will be passed back to the callback.
* It has no meaning to statsd.
*/
void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
AStatsManager_PullAtomCallback callback, void* cookie);
/**
* Clears a callback for an atom when that atom is to be pulled. Note that any ongoing
* pulls will still occur.
*
* Requires the REGISTER_STATS_PULL_ATOM permission.
*
* \param atomTag The tag of the atom of which to unregister
*/
void AStatsManager_clearPullAtomCallback(int32_t atom_tag);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,17 @@
LIBSTATSPULL {
global:
AStatsManager_PullAtomMetadata_obtain; # apex # introduced=30
AStatsManager_PullAtomMetadata_release; # apex # introduced=30
AStatsManager_PullAtomMetadata_setCoolDownMillis; # apex # introduced=30
AStatsManager_PullAtomMetadata_getCoolDownMillis; # apex # introduced=30
AStatsManager_PullAtomMetadata_setTimeoutMillis; # apex # introduced=30
AStatsManager_PullAtomMetadata_getTimeoutMillis; # apex # introduced=30
AStatsManager_PullAtomMetadata_setAdditiveFields; # apex # introduced=30
AStatsManager_PullAtomMetadata_getNumAdditiveFields; # apex # introduced=30
AStatsManager_PullAtomMetadata_getAdditiveFields; # apex # introduced=30
AStatsEventList_addStatsEvent; # apex # introduced=30
AStatsManager_setPullAtomCallback; # apex # introduced=30
AStatsManager_clearPullAtomCallback; # apex # introduced=30
local:
*;
};

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