Merge Android R
Bug: 168057903 Merged-In: I88f6774ca9985fb50f015756b8f8508d4691dc62 Change-Id: Iefe2872d29836b77344479ad2552a9c03d81bdcb
This commit is contained in:
commit
e1ebeab9c5
|
@ -754,6 +754,8 @@ cc_test {
|
|||
"mdns_test.cpp",
|
||||
],
|
||||
|
||||
test_config: "adb_test.xml",
|
||||
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
],
|
||||
|
|
|
@ -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>
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"name": "com.android.adbd",
|
||||
"version": 1
|
||||
"version": 300000000
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -69,4 +69,4 @@ class BootEventRecordStore {
|
|||
DISALLOW_COPY_AND_ASSIGN(BootEventRecordStore);
|
||||
};
|
||||
|
||||
#endif // BOOT_EVENT_RECORD_STORE_H_
|
||||
#endif // BOOT_EVENT_RECORD_STORE_H_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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]));
|
||||
}
|
|
@ -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); \
|
||||
|
|
|
@ -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",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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));
|
||||
}
|
|
@ -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 */
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -1,17 +0,0 @@
|
|||
cc_defaults {
|
||||
name: "pixelflinger-tests",
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
],
|
||||
|
||||
header_libs: ["libpixelflinger_internal"],
|
||||
static_libs: [
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libpixelflinger",
|
||||
"libutils",
|
||||
],
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
cc_defaults {
|
||||
name: "pixelflinger-tests-arm64",
|
||||
defaults: ["pixelflinger-tests"],
|
||||
|
||||
enabled: false,
|
||||
arch: {
|
||||
arm64: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -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",
|
||||
],
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
cc_test {
|
||||
name: "test-pixelflinger-arm64-col32cb16blend",
|
||||
defaults: ["pixelflinger-tests-arm64"],
|
||||
|
||||
srcs: ["col32cb16blend_test.c"],
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
cc_test {
|
||||
name: "test-pixelflinger-arm64-disassembler-test",
|
||||
defaults: ["pixelflinger-tests-arm64"],
|
||||
|
||||
srcs: ["arm64_diassembler_test.cpp"],
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
cc_test {
|
||||
name: "test-pixelflinger-arm64-t32cb16blend",
|
||||
defaults: ["pixelflinger-tests-arm64"],
|
||||
|
||||
srcs: ["t32cb16blend_test.c"],
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
cc_test {
|
||||
name: "test-opengl-codegen",
|
||||
defaults: ["pixelflinger-tests"],
|
||||
|
||||
srcs: ["codegen.cpp"],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
instruction_set: "arm",
|
||||
},
|
||||
},
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
cc_test {
|
||||
name: "test-pixelflinger-gglmul",
|
||||
|
||||
srcs: ["gglmul_test.cpp"],
|
||||
|
||||
header_libs: ["libpixelflinger_internal"],
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
],
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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,
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"presubmit" : [
|
||||
{
|
||||
"name" : "libstatspull_test"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue