diff options
author | Xin Li <delphij@google.com> | 2020-09-01 20:04:21 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-09-01 20:04:21 +0000 |
commit | 15144fd1ec8c9f8ef29dfcce7bffe0f5213a7d34 (patch) | |
tree | 1aabb8e7c0288b327ce88065921df0f8f674b51a | |
parent | b1463adad03fe6256ed65da6a36a2b39330fc30d (diff) | |
parent | 0a112d52f8d31718c7a2813d7f77811a2ef2f36e (diff) | |
download | core-15144fd1ec8c9f8ef29dfcce7bffe0f5213a7d34.tar.gz |
Merge "Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)" into stage-aosp-master
130 files changed, 1701 insertions, 29998 deletions
diff --git a/adb/Android.bp b/adb/Android.bp index 5351b3fbb..df2c0f965 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -754,6 +754,8 @@ cc_test { "mdns_test.cpp", ], + test_config: "adb_test.xml", + shared_libs: [ "liblog", ], diff --git a/adb/adb_test.xml b/adb/adb_test.xml new file mode 100644 index 000000000..cc3302d7b --- /dev/null +++ b/adb/adb_test.xml @@ -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> diff --git a/adb/apex/apex_manifest.json b/adb/apex/apex_manifest.json index ff2df127b..04444093d 100644 --- a/adb/apex/apex_manifest.json +++ b/adb/apex/apex_manifest.json @@ -1,4 +1,4 @@ { "name": "com.android.adbd", - "version": 1 + "version": 300000000 } diff --git a/adb/client/incremental_utils.cpp b/adb/client/incremental_utils.cpp index dd117d228..3297a6d3c 100644 --- a/adb/client/incremental_utils.cpp +++ b/adb/client/incremental_utils.cpp @@ -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); diff --git a/adb/daemon/adb_wifi.cpp b/adb/daemon/adb_wifi.cpp index bce303b2a..2f9e9b4d0 100644 --- a/adb/daemon/adb_wifi.cpp +++ b/adb/daemon/adb_wifi.cpp @@ -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 diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp index 2edf582d0..1a1e4ad62 100644 --- a/adb/daemon/auth.cpp +++ b/adb/daemon/auth.cpp @@ -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) { diff --git a/adb/transport.h b/adb/transport.h index b1f27445c..d59be59c6 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -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; } diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h index f872c85c8..e8523048f 100644 --- a/bootstat/boot_event_record_store.h +++ b/bootstat/boot_event_record_store.h @@ -69,4 +69,4 @@ class BootEventRecordStore { DISALLOW_COPY_AND_ASSIGN(BootEventRecordStore); }; -#endif // BOOT_EVENT_RECORD_STORE_H_
\ No newline at end of file +#endif // BOOT_EVENT_RECORD_STORE_H_ diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index d6fd5130f..1b2cdc151 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -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."; } @@ -1948,21 +1968,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; } @@ -1994,11 +2012,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 diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 233d15f11..63b7ad260 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -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; } diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index 721640246..40934450c 100644 --- a/fs_mgr/include_fstab/fstab/fstab.h +++ b/fs_mgr/include_fstab/fstab/fstab.h @@ -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 { diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index 27c8aae5b..46f1c590c 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -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) { diff --git a/init/reboot.cpp b/init/reboot.cpp index 0cce6a3c6..49baf9e68 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -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 { diff --git a/libcutils/Android.bp b/libcutils/Android.bp index 60400c98c..04b8f66f6 100644 --- a/libcutils/Android.bp +++ b/libcutils/Android.bp @@ -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", diff --git a/libcutils/arch-arm/memset32.S b/libcutils/arch-arm/memset32.S deleted file mode 100644 index 1e89636b4..000000000 --- a/libcutils/arch-arm/memset32.S +++ /dev/null @@ -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 diff --git a/libcutils/arch-arm64/android_memset.S b/libcutils/arch-arm64/android_memset.S deleted file mode 100644 index 9a83a6876..000000000 --- a/libcutils/arch-arm64/android_memset.S +++ /dev/null @@ -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) diff --git a/libcutils/arch-x86/android_memset16.S b/libcutils/arch-x86/android_memset16.S deleted file mode 100755 index f4d497e6f..000000000 --- a/libcutils/arch-x86/android_memset16.S +++ /dev/null @@ -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) diff --git a/libcutils/arch-x86/android_memset32.S b/libcutils/arch-x86/android_memset32.S deleted file mode 100755 index b928f6b11..000000000 --- a/libcutils/arch-x86/android_memset32.S +++ /dev/null @@ -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) diff --git a/libcutils/arch-x86_64/android_memset16.S b/libcutils/arch-x86_64/android_memset16.S deleted file mode 100644 index cb6d4a320..000000000 --- a/libcutils/arch-x86_64/android_memset16.S +++ /dev/null @@ -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) diff --git a/libcutils/arch-x86_64/android_memset32.S b/libcutils/arch-x86_64/android_memset32.S deleted file mode 100644 index 1514aa2c8..000000000 --- a/libcutils/arch-x86_64/android_memset32.S +++ /dev/null @@ -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) diff --git a/libcutils/include/cutils/memory.h b/libcutils/include/cutils/memory.h index 4d2688255..c6476c138 100644 --- a/libcutils/include/cutils/memory.h +++ b/libcutils/include/cutils/memory.h @@ -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 diff --git a/libcutils/memset_test.cpp b/libcutils/memset_test.cpp deleted file mode 100644 index a98485faa..000000000 --- a/libcutils/memset_test.cpp +++ /dev/null @@ -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])); -} diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc index 3ec98b3a6..654342649 100644 --- a/libcutils/trace-dev.inc +++ b/libcutils/trace-dev.inc @@ -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); \ diff --git a/libpixelflinger/Android.bp b/libpixelflinger/Android.bp deleted file mode 100644 index 45a32da08..000000000 --- a/libpixelflinger/Android.bp +++ /dev/null @@ -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", - ], - }, - }, -} diff --git a/libpixelflinger/MODULE_LICENSE_APACHE2 b/libpixelflinger/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29bb..000000000 --- a/libpixelflinger/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/libpixelflinger/NOTICE b/libpixelflinger/NOTICE deleted file mode 100644 index c5b1efa7a..000000000 --- a/libpixelflinger/NOTICE +++ /dev/null @@ -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 - diff --git a/libpixelflinger/arch-arm64/col32cb16blend.S b/libpixelflinger/arch-arm64/col32cb16blend.S deleted file mode 100644 index 84596f90b..000000000 --- a/libpixelflinger/arch-arm64/col32cb16blend.S +++ /dev/null @@ -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 - - - diff --git a/libpixelflinger/arch-arm64/t32cb16blend.S b/libpixelflinger/arch-arm64/t32cb16blend.S deleted file mode 100644 index a9733c0e2..000000000 --- a/libpixelflinger/arch-arm64/t32cb16blend.S +++ /dev/null @@ -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 diff --git a/libpixelflinger/buffer.cpp b/libpixelflinger/buffer.cpp deleted file mode 100644 index ea9514ca4..000000000 --- a/libpixelflinger/buffer.cpp +++ /dev/null @@ -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 diff --git a/libpixelflinger/buffer.h b/libpixelflinger/buffer.h deleted file mode 100644 index 9c9e4bc72..000000000 --- a/libpixelflinger/buffer.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/clear.cpp b/libpixelflinger/clear.cpp deleted file mode 100644 index b96245635..000000000 --- a/libpixelflinger/clear.cpp +++ /dev/null @@ -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 diff --git a/libpixelflinger/clear.h b/libpixelflinger/clear.h deleted file mode 100644 index b071df0a7..000000000 --- a/libpixelflinger/clear.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp deleted file mode 100644 index f47b6e42a..000000000 --- a/libpixelflinger/codeflinger/ARMAssembler.cpp +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h deleted file mode 100644 index 76acf7e3a..000000000 --- a/libpixelflinger/codeflinger/ARMAssembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp deleted file mode 100644 index c96cf4b02..000000000 --- a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp +++ /dev/null @@ -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 - diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.h b/libpixelflinger/codeflinger/ARMAssemblerInterface.h deleted file mode 100644 index 72935acd2..000000000 --- a/libpixelflinger/codeflinger/ARMAssemblerInterface.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp deleted file mode 100644 index 816de48fe..000000000 --- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp +++ /dev/null @@ -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 - diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h deleted file mode 100644 index 10d039085..000000000 --- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp deleted file mode 100644 index 8926776d4..000000000 --- a/libpixelflinger/codeflinger/Arm64Assembler.cpp +++ /dev/null @@ -1,1240 +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. - */ - -#define LOG_TAG "ArmToArm64Assembler" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cutils/properties.h> -#include <log/log.h> -#include <private/pixelflinger/ggl_context.h> - -#include "codeflinger/Arm64Assembler.h" -#include "codeflinger/Arm64Disassembler.h" -#include "codeflinger/CodeCache.h" - -/* -** -------------------------------------------- -** Support for Arm64 in GGLAssembler JIT -** -------------------------------------------- -** -** Approach -** - GGLAssembler and associated files are largely un-changed. -** - A translator class maps ArmAssemblerInterface calls to -** generate Arm64 instructions. -** -** ---------------------- -** ArmToArm64Assembler -** ---------------------- -** -** - Subclassed from ArmAssemblerInterface -** -** - Translates each ArmAssemblerInterface call to generate -** one or more Arm64 instructions as necessary. -** -** - Does not implement ArmAssemblerInterface portions unused by GGLAssembler -** It calls NOT_IMPLEMENTED() for such cases, which in turn logs -** a fatal message. -** -** - Uses A64_.. series of functions to generate instruction machine code -** for Arm64 instructions. These functions also log the instruction -** to LOG, if ARM64_ASM_DEBUG define is set to 1 -** -** - Dumps machine code and eqvt assembly if "debug.pf.disasm" option is set -** It uses arm64_disassemble to perform disassembly -** -** - Uses register 13 (SP in ARM), 15 (PC in ARM), 16, 17 for storing -** intermediate results. GGLAssembler does not use SP and PC as these -** registers are marked as reserved. The temporary registers are not -** saved/restored on stack as these are caller-saved registers in Arm64 -** -** - Uses CSEL instruction to support conditional execution. The result is -** stored in a temporary register and then copied to the target register -** if the condition is true. -** -** - In the case of conditional data transfer instructions, conditional -** branch is used to skip over instruction, if the condition is false -** -** - Wherever possible, immediate values are transferred to temporary -** register prior to processing. This simplifies overall implementation -** as instructions requiring immediate values are converted to -** move immediate instructions followed by register-register instruction. -** -** -------------------------------------------- -** ArmToArm64Assembler unit test bench -** -------------------------------------------- -** -** - Tests ArmToArm64Assembler interface for all the possible -** ways in which GGLAssembler uses ArmAssemblerInterface interface. -** -** - Uses test jacket (written in assembly) to set the registers, -** condition flags prior to calling generated instruction. It also -** copies registers and flags at the end of execution. Caller then -** checks if generated code performed correct operation based on -** output registers and flags. -** -** - Broadly contains three type of tests, (i) data operation tests -** (ii) data transfer tests and (iii) LDM/STM tests. -** -** ---------------------- -** Arm64 disassembler -** ---------------------- -** - This disassembler disassembles only those machine codes which can be -** generated by ArmToArm64Assembler. It has a unit testbench which -** tests all the instructions supported by the disassembler. -** -** ------------------------------------------------------------------ -** ARMAssembler/ARMAssemblerInterface/ARMAssemblerProxy changes -** ------------------------------------------------------------------ -** -** - In existing code, addresses were being handled as 32 bit values at -** certain places. -** -** - Added a new set of functions for address load/store/manipulation. -** These are ADDR_LDR, ADDR_STR, ADDR_ADD, ADDR_SUB and they map to -** default 32 bit implementations in ARMAssemblerInterface. -** -** - ArmToArm64Assembler maps these functions to appropriate 64 bit -** functions. -** -** ---------------------- -** GGLAssembler changes -** ---------------------- -** - Since ArmToArm64Assembler can generate 4 Arm64 instructions for -** each call in worst case, the memory required is set to 4 times -** ARM memory -** -** - Address load/store/manipulation were changed to use new functions -** added in the ARMAssemblerInterface. -** -*/ - - -#define NOT_IMPLEMENTED() LOG_FATAL("Arm instruction %s not yet implemented\n", __func__) - -#define ARM64_ASM_DEBUG 0 - -#if ARM64_ASM_DEBUG - #define LOG_INSTR(...) ALOGD("\t" __VA_ARGS__) - #define LOG_LABEL(...) ALOGD(__VA_ARGS__) -#else - #define LOG_INSTR(...) ((void)0) - #define LOG_LABEL(...) ((void)0) -#endif - -namespace android { - -static __unused const char* shift_codes[] = -{ - "LSL", "LSR", "ASR", "ROR" -}; -static __unused const char *cc_codes[] = -{ - "EQ", "NE", "CS", "CC", "MI", - "PL", "VS", "VC", "HI", "LS", - "GE", "LT", "GT", "LE", "AL", "NV" -}; - -ArmToArm64Assembler::ArmToArm64Assembler(const sp<Assembly>& assembly) - : ARMAssemblerInterface(), - mAssembly(assembly) -{ - mBase = mPC = (uint32_t *)assembly->base(); - mDuration = ggl_system_time(); - mZeroReg = 13; - mTmpReg1 = 15; - mTmpReg2 = 16; - mTmpReg3 = 17; -} - -ArmToArm64Assembler::ArmToArm64Assembler(void *base) - : ARMAssemblerInterface(), mAssembly(NULL) -{ - mBase = mPC = (uint32_t *)base; - mDuration = ggl_system_time(); - // Regs 13, 15, 16, 17 are used as temporary registers - mZeroReg = 13; - mTmpReg1 = 15; - mTmpReg2 = 16; - mTmpReg3 = 17; -} - -ArmToArm64Assembler::~ArmToArm64Assembler() -{ -} - -uint32_t* ArmToArm64Assembler::pc() const -{ - return mPC; -} - -uint32_t* ArmToArm64Assembler::base() const -{ - return mBase; -} - -void ArmToArm64Assembler::reset() -{ - if(mAssembly == NULL) - mPC = mBase; - else - mBase = mPC = (uint32_t *)mAssembly->base(); - mBranchTargets.clear(); - mLabels.clear(); - mLabelsInverseMapping.clear(); - mComments.clear(); -#if ARM64_ASM_DEBUG - ALOGI("RESET\n"); -#endif -} - -int ArmToArm64Assembler::getCodegenArch() -{ - return CODEGEN_ARCH_ARM64; -} - -// ---------------------------------------------------------------------------- - -void ArmToArm64Assembler::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("%p: %08x ", i, uint32_t(i[0])); - { - char instr[256]; - ::arm64_disassemble(*i, instr); - printf("%s\n", instr); - } - i++; - } -} - -void ArmToArm64Assembler::comment(const char* string) -{ - mComments.add(mPC, string); - LOG_INSTR("//%s\n", string); -} - -void ArmToArm64Assembler::label(const char* theLabel) -{ - mLabels.add(theLabel, mPC); - mLabelsInverseMapping.add(mPC, theLabel); - LOG_LABEL("%s:\n", theLabel); -} - -void ArmToArm64Assembler::B(int cc, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - LOG_INSTR("B%s %s\n", cc_codes[cc], label ); - *mPC++ = (0x54 << 24) | cc; -} - -void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/) -{ - NOT_IMPLEMENTED(); //Not Required -} - -// ---------------------------------------------------------------------------- -//Prolog/Epilog & Generate... -// ---------------------------------------------------------------------------- - -void ArmToArm64Assembler::prolog() -{ - // write prolog code - mPrologPC = mPC; - *mPC++ = A64_MOVZ_X(mZeroReg,0,0); -} - -void ArmToArm64Assembler::epilog(uint32_t /*touched*/) -{ - // write epilog code - static const int XLR = 30; - *mPC++ = A64_RET(XLR); -} - -int ArmToArm64Assembler::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); - *bt.pc |= (offset & 0x7FFFF) << 5; - } - - if(mAssembly != NULL) - 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 %ld 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* ArmToArm64Assembler::pcForLabel(const char* label) -{ - return mLabels.valueFor(label); -} - -// ---------------------------------------------------------------------------- -// Data Processing... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::dataProcessingCommon(int opcode, - int s, int Rd, int Rn, uint32_t Op2) -{ - if(opcode != opSUB && s == 1) - { - NOT_IMPLEMENTED(); //Not required - return; - } - - if(opcode != opSUB && opcode != opADD && opcode != opAND && - opcode != opORR && opcode != opMVN) - { - NOT_IMPLEMENTED(); //Not required - return; - } - - if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_shift > 31) - { - NOT_IMPLEMENTED(); - return; - } - - //Store immediate in temporary register and convert - //immediate operation into register operation - if(Op2 == OPERAND_IMM) - { - int imm = mAddrMode.immediate; - *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0x0000FFFF, 0); - *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16); - Op2 = mTmpReg2; - } - - - { - uint32_t shift; - uint32_t amount; - uint32_t Rm; - - if(Op2 == OPERAND_REG_IMM) - { - shift = mAddrMode.reg_imm_type; - amount = mAddrMode.reg_imm_shift; - Rm = mAddrMode.reg_imm_Rm; - } - else if(Op2 < OPERAND_REG) - { - shift = 0; - amount = 0; - Rm = Op2; - } - else - { - NOT_IMPLEMENTED(); //Not required - return; - } - - switch(opcode) - { - case opADD: *mPC++ = A64_ADD_W(Rd, Rn, Rm, shift, amount); break; - case opAND: *mPC++ = A64_AND_W(Rd, Rn, Rm, shift, amount); break; - case opORR: *mPC++ = A64_ORR_W(Rd, Rn, Rm, shift, amount); break; - case opMVN: *mPC++ = A64_ORN_W(Rd, Rn, Rm, shift, amount); break; - case opSUB: *mPC++ = A64_SUB_W(Rd, Rn, Rm, shift, amount, s);break; - }; - - } -} - -void ArmToArm64Assembler::dataProcessing(int opcode, int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ - uint32_t Wd; - - if(cc != AL) - Wd = mTmpReg1; - else - Wd = Rd; - - if(opcode == opADD || opcode == opAND || opcode == opORR ||opcode == opSUB) - { - dataProcessingCommon(opcode, s, Wd, Rn, Op2); - } - else if(opcode == opCMP) - { - dataProcessingCommon(opSUB, 1, mTmpReg3, Rn, Op2); - } - else if(opcode == opRSB) - { - dataProcessingCommon(opSUB, s, Wd, Rn, Op2); - dataProcessingCommon(opSUB, s, Wd, mZeroReg, Wd); - } - else if(opcode == opMOV) - { - dataProcessingCommon(opORR, 0, Wd, mZeroReg, Op2); - if(s == 1) - { - dataProcessingCommon(opSUB, 1, mTmpReg3, Wd, mZeroReg); - } - } - else if(opcode == opMVN) - { - dataProcessingCommon(opMVN, s, Wd, mZeroReg, Op2); - } - else if(opcode == opBIC) - { - dataProcessingCommon(opMVN, s, mTmpReg3, mZeroReg, Op2); - dataProcessingCommon(opAND, s, Wd, Rn, mTmpReg3); - } - else - { - NOT_IMPLEMENTED(); - return; - } - - if(cc != AL) - { - *mPC++ = A64_CSEL_W(Rd, mTmpReg1, Rd, cc); - } -} -// ---------------------------------------------------------------------------- -// Address Processing... -// ---------------------------------------------------------------------------- - -void ArmToArm64Assembler::ADDR_ADD(int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required - - - if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSL) - { - int Rm = mAddrMode.reg_imm_Rm; - int amount = mAddrMode.reg_imm_shift; - *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); - } - else if(Op2 < OPERAND_REG) - { - int Rm = Op2; - int amount = 0; - *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); - } - else if(Op2 == OPERAND_IMM) - { - int imm = mAddrMode.immediate; - *mPC++ = A64_MOVZ_W(mTmpReg1, imm & 0x0000FFFF, 0); - *mPC++ = A64_MOVK_W(mTmpReg1, (imm >> 16) & 0x0000FFFF, 16); - - int Rm = mTmpReg1; - int amount = 0; - *mPC++ = A64_ADD_X_Wm_SXTW(Rd, Rn, Rm, amount); - } - else - { - NOT_IMPLEMENTED(); //Not required - } -} - -void ArmToArm64Assembler::ADDR_SUB(int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required - - if(Op2 == OPERAND_REG_IMM && mAddrMode.reg_imm_type == LSR) - { - *mPC++ = A64_ADD_W(mTmpReg1, mZeroReg, mAddrMode.reg_imm_Rm, - LSR, mAddrMode.reg_imm_shift); - *mPC++ = A64_SUB_X_Wm_SXTW(Rd, Rn, mTmpReg1, 0); - } - else - { - NOT_IMPLEMENTED(); //Not required - } -} - -// ---------------------------------------------------------------------------- -// multiply... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::MLA(int cc, int s,int Rd, int Rm, int Rs, int Rn) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - - *mPC++ = A64_MADD_W(Rd, Rm, Rs, Rn); - if(s == 1) - dataProcessingCommon(opSUB, 1, mTmpReg1, Rd, mZeroReg); -} -void ArmToArm64Assembler::MUL(int cc, int s, int Rd, int Rm, int Rs) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required - *mPC++ = A64_MADD_W(Rd, Rm, Rs, mZeroReg); -} -void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/, - int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/, - int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/, - int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::SMUAL(int /*cc*/, int /*s*/, - int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -// ---------------------------------------------------------------------------- -// branches relative to PC... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::BX(int /*cc*/, int /*Rn*/){ - NOT_IMPLEMENTED(); //Not required -} - -// ---------------------------------------------------------------------------- -// data transfer... -// ---------------------------------------------------------------------------- -enum dataTransferOp -{ - opLDR,opLDRB,opLDRH,opSTR,opSTRB,opSTRH -}; - -void ArmToArm64Assembler::dataTransfer(int op, int cc, - int Rd, int Rn, uint32_t op_type, uint32_t size) -{ - const int XSP = 31; - if(Rn == SP) - Rn = XSP; - - if(op_type == OPERAND_IMM) - { - int addrReg; - int imm = mAddrMode.immediate; - if(imm >= 0 && imm < (1<<12)) - *mPC++ = A64_ADD_IMM_X(mTmpReg1, mZeroReg, imm, 0); - else if(imm < 0 && -imm < (1<<12)) - *mPC++ = A64_SUB_IMM_X(mTmpReg1, mZeroReg, -imm, 0); - else - { - NOT_IMPLEMENTED(); - return; - } - - addrReg = Rn; - if(mAddrMode.preindex == true || mAddrMode.postindex == true) - { - *mPC++ = A64_ADD_X(mTmpReg2, addrReg, mTmpReg1); - if(mAddrMode.preindex == true) - addrReg = mTmpReg2; - } - - if(cc != AL) - *mPC++ = A64_B_COND(cc^1, 8); - - *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, addrReg, mZeroReg); - - if(mAddrMode.writeback == true) - *mPC++ = A64_CSEL_X(Rn, mTmpReg2, Rn, cc); - } - else if(op_type == OPERAND_REG_OFFSET) - { - if(cc != AL) - *mPC++ = A64_B_COND(cc^1, 8); - *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mAddrMode.reg_offset); - - } - else if(op_type > OPERAND_UNSUPPORTED) - { - if(cc != AL) - *mPC++ = A64_B_COND(cc^1, 8); - *mPC++ = A64_LDRSTR_Wm_SXTW_0(op, size, Rd, Rn, mZeroReg); - } - else - { - NOT_IMPLEMENTED(); // Not required - } - return; - -} -void ArmToArm64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opLDR, cc, Rd, Rn, op_type, 64); -} -void ArmToArm64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opSTR, cc, Rd, Rn, op_type, 64); -} -void ArmToArm64Assembler::LDR(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opLDR, cc, Rd, Rn, op_type); -} -void ArmToArm64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opLDRB, cc, Rd, Rn, op_type); -} -void ArmToArm64Assembler::STR(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opSTR, cc, Rd, Rn, op_type); -} - -void ArmToArm64Assembler::STRB(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opSTRB, cc, Rd, Rn, op_type); -} - -void ArmToArm64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opLDRH, cc, Rd, Rn, op_type); -} -void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::STRH(int cc, int Rd, int Rn, uint32_t op_type) -{ - return dataTransfer(opSTRH, cc, Rd, Rn, op_type); -} - -// ---------------------------------------------------------------------------- -// block data transfer... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::LDM(int cc, int dir, - int Rn, int W, uint32_t reg_list) -{ - const int XSP = 31; - if(cc != AL || dir != IA || W == 0 || Rn != SP) - { - NOT_IMPLEMENTED(); - return; - } - - for(int i = 0; i < 32; ++i) - { - if((reg_list & (1 << i))) - { - int reg = i; - int size = 16; - *mPC++ = A64_LDR_IMM_PostIndex(reg, XSP, size); - } - } -} - -void ArmToArm64Assembler::STM(int cc, int dir, - int Rn, int W, uint32_t reg_list) -{ - const int XSP = 31; - if(cc != AL || dir != DB || W == 0 || Rn != SP) - { - NOT_IMPLEMENTED(); - return; - } - - for(int i = 31; i >= 0; --i) - { - if((reg_list & (1 << i))) - { - int size = -16; - int reg = i; - *mPC++ = A64_STR_IMM_PreIndex(reg, XSP, size); - } - } -} - -// ---------------------------------------------------------------------------- -// special... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/) -{ - NOT_IMPLEMENTED(); //Not required -} -void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -// ---------------------------------------------------------------------------- -// DSP instructions... -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) { - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -void ArmToArm64Assembler::QDSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/) -{ - NOT_IMPLEMENTED(); //Not required -} - -// ---------------------------------------------------------------------------- -// 16 x 16 multiplication -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::SMUL(int cc, int xy, - int Rd, int Rm, int Rs) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - - if (xy & xyTB) - *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 16, 31); - else - *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15); - - if (xy & xyBT) - *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 16, 31); - else - *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15); - - *mPC++ = A64_MADD_W(Rd,mTmpReg1,mTmpReg2, mZeroReg); -} -// ---------------------------------------------------------------------------- -// 32 x 16 multiplication -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::SMULW(int cc, int y, int Rd, int Rm, int Rs) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - - if (y & yT) - *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 16, 31); - else - *mPC++ = A64_SBFM_W(mTmpReg1, Rs, 0, 15); - - *mPC++ = A64_SBFM_W(mTmpReg2, Rm, 0, 31); - *mPC++ = A64_SMADDL(mTmpReg3,mTmpReg1,mTmpReg2, mZeroReg); - *mPC++ = A64_UBFM_X(Rd,mTmpReg3, 16, 47); -} -// ---------------------------------------------------------------------------- -// 16 x 16 multiplication and accumulate -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::SMLA(int cc, int xy, int Rd, int Rm, int Rs, int Rn) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - if(xy != xyBB) { NOT_IMPLEMENTED(); return;} //Not required - - *mPC++ = A64_SBFM_W(mTmpReg1, Rm, 0, 15); - *mPC++ = A64_SBFM_W(mTmpReg2, Rs, 0, 15); - *mPC++ = A64_MADD_W(Rd, mTmpReg1, mTmpReg2, Rn); -} - -void ArmToArm64Assembler::SMLAL(int /*cc*/, int /*xy*/, - int /*RdHi*/, int /*RdLo*/, int /*Rs*/, int /*Rm*/) -{ - NOT_IMPLEMENTED(); //Not required - return; -} - -void ArmToArm64Assembler::SMLAW(int /*cc*/, int /*y*/, - int /*Rd*/, int /*Rm*/, int /*Rs*/, int /*Rn*/) -{ - NOT_IMPLEMENTED(); //Not required - return; -} - -// ---------------------------------------------------------------------------- -// Byte/half word extract and extend -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - - *mPC++ = A64_EXTR_W(mTmpReg1, Rm, Rm, rotate * 8); - - uint32_t imm = 0x00FF00FF; - *mPC++ = A64_MOVZ_W(mTmpReg2, imm & 0xFFFF, 0); - *mPC++ = A64_MOVK_W(mTmpReg2, (imm >> 16) & 0x0000FFFF, 16); - *mPC++ = A64_AND_W(Rd,mTmpReg1, mTmpReg2); -} - -// ---------------------------------------------------------------------------- -// Bit manipulation -// ---------------------------------------------------------------------------- -void ArmToArm64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width) -{ - if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required - *mPC++ = A64_UBFM_W(Rd, Rn, lsb, lsb + width - 1); -} -// ---------------------------------------------------------------------------- -// Shifters... -// ---------------------------------------------------------------------------- -int ArmToArm64Assembler::buildImmediate( - uint32_t immediate, uint32_t& rot, uint32_t& imm) -{ - rot = 0; - imm = immediate; - return 0; // Always true -} - - -bool ArmToArm64Assembler::isValidImmediate(uint32_t immediate) -{ - uint32_t rot, imm; - return buildImmediate(immediate, rot, imm) == 0; -} - -uint32_t ArmToArm64Assembler::imm(uint32_t immediate) -{ - mAddrMode.immediate = immediate; - mAddrMode.writeback = false; - mAddrMode.preindex = false; - mAddrMode.postindex = false; - return OPERAND_IMM; - -} - -uint32_t ArmToArm64Assembler::reg_imm(int Rm, int type, uint32_t shift) -{ - mAddrMode.reg_imm_Rm = Rm; - mAddrMode.reg_imm_type = type; - mAddrMode.reg_imm_shift = shift; - return OPERAND_REG_IMM; -} - -uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/) -{ - NOT_IMPLEMENTED(); - return OPERAND_UNSUPPORTED; -} - -uint32_t ArmToArm64Assembler::reg_reg(int /*Rm*/, int /*type*/, int /*Rs*/) -{ - NOT_IMPLEMENTED(); //Not required - return OPERAND_UNSUPPORTED; -} -// ---------------------------------------------------------------------------- -// Addressing modes... -// ---------------------------------------------------------------------------- -uint32_t ArmToArm64Assembler::immed12_pre(int32_t immed12, int W) -{ - mAddrMode.immediate = immed12; - mAddrMode.writeback = W; - mAddrMode.preindex = true; - mAddrMode.postindex = false; - return OPERAND_IMM; -} - -uint32_t ArmToArm64Assembler::immed12_post(int32_t immed12) -{ - mAddrMode.immediate = immed12; - mAddrMode.writeback = true; - mAddrMode.preindex = false; - mAddrMode.postindex = true; - return OPERAND_IMM; -} - -uint32_t ArmToArm64Assembler::reg_scale_pre(int Rm, int type, - uint32_t shift, int W) -{ - if(type != 0 || shift != 0 || W != 0) - { - NOT_IMPLEMENTED(); //Not required - return OPERAND_UNSUPPORTED; - } - else - { - mAddrMode.reg_offset = Rm; - return OPERAND_REG_OFFSET; - } -} - -uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/) -{ - NOT_IMPLEMENTED(); //Not required - return OPERAND_UNSUPPORTED; -} - -uint32_t ArmToArm64Assembler::immed8_pre(int32_t immed8, int W) -{ - mAddrMode.immediate = immed8; - mAddrMode.writeback = W; - mAddrMode.preindex = true; - mAddrMode.postindex = false; - return OPERAND_IMM; -} - -uint32_t ArmToArm64Assembler::immed8_post(int32_t immed8) -{ - mAddrMode.immediate = immed8; - mAddrMode.writeback = true; - mAddrMode.preindex = false; - mAddrMode.postindex = true; - return OPERAND_IMM; -} - -uint32_t ArmToArm64Assembler::reg_pre(int Rm, int W) -{ - if(W != 0) - { - NOT_IMPLEMENTED(); //Not required - return OPERAND_UNSUPPORTED; - } - else - { - mAddrMode.reg_offset = Rm; - return OPERAND_REG_OFFSET; - } -} - -uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/) -{ - NOT_IMPLEMENTED(); //Not required - return OPERAND_UNSUPPORTED; -} - -// ---------------------------------------------------------------------------- -// A64 instructions -// ---------------------------------------------------------------------------- - -static __unused const char * dataTransferOpName[] = -{ - "LDR","LDRB","LDRH","STR","STRB","STRH" -}; - -static const uint32_t dataTransferOpCode [] = -{ - ((0xB8u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), - ((0x38u << 24) | (0x3 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)), - ((0x78u << 24) | (0x3 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), - ((0xB8u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)), - ((0x38u << 24) | (0x1 << 21) | (0x6 << 13) | (0x1 << 12) |(0x1 << 11)), - ((0x78u << 24) | (0x1 << 21) | (0x6 << 13) | (0x0 << 12) |(0x1 << 11)) -}; -uint32_t ArmToArm64Assembler::A64_LDRSTR_Wm_SXTW_0(uint32_t op, - uint32_t size, uint32_t Rt, - uint32_t Rn, uint32_t Rm) -{ - if(size == 32) - { - LOG_INSTR("%s W%d, [X%d, W%d, SXTW #0]\n", - dataTransferOpName[op], Rt, Rn, Rm); - return(dataTransferOpCode[op] | (Rm << 16) | (Rn << 5) | Rt); - } - else - { - LOG_INSTR("%s X%d, [X%d, W%d, SXTW #0]\n", - dataTransferOpName[op], Rt, Rn, Rm); - return(dataTransferOpCode[op] | (0x1<<30) | (Rm<<16) | (Rn<<5)|Rt); - } -} - -uint32_t ArmToArm64Assembler::A64_STR_IMM_PreIndex(uint32_t Rt, - uint32_t Rn, int32_t simm) -{ - if(Rn == 31) - LOG_INSTR("STR W%d, [SP, #%d]!\n", Rt, simm); - else - LOG_INSTR("STR W%d, [X%d, #%d]!\n", Rt, Rn, simm); - - uint32_t imm9 = (unsigned)(simm) & 0x01FF; - return (0xB8 << 24) | (imm9 << 12) | (0x3 << 10) | (Rn << 5) | Rt; -} - -uint32_t ArmToArm64Assembler::A64_LDR_IMM_PostIndex(uint32_t Rt, - uint32_t Rn, int32_t simm) -{ - if(Rn == 31) - LOG_INSTR("LDR W%d, [SP], #%d\n",Rt,simm); - else - LOG_INSTR("LDR W%d, [X%d], #%d\n",Rt, Rn, simm); - - uint32_t imm9 = (unsigned)(simm) & 0x01FF; - return (0xB8 << 24) | (0x1 << 22) | - (imm9 << 12) | (0x1 << 10) | (Rn << 5) | Rt; - -} -uint32_t ArmToArm64Assembler::A64_ADD_X_Wm_SXTW(uint32_t Rd, - uint32_t Rn, - uint32_t Rm, - uint32_t amount) -{ - LOG_INSTR("ADD X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount); - return ((0x8B << 24) | (0x1 << 21) |(Rm << 16) | - (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd); - -} - -uint32_t ArmToArm64Assembler::A64_SUB_X_Wm_SXTW(uint32_t Rd, - uint32_t Rn, - uint32_t Rm, - uint32_t amount) -{ - LOG_INSTR("SUB X%d, X%d, W%d, SXTW #%d\n", Rd, Rn, Rm, amount); - return ((0xCB << 24) | (0x1 << 21) |(Rm << 16) | - (0x6 << 13) | (amount << 10) | (Rn << 5) | Rd); - -} - -uint32_t ArmToArm64Assembler::A64_B_COND(uint32_t cc, uint32_t offset) -{ - LOG_INSTR("B.%s #.+%d\n", cc_codes[cc], offset); - return (0x54 << 24) | ((offset/4) << 5) | (cc); - -} -uint32_t ArmToArm64Assembler::A64_ADD_X(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount) -{ - LOG_INSTR("ADD X%d, X%d, X%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x8B << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); -} -uint32_t ArmToArm64Assembler::A64_ADD_IMM_X(uint32_t Rd, uint32_t Rn, - uint32_t imm, uint32_t shift) -{ - LOG_INSTR("ADD X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift); - return (0x91 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd; -} - -uint32_t ArmToArm64Assembler::A64_SUB_IMM_X(uint32_t Rd, uint32_t Rn, - uint32_t imm, uint32_t shift) -{ - LOG_INSTR("SUB X%d, X%d, #%d, LSL #%d\n", Rd, Rn, imm, shift); - return (0xD1 << 24) | ((shift/12) << 22) | (imm << 10) | (Rn << 5) | Rd; -} - -uint32_t ArmToArm64Assembler::A64_ADD_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount) -{ - LOG_INSTR("ADD W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x0B << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_SUB_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount, - uint32_t setflag) -{ - if(setflag == 0) - { - LOG_INSTR("SUB W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x4B << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); - } - else - { - LOG_INSTR("SUBS W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x6B << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); - } -} - -uint32_t ArmToArm64Assembler::A64_AND_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount) -{ - LOG_INSTR("AND W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x0A << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_ORR_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount) -{ - LOG_INSTR("ORR W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x2A << 24) | (shift << 22) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_ORN_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t shift, - uint32_t amount) -{ - LOG_INSTR("ORN W%d, W%d, W%d, %s #%d\n", - Rd, Rn, Rm, shift_codes[shift], amount); - return ((0x2A << 24) | (shift << 22) | (0x1 << 21) | ( Rm << 16) | - (amount << 10) |(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_CSEL_X(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t cond) -{ - LOG_INSTR("CSEL X%d, X%d, X%d, %s\n", Rd, Rn, Rm, cc_codes[cond]); - return ((0x9A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_CSEL_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t cond) -{ - LOG_INSTR("CSEL W%d, W%d, W%d, %s\n", Rd, Rn, Rm, cc_codes[cond]); - return ((0x1A << 24)|(0x1 << 23)|(Rm << 16) |(cond << 12)| (Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_RET(uint32_t Rn) -{ - LOG_INSTR("RET X%d\n", Rn); - return ((0xD6 << 24) | (0x1 << 22) | (0x1F << 16) | (Rn << 5)); -} - -uint32_t ArmToArm64Assembler::A64_MOVZ_X(uint32_t Rd, uint32_t imm, - uint32_t shift) -{ - LOG_INSTR("MOVZ X%d, #0x%x, LSL #%d\n", Rd, imm, shift); - return(0xD2 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; -} - -uint32_t ArmToArm64Assembler::A64_MOVK_W(uint32_t Rd, uint32_t imm, - uint32_t shift) -{ - LOG_INSTR("MOVK W%d, #0x%x, LSL #%d\n", Rd, imm, shift); - return (0x72 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; -} - -uint32_t ArmToArm64Assembler::A64_MOVZ_W(uint32_t Rd, uint32_t imm, - uint32_t shift) -{ - LOG_INSTR("MOVZ W%d, #0x%x, LSL #%d\n", Rd, imm, shift); - return(0x52 << 24) | (0x1 << 23) | ((shift/16) << 21) | (imm << 5) | Rd; -} - -uint32_t ArmToArm64Assembler::A64_SMADDL(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t Ra) -{ - LOG_INSTR("SMADDL X%d, W%d, W%d, X%d\n",Rd, Rn, Rm, Ra); - return ((0x9B << 24) | (0x1 << 21) | (Rm << 16)|(Ra << 10)|(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_MADD_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t Ra) -{ - LOG_INSTR("MADD W%d, W%d, W%d, W%d\n",Rd, Rn, Rm, Ra); - return ((0x1B << 24) | (Rm << 16) | (Ra << 10) |(Rn << 5) | Rd); -} - -uint32_t ArmToArm64Assembler::A64_SBFM_W(uint32_t Rd, uint32_t Rn, - uint32_t immr, uint32_t imms) -{ - LOG_INSTR("SBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms); - return ((0x13 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd); - -} -uint32_t ArmToArm64Assembler::A64_UBFM_W(uint32_t Rd, uint32_t Rn, - uint32_t immr, uint32_t imms) -{ - LOG_INSTR("UBFM W%d, W%d, #%d, #%d\n", Rd, Rn, immr, imms); - return ((0x53 << 24) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd); - -} -uint32_t ArmToArm64Assembler::A64_UBFM_X(uint32_t Rd, uint32_t Rn, - uint32_t immr, uint32_t imms) -{ - LOG_INSTR("UBFM X%d, X%d, #%d, #%d\n", Rd, Rn, immr, imms); - return ((0xD3 << 24) | (0x1 << 22) | - (immr << 16) | (imms << 10) | (Rn << 5) | Rd); - -} -uint32_t ArmToArm64Assembler::A64_EXTR_W(uint32_t Rd, uint32_t Rn, - uint32_t Rm, uint32_t lsb) -{ - LOG_INSTR("EXTR W%d, W%d, W%d, #%d\n", Rd, Rn, Rm, lsb); - return (0x13 << 24)|(0x1 << 23) | (Rm << 16) | (lsb << 10)|(Rn << 5) | Rd; -} - -}; // namespace android diff --git a/libpixelflinger/codeflinger/Arm64Assembler.h b/libpixelflinger/codeflinger/Arm64Assembler.h deleted file mode 100644 index 527c757aa..000000000 --- a/libpixelflinger/codeflinger/Arm64Assembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/Arm64Disassembler.cpp b/libpixelflinger/codeflinger/Arm64Disassembler.cpp deleted file mode 100644 index 70f1ff11f..000000000 --- a/libpixelflinger/codeflinger/Arm64Disassembler.cpp +++ /dev/null @@ -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; - } -} diff --git a/libpixelflinger/codeflinger/Arm64Disassembler.h b/libpixelflinger/codeflinger/Arm64Disassembler.h deleted file mode 100644 index 86f3aba8d..000000000 --- a/libpixelflinger/codeflinger/Arm64Disassembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp deleted file mode 100644 index 32691a389..000000000 --- a/libpixelflinger/codeflinger/CodeCache.cpp +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h deleted file mode 100644 index 93264530f..000000000 --- a/libpixelflinger/codeflinger/CodeCache.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp deleted file mode 100644 index 04e285d1b..000000000 --- a/libpixelflinger/codeflinger/GGLAssembler.cpp +++ /dev/null @@ -1,1195 +0,0 @@ -/* libs/pixelflinger/codeflinger/GGLAssembler.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 "GGLAssembler" - -#include <assert.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> - -#include <log/log.h> - -#include "GGLAssembler.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -GGLAssembler::GGLAssembler(ARMAssemblerInterface* target) - : ARMAssemblerProxy(target), - RegisterAllocator(ARMAssemblerProxy::getCodegenArch()), mOptLevel(7) -{ -} - -GGLAssembler::~GGLAssembler() -{ -} - -void GGLAssembler::prolog() -{ - ARMAssemblerProxy::prolog(); -} - -void GGLAssembler::epilog(uint32_t touched) -{ - ARMAssemblerProxy::epilog(touched); -} - -void GGLAssembler::reset(int opt_level) -{ - ARMAssemblerProxy::reset(); - RegisterAllocator::reset(); - mOptLevel = opt_level; -} - -// --------------------------------------------------------------------------- - -int GGLAssembler::scanline(const needs_t& needs, context_t const* c) -{ - int err = 0; - int opt_level = mOptLevel; - while (opt_level >= 0) { - reset(opt_level); - err = scanline_core(needs, c); - if (err == 0) - break; - opt_level--; - } - - // XXX: in theory, pcForLabel is not valid before generate() - uint32_t* fragment_start_pc = pcForLabel("fragment_loop"); - uint32_t* fragment_end_pc = pcForLabel("epilog"); - const int per_fragment_ops = int(fragment_end_pc - fragment_start_pc); - - // build a name for our pipeline - char name[64]; - sprintf(name, - "scanline__%08X:%08X_%08X_%08X [%3d ipp]", - needs.p, needs.n, needs.t[0], needs.t[1], per_fragment_ops); - - if (err) { - ALOGE("Error while generating ""%s""\n", name); - disassemble(name); - return -1; - } - - return generate(name); -} - -int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c) -{ - mBlendFactorCached = 0; - mBlending = 0; - mMasking = 0; - mAA = GGL_READ_NEEDS(P_AA, needs.p); - mDithering = GGL_READ_NEEDS(P_DITHER, needs.p); - mAlphaTest = GGL_READ_NEEDS(P_ALPHA_TEST, needs.p) + GGL_NEVER; - mDepthTest = GGL_READ_NEEDS(P_DEPTH_TEST, needs.p) + GGL_NEVER; - mFog = GGL_READ_NEEDS(P_FOG, needs.p) != 0; - mSmooth = GGL_READ_NEEDS(SHADE, needs.n) != 0; - mBuilderContext.needs = needs; - mBuilderContext.c = c; - mBuilderContext.Rctx = reserveReg(R0); // context always in R0 - mCbFormat = c->formats[ GGL_READ_NEEDS(CB_FORMAT, needs.n) ]; - - // ------------------------------------------------------------------------ - - decodeLogicOpNeeds(needs); - - decodeTMUNeeds(needs, c); - - mBlendSrc = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRC, needs.n)); - mBlendDst = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DST, needs.n)); - mBlendSrcA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRCA, needs.n)); - mBlendDstA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DSTA, needs.n)); - - if (!mCbFormat.c[GGLFormat::ALPHA].h) { - if ((mBlendSrc == GGL_ONE_MINUS_DST_ALPHA) || - (mBlendSrc == GGL_DST_ALPHA)) { - mBlendSrc = GGL_ONE; - } - if ((mBlendSrcA == GGL_ONE_MINUS_DST_ALPHA) || - (mBlendSrcA == GGL_DST_ALPHA)) { - mBlendSrcA = GGL_ONE; - } - if ((mBlendDst == GGL_ONE_MINUS_DST_ALPHA) || - (mBlendDst == GGL_DST_ALPHA)) { - mBlendDst = GGL_ONE; - } - if ((mBlendDstA == GGL_ONE_MINUS_DST_ALPHA) || - (mBlendDstA == GGL_DST_ALPHA)) { - mBlendDstA = GGL_ONE; - } - } - - // if we need the framebuffer, read it now - const int blending = blending_codes(mBlendSrc, mBlendDst) | - blending_codes(mBlendSrcA, mBlendDstA); - - // XXX: handle special cases, destination not modified... - if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) && - (mBlendDst==GGL_ONE) && (mBlendDstA==GGL_ONE)) { - // Destination unmodified (beware of logic ops) - } else if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) && - (mBlendDst==GGL_ZERO) && (mBlendDstA==GGL_ZERO)) { - // Destination is zero (beware of logic ops) - } - - int fbComponents = 0; - const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n); - for (int i=0 ; i<4 ; i++) { - const int mask = 1<<i; - component_info_t& info = mInfo[i]; - int fs = i==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc; - int fd = i==GGLFormat::ALPHA ? mBlendDstA : mBlendDst; - if (fs==GGL_SRC_ALPHA_SATURATE && i==GGLFormat::ALPHA) - fs = GGL_ONE; - info.masked = !!(masking & mask); - info.inDest = !info.masked && mCbFormat.c[i].h && - ((mLogicOp & LOGIC_OP_SRC) || (!mLogicOp)); - if (mCbFormat.components >= GGL_LUMINANCE && - (i==GGLFormat::GREEN || i==GGLFormat::BLUE)) { - info.inDest = false; - } - info.needed = (i==GGLFormat::ALPHA) && - (isAlphaSourceNeeded() || mAlphaTest != GGL_ALWAYS); - info.replaced = !!(mTextureMachine.replaced & mask); - info.iterated = (!info.replaced && (info.inDest || info.needed)); - info.smooth = mSmooth && info.iterated; - info.fog = mFog && info.inDest && (i != GGLFormat::ALPHA); - info.blend = (fs != int(GGL_ONE)) || (fd > int(GGL_ZERO)); - - mBlending |= (info.blend ? mask : 0); - mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0; - fbComponents |= mCbFormat.c[i].h ? mask : 0; - } - - mAllMasked = (mMasking == fbComponents); - if (mAllMasked) { - mDithering = 0; - } - - fragment_parts_t parts; - - // ------------------------------------------------------------------------ - prolog(); - // ------------------------------------------------------------------------ - - build_scanline_prolog(parts, needs); - - if (registerFile().status()) - return registerFile().status(); - - // ------------------------------------------------------------------------ - label("fragment_loop"); - // ------------------------------------------------------------------------ - { - Scratch regs(registerFile()); - - if (mDithering) { - // update the dither index. - MOV(AL, 0, parts.count.reg, - reg_imm(parts.count.reg, ROR, GGL_DITHER_ORDER_SHIFT)); - ADD(AL, 0, parts.count.reg, parts.count.reg, - imm( 1 << (32 - GGL_DITHER_ORDER_SHIFT))); - MOV(AL, 0, parts.count.reg, - reg_imm(parts.count.reg, ROR, 32 - GGL_DITHER_ORDER_SHIFT)); - } - - // XXX: could we do an early alpha-test here in some cases? - // It would probaly be used only with smooth-alpha and no texture - // (or no alpha component in the texture). - - // Early z-test - if (mAlphaTest==GGL_ALWAYS) { - build_depth_test(parts, Z_TEST|Z_WRITE); - } else { - // we cannot do the z-write here, because - // it might be killed by the alpha-test later - build_depth_test(parts, Z_TEST); - } - - { // texture coordinates - Scratch scratches(registerFile()); - - // texel generation - build_textures(parts, regs); - if (registerFile().status()) - return registerFile().status(); - } - - if ((blending & (FACTOR_DST|BLEND_DST)) || - (mMasking && !mAllMasked) || - (mLogicOp & LOGIC_OP_DST)) - { - // blending / logic_op / masking need the framebuffer - mDstPixel.setTo(regs.obtain(), &mCbFormat); - - // load the framebuffer pixel - comment("fetch color-buffer"); - load(parts.cbPtr, mDstPixel); - } - - if (registerFile().status()) - return registerFile().status(); - - pixel_t pixel; - int directTex = mTextureMachine.directTexture; - if (directTex | parts.packed) { - // note: we can't have both here - // iterated color or direct texture - pixel = directTex ? parts.texel[directTex-1] : parts.iterated; - pixel.flags &= ~CORRUPTIBLE; - } else { - if (mDithering) { - const int ctxtReg = mBuilderContext.Rctx; - const int mask = GGL_DITHER_SIZE-1; - parts.dither = reg_t(regs.obtain()); - AND(AL, 0, parts.dither.reg, parts.count.reg, imm(mask)); - ADDR_ADD(AL, 0, parts.dither.reg, ctxtReg, parts.dither.reg); - LDRB(AL, parts.dither.reg, parts.dither.reg, - immed12_pre(GGL_OFFSETOF(ditherMatrix))); - } - - // allocate a register for the resulting pixel - pixel.setTo(regs.obtain(), &mCbFormat, FIRST); - - build_component(pixel, parts, GGLFormat::ALPHA, regs); - - if (mAlphaTest!=GGL_ALWAYS) { - // only handle the z-write part here. We know z-test - // was successful, as well as alpha-test. - build_depth_test(parts, Z_WRITE); - } - - build_component(pixel, parts, GGLFormat::RED, regs); - build_component(pixel, parts, GGLFormat::GREEN, regs); - build_component(pixel, parts, GGLFormat::BLUE, regs); - - pixel.flags |= CORRUPTIBLE; - } - - if (registerFile().status()) - return registerFile().status(); - - if (pixel.reg == -1) { - // be defensive here. if we're here it's probably - // that this whole fragment is a no-op. - pixel = mDstPixel; - } - - if (!mAllMasked) { - // logic operation - build_logic_op(pixel, regs); - - // masking - build_masking(pixel, regs); - - comment("store"); - store(parts.cbPtr, pixel, WRITE_BACK); - } - } - - if (registerFile().status()) - return registerFile().status(); - - // update the iterated color... - if (parts.reload != 3) { - build_smooth_shade(parts); - } - - // update iterated z - build_iterate_z(parts); - - // update iterated fog - build_iterate_f(parts); - - SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16)); - B(PL, "fragment_loop"); - label("epilog"); - epilog(registerFile().touched()); - - if ((mAlphaTest!=GGL_ALWAYS) || (mDepthTest!=GGL_ALWAYS)) { - if (mDepthTest!=GGL_ALWAYS) { - label("discard_before_textures"); - build_iterate_texture_coordinates(parts); - } - label("discard_after_textures"); - build_smooth_shade(parts); - build_iterate_z(parts); - build_iterate_f(parts); - if (!mAllMasked) { - ADDR_ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3)); - } - SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16)); - B(PL, "fragment_loop"); - epilog(registerFile().touched()); - } - - return registerFile().status(); -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_scanline_prolog( - fragment_parts_t& parts, const needs_t& needs) -{ - Scratch scratches(registerFile()); - - // compute count - comment("compute ct (# of pixels to process)"); - parts.count.setTo(obtainReg()); - int Rx = scratches.obtain(); - int Ry = scratches.obtain(); - CONTEXT_LOAD(Rx, iterators.xl); - CONTEXT_LOAD(parts.count.reg, iterators.xr); - CONTEXT_LOAD(Ry, iterators.y); - - // parts.count = iterators.xr - Rx - SUB(AL, 0, parts.count.reg, parts.count.reg, Rx); - SUB(AL, 0, parts.count.reg, parts.count.reg, imm(1)); - - if (mDithering) { - // parts.count.reg = 0xNNNNXXDD - // NNNN = count-1 - // DD = dither offset - // XX = 0xxxxxxx (x = garbage) - Scratch scratches(registerFile()); - int tx = scratches.obtain(); - int ty = scratches.obtain(); - AND(AL, 0, tx, Rx, imm(GGL_DITHER_MASK)); - AND(AL, 0, ty, Ry, imm(GGL_DITHER_MASK)); - ADD(AL, 0, tx, tx, reg_imm(ty, LSL, GGL_DITHER_ORDER_SHIFT)); - ORR(AL, 0, parts.count.reg, tx, reg_imm(parts.count.reg, LSL, 16)); - } else { - // parts.count.reg = 0xNNNN0000 - // NNNN = count-1 - MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, LSL, 16)); - } - - if (!mAllMasked) { - // compute dst ptr - comment("compute color-buffer pointer"); - const int cb_bits = mCbFormat.size*8; - int Rs = scratches.obtain(); - parts.cbPtr.setTo(obtainReg(), cb_bits); - CONTEXT_LOAD(Rs, state.buffers.color.stride); - CONTEXT_ADDR_LOAD(parts.cbPtr.reg, state.buffers.color.data); - SMLABB(AL, Rs, Ry, Rs, Rx); // Rs = Rx + Ry*Rs - base_offset(parts.cbPtr, parts.cbPtr, Rs); - scratches.recycle(Rs); - } - - // init fog - const int need_fog = GGL_READ_NEEDS(P_FOG, needs.p); - if (need_fog) { - comment("compute initial fog coordinate"); - Scratch scratches(registerFile()); - int dfdx = scratches.obtain(); - int ydfdy = scratches.obtain(); - int f = ydfdy; - CONTEXT_LOAD(dfdx, generated_vars.dfdx); - CONTEXT_LOAD(ydfdy, iterators.ydfdy); - MLA(AL, 0, f, Rx, dfdx, ydfdy); - CONTEXT_STORE(f, generated_vars.f); - } - - // init Z coordinate - if ((mDepthTest != GGL_ALWAYS) || GGL_READ_NEEDS(P_MASK_Z, needs.p)) { - parts.z = reg_t(obtainReg()); - comment("compute initial Z coordinate"); - Scratch scratches(registerFile()); - int dzdx = scratches.obtain(); - int ydzdy = parts.z.reg; - CONTEXT_LOAD(dzdx, generated_vars.dzdx); // 1.31 fixed-point - CONTEXT_LOAD(ydzdy, iterators.ydzdy); // 1.31 fixed-point - MLA(AL, 0, parts.z.reg, Rx, dzdx, ydzdy); - - // we're going to index zbase of parts.count - // zbase = base + (xl-count + stride*y)*2 - int Rs = dzdx; - int zbase = scratches.obtain(); - CONTEXT_LOAD(Rs, state.buffers.depth.stride); - CONTEXT_ADDR_LOAD(zbase, state.buffers.depth.data); - SMLABB(AL, Rs, Ry, Rs, Rx); - ADD(AL, 0, Rs, Rs, reg_imm(parts.count.reg, LSR, 16)); - ADDR_ADD(AL, 0, zbase, zbase, reg_imm(Rs, LSL, 1)); - CONTEXT_ADDR_STORE(zbase, generated_vars.zbase); - } - - // init texture coordinates - init_textures(parts.coords, reg_t(Rx), reg_t(Ry)); - scratches.recycle(Ry); - - // iterated color - init_iterated_color(parts, reg_t(Rx)); - - // init coverage factor application (anti-aliasing) - if (mAA) { - parts.covPtr.setTo(obtainReg(), 16); - CONTEXT_ADDR_LOAD(parts.covPtr.reg, state.buffers.coverage); - ADDR_ADD(AL, 0, parts.covPtr.reg, parts.covPtr.reg, reg_imm(Rx, LSL, 1)); - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_component( pixel_t& pixel, - const fragment_parts_t& parts, - int component, - Scratch& regs) -{ - static char const * comments[] = {"alpha", "red", "green", "blue"}; - comment(comments[component]); - - // local register file - Scratch scratches(registerFile()); - const int dst_component_size = pixel.component_size(component); - - component_t temp(-1); - build_incoming_component( temp, dst_component_size, - parts, component, scratches, regs); - - if (mInfo[component].inDest) { - - // blending... - build_blending( temp, mDstPixel, component, scratches ); - - // downshift component and rebuild pixel... - downshift(pixel, component, temp, parts.dither); - } -} - -void GGLAssembler::build_incoming_component( - component_t& temp, - int dst_size, - const fragment_parts_t& parts, - int component, - Scratch& scratches, - Scratch& global_regs) -{ - const uint32_t component_mask = 1<<component; - - // Figure out what we need for the blending stage... - 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; - } - - // Figure out what we need to extract and for what reason - const int blending = blending_codes(fs, fd); - - // Are we actually going to blend? - const int need_blending = (fs != int(GGL_ONE)) || (fd > int(GGL_ZERO)); - - // expand the source if the destination has more bits - int need_expander = false; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT-1 ; i++) { - texture_unit_t& tmu = mTextureMachine.tmu[i]; - if ((tmu.format_idx) && - (parts.texel[i].component_size(component) < dst_size)) { - need_expander = true; - } - } - - // do we need to extract this component? - const bool multiTexture = mTextureMachine.activeUnits > 1; - const int blend_needs_alpha_source = (component==GGLFormat::ALPHA) && - (isAlphaSourceNeeded()); - int need_extract = mInfo[component].needed; - if (mInfo[component].inDest) - { - need_extract |= ((need_blending ? - (blending & (BLEND_SRC|FACTOR_SRC)) : need_expander)); - need_extract |= (mTextureMachine.mask != mTextureMachine.replaced); - need_extract |= mInfo[component].smooth; - need_extract |= mInfo[component].fog; - need_extract |= mDithering; - need_extract |= multiTexture; - } - - if (need_extract) { - Scratch& regs = blend_needs_alpha_source ? global_regs : scratches; - component_t fragment; - - // iterated color - build_iterated_color(fragment, parts, component, regs); - - // texture environement (decal, modulate, replace) - build_texture_environment(fragment, parts, component, regs); - - // expand the source if the destination has more bits - if (need_expander && (fragment.size() < dst_size)) { - // we're here only if we fetched a texel - // (so we know for sure fragment is CORRUPTIBLE) - expand(fragment, fragment, dst_size); - } - - // We have a few specific things to do for the alpha-channel - if ((component==GGLFormat::ALPHA) && - (mInfo[component].needed || fragment.size()<dst_size)) - { - // convert to integer_t first and make sure - // we don't corrupt a needed register - if (fragment.l) { - component_t incoming(fragment); - modify(fragment, regs); - MOV(AL, 0, fragment.reg, reg_imm(incoming.reg, LSR, incoming.l)); - fragment.h -= fragment.l; - fragment.l = 0; - } - - // coverage factor application - build_coverage_application(fragment, parts, regs); - - // alpha-test - build_alpha_test(fragment, parts); - - if (blend_needs_alpha_source) { - // We keep only 8 bits for the blending stage - const int shift = fragment.h <= 8 ? 0 : fragment.h-8; - if (fragment.flags & CORRUPTIBLE) { - fragment.flags &= ~CORRUPTIBLE; - mAlphaSource.setTo(fragment.reg, - fragment.size(), fragment.flags); - if (shift) { - MOV(AL, 0, mAlphaSource.reg, - reg_imm(mAlphaSource.reg, LSR, shift)); - } - } else { - // XXX: it would better to do this in build_blend_factor() - // so we can avoid the extra MOV below. - mAlphaSource.setTo(regs.obtain(), - fragment.size(), CORRUPTIBLE); - if (shift) { - MOV(AL, 0, mAlphaSource.reg, - reg_imm(fragment.reg, LSR, shift)); - } else { - MOV(AL, 0, mAlphaSource.reg, fragment.reg); - } - } - mAlphaSource.s -= shift; - } - } - - // fog... - build_fog( fragment, component, regs ); - - temp = fragment; - } else { - if (mInfo[component].inDest) { - // extraction not needed and replace - // we just select the right component - if ((mTextureMachine.replaced & component_mask) == 0) { - // component wasn't replaced, so use it! - temp = component_t(parts.iterated, component); - } - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - const texture_unit_t& tmu = mTextureMachine.tmu[i]; - if ((tmu.mask & component_mask) && - ((tmu.replaced & component_mask) == 0)) { - temp = component_t(parts.texel[i], component); - } - } - } - } -} - -bool GGLAssembler::isAlphaSourceNeeded() const -{ - // XXX: also needed for alpha-test - const int bs = mBlendSrc; - const int bd = mBlendDst; - return bs==GGL_SRC_ALPHA_SATURATE || - bs==GGL_SRC_ALPHA || bs==GGL_ONE_MINUS_SRC_ALPHA || - bd==GGL_SRC_ALPHA || bd==GGL_ONE_MINUS_SRC_ALPHA ; -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_smooth_shade(const fragment_parts_t& parts) -{ - if (mSmooth && !parts.iterated_packed) { - // update the iterated color in a pipelined way... - comment("update iterated color"); - Scratch scratches(registerFile()); - - const int reload = parts.reload; - for (int i=0 ; i<4 ; i++) { - if (!mInfo[i].iterated) - continue; - - int c = parts.argb[i].reg; - int dx = parts.argb_dx[i].reg; - - if (reload & 1) { - c = scratches.obtain(); - CONTEXT_LOAD(c, generated_vars.argb[i].c); - } - if (reload & 2) { - dx = scratches.obtain(); - CONTEXT_LOAD(dx, generated_vars.argb[i].dx); - } - - if (mSmooth) { - ADD(AL, 0, c, c, dx); - } - - if (reload & 1) { - CONTEXT_STORE(c, generated_vars.argb[i].c); - scratches.recycle(c); - } - if (reload & 2) { - scratches.recycle(dx); - } - } - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_coverage_application(component_t& fragment, - const fragment_parts_t& parts, Scratch& regs) -{ - // here fragment.l is guarenteed to be 0 - if (mAA) { - // coverages are 1.15 fixed-point numbers - comment("coverage application"); - - component_t incoming(fragment); - modify(fragment, regs); - - Scratch scratches(registerFile()); - int cf = scratches.obtain(); - LDRH(AL, cf, parts.covPtr.reg, immed8_post(2)); - if (fragment.h > 31) { - fragment.h--; - SMULWB(AL, fragment.reg, incoming.reg, cf); - } else { - MOV(AL, 0, fragment.reg, reg_imm(incoming.reg, LSL, 1)); - SMULWB(AL, fragment.reg, fragment.reg, cf); - } - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_alpha_test(component_t& fragment, - const fragment_parts_t& /*parts*/) -{ - if (mAlphaTest != GGL_ALWAYS) { - comment("Alpha Test"); - Scratch scratches(registerFile()); - int ref = scratches.obtain(); - const int shift = GGL_COLOR_BITS-fragment.size(); - CONTEXT_LOAD(ref, state.alpha_test.ref); - if (shift) CMP(AL, fragment.reg, reg_imm(ref, LSR, shift)); - else CMP(AL, fragment.reg, ref); - int cc = NV; - switch (mAlphaTest) { - case GGL_NEVER: cc = NV; break; - case GGL_LESS: cc = LT; break; - case GGL_EQUAL: cc = EQ; break; - case GGL_LEQUAL: cc = LS; break; - case GGL_GREATER: cc = HI; break; - case GGL_NOTEQUAL: cc = NE; break; - case GGL_GEQUAL: cc = HS; break; - } - B(cc^1, "discard_after_textures"); - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_depth_test( - const fragment_parts_t& parts, uint32_t mask) -{ - mask &= Z_TEST|Z_WRITE; - const needs_t& needs = mBuilderContext.needs; - const int zmask = GGL_READ_NEEDS(P_MASK_Z, needs.p); - Scratch scratches(registerFile()); - - if (mDepthTest != GGL_ALWAYS || zmask) { - int cc=AL, ic=AL; - switch (mDepthTest) { - case GGL_LESS: ic = HI; break; - case GGL_EQUAL: ic = EQ; break; - case GGL_LEQUAL: ic = HS; break; - case GGL_GREATER: ic = LT; break; - case GGL_NOTEQUAL: ic = NE; break; - case GGL_GEQUAL: ic = LS; break; - case GGL_NEVER: - // this never happens, because it's taken care of when - // computing the needs. but we keep it for completness. - comment("Depth Test (NEVER)"); - B(AL, "discard_before_textures"); - return; - case GGL_ALWAYS: - // we're here because zmask is enabled - mask &= ~Z_TEST; // test always passes. - break; - } - - // inverse the condition - cc = ic^1; - - if ((mask & Z_WRITE) && !zmask) { - mask &= ~Z_WRITE; - } - - if (!mask) - return; - - comment("Depth Test"); - - int zbase = scratches.obtain(); - int depth = scratches.obtain(); - int z = parts.z.reg; - - CONTEXT_ADDR_LOAD(zbase, generated_vars.zbase); // stall - ADDR_SUB(AL, 0, zbase, zbase, reg_imm(parts.count.reg, LSR, 15)); - // above does zbase = zbase + ((count >> 16) << 1) - - if (mask & Z_TEST) { - LDRH(AL, depth, zbase); // stall - CMP(AL, depth, reg_imm(z, LSR, 16)); - B(cc, "discard_before_textures"); - } - if (mask & Z_WRITE) { - if (mask == Z_WRITE) { - // only z-write asked, cc is meaningless - ic = AL; - } - MOV(AL, 0, depth, reg_imm(z, LSR, 16)); - STRH(ic, depth, zbase); - } - } -} - -void GGLAssembler::build_iterate_z(const fragment_parts_t& parts) -{ - const needs_t& needs = mBuilderContext.needs; - if ((mDepthTest != GGL_ALWAYS) || GGL_READ_NEEDS(P_MASK_Z, needs.p)) { - Scratch scratches(registerFile()); - int dzdx = scratches.obtain(); - CONTEXT_LOAD(dzdx, generated_vars.dzdx); // stall - ADD(AL, 0, parts.z.reg, parts.z.reg, dzdx); - } -} - -void GGLAssembler::build_iterate_f(const fragment_parts_t& /*parts*/) -{ - const needs_t& needs = mBuilderContext.needs; - if (GGL_READ_NEEDS(P_FOG, needs.p)) { - Scratch scratches(registerFile()); - int dfdx = scratches.obtain(); - int f = scratches.obtain(); - CONTEXT_LOAD(f, generated_vars.f); - CONTEXT_LOAD(dfdx, generated_vars.dfdx); // stall - ADD(AL, 0, f, f, dfdx); - CONTEXT_STORE(f, generated_vars.f); - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::build_logic_op(pixel_t& pixel, Scratch& regs) -{ - const needs_t& needs = mBuilderContext.needs; - const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; - if (opcode == GGL_COPY) - return; - - comment("logic operation"); - - pixel_t s(pixel); - if (!(pixel.flags & CORRUPTIBLE)) { - pixel.reg = regs.obtain(); - pixel.flags |= CORRUPTIBLE; - } - - pixel_t d(mDstPixel); - switch(opcode) { - case GGL_CLEAR: MOV(AL, 0, pixel.reg, imm(0)); break; - case GGL_AND: AND(AL, 0, pixel.reg, s.reg, d.reg); break; - case GGL_AND_REVERSE: BIC(AL, 0, pixel.reg, s.reg, d.reg); break; - case GGL_COPY: break; - case GGL_AND_INVERTED: BIC(AL, 0, pixel.reg, d.reg, s.reg); break; - case GGL_NOOP: MOV(AL, 0, pixel.reg, d.reg); break; - case GGL_XOR: EOR(AL, 0, pixel.reg, s.reg, d.reg); break; - case GGL_OR: ORR(AL, 0, pixel.reg, s.reg, d.reg); break; - case GGL_NOR: ORR(AL, 0, pixel.reg, s.reg, d.reg); - MVN(AL, 0, pixel.reg, pixel.reg); break; - case GGL_EQUIV: EOR(AL, 0, pixel.reg, s.reg, d.reg); - MVN(AL, 0, pixel.reg, pixel.reg); break; - case GGL_INVERT: MVN(AL, 0, pixel.reg, d.reg); break; - case GGL_OR_REVERSE: // s | ~d == ~(~s & d) - BIC(AL, 0, pixel.reg, d.reg, s.reg); - MVN(AL, 0, pixel.reg, pixel.reg); break; - case GGL_COPY_INVERTED: MVN(AL, 0, pixel.reg, s.reg); break; - case GGL_OR_INVERTED: // ~s | d == ~(s & ~d) - BIC(AL, 0, pixel.reg, s.reg, d.reg); - MVN(AL, 0, pixel.reg, pixel.reg); break; - case GGL_NAND: AND(AL, 0, pixel.reg, s.reg, d.reg); - MVN(AL, 0, pixel.reg, pixel.reg); break; - case GGL_SET: MVN(AL, 0, pixel.reg, imm(0)); break; - }; -} - -// --------------------------------------------------------------------------- - -static uint32_t find_bottom(uint32_t val) -{ - uint32_t i = 0; - while (!(val & (3<<i))) - i+= 2; - return i; -} - -static void normalize(uint32_t& val, uint32_t& rot) -{ - rot = 0; - while (!(val&3) || (val & 0xFC000000)) { - uint32_t newval; - newval = val >> 2; - newval |= (val&3) << 30; - val = newval; - rot += 2; - if (rot == 32) { - rot = 0; - break; - } - } -} - -void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits) -{ - uint32_t rot; - uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1; - mask &= size; - - if (mask == size) { - if (d != s) - MOV( AL, 0, d, s); - return; - } - - if ((getCodegenArch() == CODEGEN_ARCH_MIPS) || - (getCodegenArch() == CODEGEN_ARCH_MIPS64)) { - // MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr - // the below ' while (mask)' code is buggy on mips - // since mips returns true on isValidImmediate() - // then we get multiple AND instr (positive logic) - AND( AL, 0, d, s, imm(mask) ); - return; - } - else if (getCodegenArch() == CODEGEN_ARCH_ARM64) { - AND( AL, 0, d, s, imm(mask) ); - return; - } - - int negative_logic = !isValidImmediate(mask); - if (negative_logic) { - mask = ~mask & size; - } - normalize(mask, rot); - - if (mask) { - while (mask) { - uint32_t bitpos = find_bottom(mask); - int shift = rot + bitpos; - uint32_t m = mask & (0xff << bitpos); - mask &= ~m; - m >>= bitpos; - int32_t newMask = (m<<shift) | (m>>(32-shift)); - if (!negative_logic) { - AND( AL, 0, d, s, imm(newMask) ); - } else { - BIC( AL, 0, d, s, imm(newMask) ); - } - s = d; - } - } else { - MOV( AL, 0, d, imm(0)); - } -} - -void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs) -{ - if (!mMasking || mAllMasked) { - return; - } - - comment("color mask"); - - pixel_t fb(mDstPixel); - pixel_t s(pixel); - if (!(pixel.flags & CORRUPTIBLE)) { - pixel.reg = regs.obtain(); - pixel.flags |= CORRUPTIBLE; - } - - int mask = 0; - for (int i=0 ; i<4 ; i++) { - const int component_mask = 1<<i; - const int h = fb.format.c[i].h; - const int l = fb.format.c[i].l; - if (h && (!(mMasking & component_mask))) { - mask |= ((1<<(h-l))-1) << l; - } - } - - // There is no need to clear the masked components of the source - // (unless we applied a logic op), because they're already zeroed - // by construction (masked components are not computed) - - if (mLogicOp) { - const needs_t& needs = mBuilderContext.needs; - const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; - if (opcode != GGL_CLEAR) { - // clear masked component of source - build_and_immediate(pixel.reg, s.reg, mask, fb.size()); - s = pixel; - } - } - - // clear non masked components of destination - build_and_immediate(fb.reg, fb.reg, ~mask, fb.size()); - - // or back the channels that were masked - if (s.reg == fb.reg) { - // this is in fact a MOV - if (s.reg == pixel.reg) { - // ugh. this in in fact a nop - } else { - MOV(AL, 0, pixel.reg, fb.reg); - } - } else { - ORR(AL, 0, pixel.reg, s.reg, fb.reg); - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::base_offset( - const pointer_t& d, const pointer_t& b, const reg_t& o) -{ - switch (b.size) { - case 32: - ADDR_ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 2)); - break; - case 24: - if (d.reg == b.reg) { - ADDR_ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 1)); - ADDR_ADD(AL, 0, d.reg, d.reg, o.reg); - } else { - ADDR_ADD(AL, 0, d.reg, o.reg, reg_imm(o.reg, LSL, 1)); - ADDR_ADD(AL, 0, d.reg, d.reg, b.reg); - } - break; - case 16: - ADDR_ADD(AL, 0, d.reg, b.reg, reg_imm(o.reg, LSL, 1)); - break; - case 8: - ADDR_ADD(AL, 0, d.reg, b.reg, o.reg); - break; - } -} - -// ---------------------------------------------------------------------------- -// cheezy register allocator... -// ---------------------------------------------------------------------------- - -// Modified to support MIPS processors, in a very simple way. We retain the -// (Arm) limit of 16 total registers, but shift the mapping of those registers -// from 0-15, to 2-17. Register 0 on Mips cannot be used as GP registers, and -// register 1 has a traditional use as a temp). - -RegisterAllocator::RegisterAllocator(int arch) : mRegs(arch) -{ -} - -void RegisterAllocator::reset() -{ - mRegs.reset(); -} - -int RegisterAllocator::reserveReg(int reg) -{ - return mRegs.reserve(reg); -} - -int RegisterAllocator::obtainReg() -{ - return mRegs.obtain(); -} - -void RegisterAllocator::recycleReg(int reg) -{ - mRegs.recycle(reg); -} - -RegisterAllocator::RegisterFile& RegisterAllocator::registerFile() -{ - return mRegs; -} - -// ---------------------------------------------------------------------------- - -RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch) - : mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0) -{ - if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) || - (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) { - mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17 - } - reserve(ARMAssemblerInterface::SP); - reserve(ARMAssemblerInterface::PC); -} - -RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch) - : mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0) -{ - if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) || - (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) { - mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17 - } -} - -RegisterAllocator::RegisterFile::~RegisterFile() -{ -} - -bool RegisterAllocator::RegisterFile::operator == (const RegisterFile& rhs) const -{ - return (mRegs == rhs.mRegs); -} - -void RegisterAllocator::RegisterFile::reset() -{ - mRegs = mTouched = mStatus = 0; - reserve(ARMAssemblerInterface::SP); - reserve(ARMAssemblerInterface::PC); -} - -// RegisterFile::reserve() take a register parameter in the -// range 0-15 (Arm compatible), but on a Mips processor, will -// return the actual allocated register in the range 2-17. -int RegisterAllocator::RegisterFile::reserve(int reg) -{ - reg += mRegisterOffset; - LOG_ALWAYS_FATAL_IF(isUsed(reg), - "reserving register %d, but already in use", - reg); - mRegs |= (1<<reg); - mTouched |= mRegs; - return reg; -} - -// This interface uses regMask in range 2-17 on MIPS, no translation. -void RegisterAllocator::RegisterFile::reserveSeveral(uint32_t regMask) -{ - mRegs |= regMask; - mTouched |= regMask; -} - -int RegisterAllocator::RegisterFile::isUsed(int reg) const -{ - LOG_ALWAYS_FATAL_IF(reg>=16+(int)mRegisterOffset, "invalid register %d", reg); - return mRegs & (1<<reg); -} - -int RegisterAllocator::RegisterFile::obtain() -{ - const char priorityList[14] = { 0, 1, 2, 3, - 12, 14, 4, 5, - 6, 7, 8, 9, - 10, 11 }; - const int nbreg = sizeof(priorityList); - int i, r, reg; - for (i=0 ; i<nbreg ; i++) { - r = priorityList[i]; - if (!isUsed(r + mRegisterOffset)) { - break; - } - } - // this is not an error anymore because, we'll try again with - // a lower optimization level. - //ALOGE_IF(i >= nbreg, "pixelflinger ran out of registers\n"); - if (i >= nbreg) { - mStatus |= OUT_OF_REGISTERS; - // we return SP so we can more easily debug things - // the code will never be run anyway. - return ARMAssemblerInterface::SP; - } - reg = reserve(r); // Param in Arm range 0-15, returns range 2-17 on Mips. - return reg; -} - -bool RegisterAllocator::RegisterFile::hasFreeRegs() const -{ - uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix. - return ((regs & 0xFFFF) == 0xFFFF) ? false : true; -} - -int RegisterAllocator::RegisterFile::countFreeRegs() const -{ - uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix. - int f = ~regs & 0xFFFF; - // now count number of 1 - f = (f & 0x5555) + ((f>>1) & 0x5555); - f = (f & 0x3333) + ((f>>2) & 0x3333); - f = (f & 0x0F0F) + ((f>>4) & 0x0F0F); - f = (f & 0x00FF) + ((f>>8) & 0x00FF); - return f; -} - -void RegisterAllocator::RegisterFile::recycle(int reg) -{ - // commented out, since common failure of running out of regs - // triggers this assertion. Since the code is not execectued - // in that case, it does not matter. No reason to FATAL err. - // LOG_FATAL_IF(!isUsed(reg), - // "recycling unallocated register %d", - // reg); - mRegs &= ~(1<<reg); -} - -void RegisterAllocator::RegisterFile::recycleSeveral(uint32_t regMask) -{ - // commented out, since common failure of running out of regs - // triggers this assertion. Since the code is not execectued - // in that case, it does not matter. No reason to FATAL err. - // LOG_FATAL_IF((mRegs & regMask)!=regMask, - // "recycling unallocated registers " - // "(recycle=%08x, allocated=%08x, unallocated=%08x)", - // regMask, mRegs, mRegs®Mask); - mRegs &= ~regMask; -} - -uint32_t RegisterAllocator::RegisterFile::touched() const -{ - return mTouched; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h deleted file mode 100644 index 47dbf3a33..000000000 --- a/libpixelflinger/codeflinger/GGLAssembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.cpp b/libpixelflinger/codeflinger/MIPS64Assembler.cpp deleted file mode 100644 index d6d215679..000000000 --- a/libpixelflinger/codeflinger/MIPS64Assembler.cpp +++ /dev/null @@ -1,1447 +0,0 @@ -/* libs/pixelflinger/codeflinger/MIPS64Assembler.cpp -** -** 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. -*/ - - -/* MIPS64 assembler and ARM->MIPS64 assembly translator -** -** The approach is utilize MIPSAssembler generator, using inherited MIPS64Assembler -** that overrides just the specific MIPS64r6 instructions. -** For now ArmToMips64Assembler is copied over from ArmToMipsAssembler class, -** changing some MIPS64r6 related stuff. -** -*/ - -#define LOG_TAG "MIPS64Assembler" - -#include <stdio.h> -#include <stdlib.h> - -#include <cutils/properties.h> -#include <log/log.h> -#include <private/pixelflinger/ggl_context.h> - -#include "MIPS64Assembler.h" -#include "CodeCache.h" -#include "mips64_disassem.h" - -#define NOT_IMPLEMENTED() LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__) -#define __unused __attribute__((__unused__)) - -// ---------------------------------------------------------------------------- - -namespace android { - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark ArmToMips64Assembler... -#endif - -ArmToMips64Assembler::ArmToMips64Assembler(const sp<Assembly>& assembly, - char *abuf, int linesz, int instr_count) - : ARMAssemblerInterface(), - mArmDisassemblyBuffer(abuf), - mArmLineLength(linesz), - mArmInstrCount(instr_count), - mInum(0), - mAssembly(assembly) -{ - mMips = new MIPS64Assembler(assembly, this); - mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *)); - init_conditional_labels(); -} - -ArmToMips64Assembler::ArmToMips64Assembler(void* assembly) - : ARMAssemblerInterface(), - mArmDisassemblyBuffer(NULL), - mInum(0), - mAssembly(NULL) -{ - mMips = new MIPS64Assembler(assembly, this); - mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *)); - init_conditional_labels(); -} - -ArmToMips64Assembler::~ArmToMips64Assembler() -{ - delete mMips; - free((void *) mArmPC); -} - -uint32_t* ArmToMips64Assembler::pc() const -{ - return mMips->pc(); -} - -uint32_t* ArmToMips64Assembler::base() const -{ - return mMips->base(); -} - -void ArmToMips64Assembler::reset() -{ - cond.labelnum = 0; - mInum = 0; - mMips->reset(); -} - -int ArmToMips64Assembler::getCodegenArch() -{ - return CODEGEN_ARCH_MIPS64; -} - -void ArmToMips64Assembler::comment(const char* string) -{ - mMips->comment(string); -} - -void ArmToMips64Assembler::label(const char* theLabel) -{ - mMips->label(theLabel); -} - -void ArmToMips64Assembler::disassemble(const char* name) -{ - mMips->disassemble(name); -} - -void ArmToMips64Assembler::init_conditional_labels() -{ - int i; - for (i=0;i<99; ++i) { - sprintf(cond.label[i], "cond_%d", i); - } -} - - - -#if 0 -#pragma mark - -#pragma mark Prolog/Epilog & Generate... -#endif - -void ArmToMips64Assembler::prolog() -{ - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->DADDIU(R_sp, R_sp, -(5 * 8)); - mMips->SD(R_s0, R_sp, 0); - mMips->SD(R_s1, R_sp, 8); - mMips->SD(R_s2, R_sp, 16); - mMips->SD(R_s3, R_sp, 24); - mMips->SD(R_s4, R_sp, 32); - mMips->MOVE(R_v0, R_a0); // move context * passed in a0 to v0 (arm r0) -} - -void ArmToMips64Assembler::epilog(uint32_t touched __unused) -{ - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->LD(R_s0, R_sp, 0); - mMips->LD(R_s1, R_sp, 8); - mMips->LD(R_s2, R_sp, 16); - mMips->LD(R_s3, R_sp, 24); - mMips->LD(R_s4, R_sp, 32); - mMips->DADDIU(R_sp, R_sp, (5 * 8)); - mMips->JR(R_ra); - -} - -int ArmToMips64Assembler::generate(const char* name) -{ - return mMips->generate(name); -} - -void ArmToMips64Assembler::fix_branches() -{ - mMips->fix_branches(); -} - -uint32_t* ArmToMips64Assembler::pcForLabel(const char* label) -{ - return mMips->pcForLabel(label); -} - -void ArmToMips64Assembler::set_condition(int mode, int R1, int R2) { - if (mode == 2) { - cond.type = SBIT_COND; - } else { - cond.type = CMP_COND; - } - cond.r1 = R1; - cond.r2 = R2; -} - -//---------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Addressing modes & shifters... -#endif - - -// do not need this for MIPS, but it is in the Interface (virtual) -int ArmToMips64Assembler::buildImmediate( - uint32_t immediate, uint32_t& rot, uint32_t& imm) -{ - // for MIPS, any 32-bit immediate is OK - rot = 0; - imm = immediate; - return 0; -} - -// shifters... - -bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate __unused) -{ - // for MIPS, any 32-bit immediate is OK - return true; -} - -uint32_t ArmToMips64Assembler::imm(uint32_t immediate) -{ - amode.value = immediate; - return AMODE_IMM; -} - -uint32_t ArmToMips64Assembler::reg_imm(int Rm, int type, uint32_t shift) -{ - amode.reg = Rm; - amode.stype = type; - amode.value = shift; - return AMODE_REG_IMM; -} - -uint32_t ArmToMips64Assembler::reg_rrx(int Rm __unused) -{ - // reg_rrx mode is not used in the GLLAssember code at this time - return AMODE_UNSUPPORTED; -} - -uint32_t ArmToMips64Assembler::reg_reg(int Rm __unused, int type __unused, - int Rs __unused) -{ - // reg_reg mode is not used in the GLLAssember code at this time - return AMODE_UNSUPPORTED; -} - - -// addressing modes... -// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMips64Assembler::immed12_pre(int32_t immed12, int W) -{ - LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800, - "LDR(B)/STR(B)/PLD immediate too big (%08x)", - immed12); - amode.value = immed12; - amode.writeback = W; - return AMODE_IMM_12_PRE; -} - -uint32_t ArmToMips64Assembler::immed12_post(int32_t immed12) -{ - LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800, - "LDR(B)/STR(B)/PLD immediate too big (%08x)", - immed12); - - amode.value = immed12; - return AMODE_IMM_12_POST; -} - -uint32_t ArmToMips64Assembler::reg_scale_pre(int Rm, int type, - uint32_t shift, int W) -{ - LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented"); - - amode.reg = Rm; - // amode.stype = type; // more advanced modes not used in GGLAssembler yet - // amode.value = shift; - // amode.writeback = W; - return AMODE_REG_SCALE_PRE; -} - -uint32_t ArmToMips64Assembler::reg_scale_post(int Rm __unused, int type __unused, - uint32_t shift __unused) -{ - LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n"); - return AMODE_UNSUPPORTED; -} - -// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMips64Assembler::immed8_pre(int32_t immed8, int W __unused) -{ - LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n"); - - LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100, - "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)", - immed8); - return AMODE_IMM_8_PRE; -} - -uint32_t ArmToMips64Assembler::immed8_post(int32_t immed8) -{ - LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100, - "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)", - immed8); - amode.value = immed8; - return AMODE_IMM_8_POST; -} - -uint32_t ArmToMips64Assembler::reg_pre(int Rm, int W) -{ - LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented"); - amode.reg = Rm; - return AMODE_REG_PRE; -} - -uint32_t ArmToMips64Assembler::reg_post(int Rm __unused) -{ - LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n"); - return AMODE_UNSUPPORTED; -} - - - -// ---------------------------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Data Processing... -#endif - -// check if the operand registers from a previous CMP or S-bit instruction -// would be overwritten by this instruction. If so, move the value to a -// safe register. -// Note that we cannot tell at _this_ instruction time if a future (conditional) -// instruction will _also_ use this value (a defect of the simple 1-pass, one- -// instruction-at-a-time translation). Therefore we must be conservative and -// save the value before it is overwritten. This costs an extra MOVE instr. - -void ArmToMips64Assembler::protectConditionalOperands(int Rd) -{ - if (Rd == cond.r1) { - mMips->MOVE(R_cmp, cond.r1); - cond.r1 = R_cmp; - } - if (cond.type == CMP_COND && Rd == cond.r2) { - mMips->MOVE(R_cmp2, cond.r2); - cond.r2 = R_cmp2; - } -} - - -// interprets the addressing mode, and generates the common code -// used by the majority of data-processing ops. Many MIPS instructions -// have a register-based form and a different immediate form. See -// opAND below for an example. (this could be inlined) -// -// this works with the imm(), reg_imm() methods above, which are directly -// called by the GLLAssembler. -// note: _signed parameter defaults to false (un-signed) -// note: tmpReg parameter defaults to 1, MIPS register AT -int ArmToMips64Assembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg) -{ - if (op < AMODE_REG) { - source = op; - return SRC_REG; - } else if (op == AMODE_IMM) { - if ((!_signed && amode.value > 0xffff) - || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) { - mMips->LUI(tmpReg, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff)); - } - source = tmpReg; - return SRC_REG; - } else { - source = amode.value; - return SRC_IMM; - } - } else if (op == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break; - case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break; - case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break; - case ROR: mMips->ROTR(tmpReg, amode.reg, amode.value); break; - } - source = tmpReg; - return SRC_REG; - } else { // adr mode RRX is not used in GGL Assembler at this time - // we are screwed, this should be exception, assert-fail or something - LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n"); - return SRC_ERROR; - } -} - - -void ArmToMips64Assembler::dataProcessing(int opcode, int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ - int src; // src is modified by dataProcAdrModes() - passed as int& - - if (cc != AL) { - protectConditionalOperands(Rd); - // the branch tests register(s) set by prev CMP or instr with 'S' bit set - // inverse the condition to jump past this conditional instruction - ArmToMips64Assembler::B(cc^1, cond.label[++cond.labelnum]); - } else { - mArmPC[mInum++] = pc(); // save starting PC for this instr - } - - switch (opcode) { - case opAND: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->AND(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ANDI(Rd, Rn, src); - } - break; - - case opADD: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->ADDU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ADDIU(Rd, Rn, src); - } - break; - - case opSUB: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->SUBU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->SUBIU(Rd, Rn, src); - } - break; - - case opADD64: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->DADDU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->DADDIU(Rd, Rn, src); - } - break; - - case opSUB64: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->DSUBU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->DSUBIU(Rd, Rn, src); - } - break; - - case opEOR: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->XOR(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->XORI(Rd, Rn, src); - } - break; - - case opORR: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->OR(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ORI(Rd, Rn, src); - } - break; - - case opBIC: - if (dataProcAdrModes(Op2, src) == SRC_IMM) { - // if we are 16-bit imnmediate, load to AT reg - mMips->ORI(R_at, 0, src); - src = R_at; - } - mMips->NOT(R_at, src); - mMips->AND(Rd, Rn, R_at); - break; - - case opRSB: - if (dataProcAdrModes(Op2, src) == SRC_IMM) { - // if we are 16-bit imnmediate, load to AT reg - mMips->ORI(R_at, 0, src); - src = R_at; - } - mMips->SUBU(Rd, src, Rn); // subu with the parameters reversed - break; - - case opMOV: - if (Op2 < AMODE_REG) { // op2 is reg # in this case - mMips->MOVE(Rd, Op2); - } else if (Op2 == AMODE_IMM) { - if (amode.value > 0xffff) { - mMips->LUI(Rd, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff)); - } - } else { - mMips->ORI(Rd, 0, amode.value); - } - } else if (Op2 == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(Rd, amode.reg, amode.value); break; - case LSR: mMips->SRL(Rd, amode.reg, amode.value); break; - case ASR: mMips->SRA(Rd, amode.reg, amode.value); break; - case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break; - } - } - else { - // adr mode RRX is not used in GGL Assembler at this time - mMips->UNIMPL(); - } - break; - - case opMVN: // this is a 1's complement: NOT - if (Op2 < AMODE_REG) { // op2 is reg # in this case - mMips->NOR(Rd, Op2, 0); // NOT is NOR with 0 - break; - } else if (Op2 == AMODE_IMM) { - if (amode.value > 0xffff) { - mMips->LUI(Rd, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff)); - } - } else { - mMips->ORI(Rd, 0, amode.value); - } - } else if (Op2 == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(Rd, amode.reg, amode.value); break; - case LSR: mMips->SRL(Rd, amode.reg, amode.value); break; - case ASR: mMips->SRA(Rd, amode.reg, amode.value); break; - case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break; - } - } - else { - // adr mode RRX is not used in GGL Assembler at this time - mMips->UNIMPL(); - } - mMips->NOR(Rd, Rd, 0); // NOT is NOR with 0 - break; - - case opCMP: - // Either operand of a CMP instr could get overwritten by a subsequent - // conditional instruction, which is ok, _UNLESS_ there is a _second_ - // conditional instruction. Under MIPS, this requires doing the comparison - // again (SLT), and the original operands must be available. (and this - // pattern of multiple conditional instructions from same CMP _is_ used - // in GGL-Assembler) - // - // For now, if a conditional instr overwrites the operands, we will - // move them to dedicated temp regs. This is ugly, and inefficient, - // and should be optimized. - // - // WARNING: making an _Assumption_ that CMP operand regs will NOT be - // trashed by intervening NON-conditional instructions. In the general - // case this is legal, but it is NOT currently done in GGL-Assembler. - - cond.type = CMP_COND; - cond.r1 = Rn; - if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) { - cond.r2 = src; - } else { // adr mode was SRC_IMM - mMips->ORI(R_cmp2, R_zero, src); - cond.r2 = R_cmp2; - } - - break; - - - case opTST: - case opTEQ: - case opCMN: - case opADC: - case opSBC: - case opRSC: - mMips->UNIMPL(); // currently unused in GGL Assembler code - break; - } - - if (cc != AL) { - mMips->label(cond.label[cond.labelnum]); - } - if (s && opcode != opCMP) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - - - -#if 0 -#pragma mark - -#pragma mark Multiply... -#endif - -// multiply, accumulate -void ArmToMips64Assembler::MLA(int cc __unused, int s, - int Rd, int Rm, int Rs, int Rn) { - - //ALOGW("MLA"); - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->MUL(R_at, Rm, Rs); - mMips->ADDU(Rd, R_at, Rn); - if (s) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - -void ArmToMips64Assembler::MUL(int cc __unused, int s, - int Rd, int Rm, int Rs) { - mArmPC[mInum++] = pc(); - mMips->MUL(Rd, Rm, Rs); - if (s) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - -void ArmToMips64Assembler::UMULL(int cc __unused, int s, - int RdLo, int RdHi, int Rm, int Rs) { - mArmPC[mInum++] = pc(); - mMips->MUH(RdHi, Rm, Rs); - mMips->MUL(RdLo, Rm, Rs); - - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n"); - } -} - -void ArmToMips64Assembler::UMUAL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n"); - } -} - -void ArmToMips64Assembler::SMULL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n"); - } -} -void ArmToMips64Assembler::SMUAL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on SMUAL must be on 64-bit result\n"); - } -} - - - -#if 0 -#pragma mark - -#pragma mark Branches... -#endif - -// branches... - -void ArmToMips64Assembler::B(int cc, const char* label) -{ - mArmPC[mInum++] = pc(); - if (cond.type == SBIT_COND) { cond.r2 = R_zero; } - - switch(cc) { - case EQ: mMips->BEQ(cond.r1, cond.r2, label); break; - case NE: mMips->BNE(cond.r1, cond.r2, label); break; - case HS: mMips->BGEU(cond.r1, cond.r2, label); break; - case LO: mMips->BLTU(cond.r1, cond.r2, label); break; - case MI: mMips->BLT(cond.r1, cond.r2, label); break; - case PL: mMips->BGE(cond.r1, cond.r2, label); break; - - case HI: mMips->BGTU(cond.r1, cond.r2, label); break; - case LS: mMips->BLEU(cond.r1, cond.r2, label); break; - case GE: mMips->BGE(cond.r1, cond.r2, label); break; - case LT: mMips->BLT(cond.r1, cond.r2, label); break; - case GT: mMips->BGT(cond.r1, cond.r2, label); break; - case LE: mMips->BLE(cond.r1, cond.r2, label); break; - case AL: mMips->B(label); break; - case NV: /* B Never - no instruction */ break; - - case VS: - case VC: - default: - LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc); - break; - } -} - -void ArmToMips64Assembler::BL(int cc __unused, const char* label __unused) -{ - LOG_ALWAYS_FATAL("branch-and-link not supported yet\n"); - mArmPC[mInum++] = pc(); -} - -// no use for Branches with integer PC, but they're in the Interface class .... -void ArmToMips64Assembler::B(int cc __unused, uint32_t* to_pc __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - -void ArmToMips64Assembler::BL(int cc __unused, uint32_t* to_pc __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - -void ArmToMips64Assembler::BX(int cc __unused, int Rn __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - - - -#if 0 -#pragma mark - -#pragma mark Data Transfer... -#endif - -// data transfer... -void ArmToMips64Assembler::LDR(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert LDR via Arm SP to LW via Mips SP - } - mMips->LW(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->DADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to STR thru Mips SP - } - mMips->LW(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->LW(Rd, R_at, 0); - break; - } -} - -void ArmToMips64Assembler::LDRB(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - mMips->LBU(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->DADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->LBU(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->LBU(Rd, R_at, 0); - break; - } - -} - -void ArmToMips64Assembler::STR(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to SW thru Mips SP - } - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - // If we will writeback, then update the index reg, then store. - // This correctly handles stack-push case. - mMips->DADDIU(Rn, Rn, amode.value); - mMips->SW(Rd, Rn, 0); - } else { - // No writeback so store offset by value - mMips->SW(Rd, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->SW(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); // post index always writes back - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->SW(Rd, R_at, 0); - break; - } -} - -void ArmToMips64Assembler::STRB(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - mMips->SB(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->DADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->SB(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->SB(Rd, R_at, 0); - break; - } -} - -void ArmToMips64Assembler::LDRH(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed8_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - // fall thru to next case .... - case AMODE_IMM_8_PRE: // no support yet for writeback - mMips->LHU(Rd, Rn, amode.value); - break; - case AMODE_IMM_8_POST: - mMips->LHU(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_PRE: - // we only support simple base +/- index - if (amode.reg >= 0) { - mMips->DADDU(R_at, Rn, amode.reg); - } else { - mMips->DSUBU(R_at, Rn, abs(amode.reg)); - } - mMips->LHU(Rd, R_at, 0); - break; - } -} - -void ArmToMips64Assembler::LDRSB(int cc __unused, int Rd __unused, - int Rn __unused, uint32_t offset __unused) -{ - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::LDRSH(int cc __unused, int Rd __unused, - int Rn __unused, uint32_t offset __unused) -{ - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::STRH(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed8_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - // fall thru to next case .... - case AMODE_IMM_8_PRE: // no support yet for writeback - mMips->SH(Rd, Rn, amode.value); - break; - case AMODE_IMM_8_POST: - mMips->SH(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_PRE: - // we only support simple base +/- index - if (amode.reg >= 0) { - mMips->DADDU(R_at, Rn, amode.reg); - } else { - mMips->DSUBU(R_at, Rn, abs(amode.reg)); - } - mMips->SH(Rd, R_at, 0); - break; - } -} - - - -#if 0 -#pragma mark - -#pragma mark Block Data Transfer... -#endif - -// block data transfer... -void ArmToMips64Assembler::LDM(int cc __unused, int dir __unused, - int Rn __unused, int W __unused, uint32_t reg_list __unused) -{ // 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::STM(int cc __unused, int dir __unused, - int Rn __unused, int W __unused, uint32_t reg_list __unused) -{ // FA EA FD ED 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - - - -#if 0 -#pragma mark - -#pragma mark Special... -#endif - -// special... -void ArmToMips64Assembler::SWP(int cc __unused, int Rn __unused, - int Rd __unused, int Rm __unused) { - // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::SWPB(int cc __unused, int Rn __unused, - int Rd __unused, int Rm __unused) { - // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::SWI(int cc __unused, uint32_t comment __unused) { - // *mPC++ = (cc<<28) | (0xF<<24) | comment; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - - -#if 0 -#pragma mark - -#pragma mark DSP instructions... -#endif - -// DSP instructions... -void ArmToMips64Assembler::PLD(int Rn __unused, uint32_t offset) { - LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))), - "PLD only P=1, W=0"); - // *mPC++ = 0xF550F000 | (Rn<<16) | offset; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::CLZ(int cc __unused, int Rd, int Rm) -{ - mArmPC[mInum++] = pc(); - mMips->CLZ(Rd, Rm); -} - -void ArmToMips64Assembler::QADD(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::QDADD(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::QSUB(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::QDSUB(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -// 16 x 16 signed multiply (like SMLAxx without the accumulate) -void ArmToMips64Assembler::SMUL(int cc __unused, int xy, - int Rd, int Rm, int Rs) -{ - mArmPC[mInum++] = pc(); - - // the 16 bits may be in the top or bottom half of 32-bit source reg, - // as defined by the codes BB, BT, TB, TT (compressed param xy) - // where x corresponds to Rm and y to Rs - - // select half-reg for Rm - if (xy & xyTB) { - // use top 16-bits - mMips->SRA(R_at, Rm, 16); - } else { - // use bottom 16, but sign-extend to 32 - mMips->SEH(R_at, Rm); - } - // select half-reg for Rs - if (xy & xyBT) { - // use top 16-bits - mMips->SRA(R_at2, Rs, 16); - } else { - // use bottom 16, but sign-extend to 32 - mMips->SEH(R_at2, Rs); - } - mMips->MUL(Rd, R_at, R_at2); -} - -// signed 32b x 16b multiple, save top 32-bits of 48-bit result -void ArmToMips64Assembler::SMULW(int cc __unused, int y, - int Rd, int Rm, int Rs) -{ - mArmPC[mInum++] = pc(); - - // the selector yT or yB refers to reg Rs - if (y & yT) { - // zero the bottom 16-bits, with 2 shifts, it can affect result - mMips->SRL(R_at, Rs, 16); - mMips->SLL(R_at, R_at, 16); - - } else { - // move low 16-bit half, to high half - mMips->SLL(R_at, Rs, 16); - } - mMips->MUH(Rd, Rm, R_at); -} - -// 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn -void ArmToMips64Assembler::SMLA(int cc __unused, int xy, - int Rd, int Rm, int Rs, int Rn) -{ - mArmPC[mInum++] = pc(); - - // the 16 bits may be in the top or bottom half of 32-bit source reg, - // as defined by the codes BB, BT, TB, TT (compressed param xy) - // where x corresponds to Rm and y to Rs - - // select half-reg for Rm - if (xy & xyTB) { - // use top 16-bits - mMips->SRA(R_at, Rm, 16); - } else { - // use bottom 16, but sign-extend to 32 - mMips->SEH(R_at, Rm); - } - // select half-reg for Rs - if (xy & xyBT) { - // use top 16-bits - mMips->SRA(R_at2, Rs, 16); - } else { - // use bottom 16, but sign-extend to 32 - mMips->SEH(R_at2, Rs); - } - - mMips->MUL(R_at, R_at, R_at2); - mMips->ADDU(Rd, R_at, Rn); -} - -void ArmToMips64Assembler::SMLAL(int cc __unused, int xy __unused, - int RdHi __unused, int RdLo __unused, - int Rs __unused, int Rm __unused) -{ - // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMips64Assembler::SMLAW(int cc __unused, int y __unused, - int Rd __unused, int Rm __unused, - int Rs __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -// used by ARMv6 version of GGLAssembler::filter32 -void ArmToMips64Assembler::UXTB16(int cc __unused, int Rd, int Rm, int rotate) -{ - mArmPC[mInum++] = pc(); - - //Rd[31:16] := ZeroExtend((Rm ROR (8 * sh))[23:16]), - //Rd[15:0] := ZeroExtend((Rm ROR (8 * sh))[7:0]). sh 0-3. - - mMips->ROTR(R_at2, Rm, rotate * 8); - mMips->LUI(R_at, 0xFF); - mMips->ORI(R_at, R_at, 0xFF); - mMips->AND(Rd, R_at2, R_at); -} - -void ArmToMips64Assembler::UBFX(int cc __unused, int Rd __unused, int Rn __unused, - int lsb __unused, int width __unused) -{ - /* Placeholder for UBFX */ - mArmPC[mInum++] = pc(); - - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -// ---------------------------------------------------------------------------- -// Address Processing... -// ---------------------------------------------------------------------------- - -void ArmToMips64Assembler::ADDR_ADD(int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ -// if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required -// if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required - dataProcessing(opADD64, cc, s, Rd, Rn, Op2); -} - -void ArmToMips64Assembler::ADDR_SUB(int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ -// if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required -// if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required - dataProcessing(opSUB64, cc, s, Rd, Rn, Op2); -} - -void ArmToMips64Assembler::ADDR_LDR(int cc __unused, int Rd, - int Rn, uint32_t offset) { - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert LDR via Arm SP to LW via Mips SP - } - mMips->LD(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->DADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to STR thru Mips SP - } - mMips->LD(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->LD(Rd, R_at, 0); - break; - } -} - -void ArmToMips64Assembler::ADDR_STR(int cc __unused, int Rd, - int Rn, uint32_t offset) { - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to SW thru Mips SP - } - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - // If we will writeback, then update the index reg, then store. - // This correctly handles stack-push case. - mMips->DADDIU(Rn, Rn, amode.value); - mMips->SD(Rd, Rn, 0); - } else { - // No writeback so store offset by value - mMips->SD(Rd, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->SD(Rd, Rn, 0); - mMips->DADDIU(Rn, Rn, amode.value); // post index always writes back - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->DADDU(R_at, Rn, amode.reg); - mMips->SD(Rd, R_at, 0); - break; - } -} - -#if 0 -#pragma mark - -#pragma mark MIPS Assembler... -#endif - - -//************************************************************************** -//************************************************************************** -//************************************************************************** - - -/* MIPS64 assembler -** this is a subset of mips64r6, targeted specifically at ARM instruction -** replacement in the pixelflinger/codeflinger code. -** -** This class is extended from MIPSAssembler class and overrides only -** MIPS64r6 specific stuff. -*/ - -MIPS64Assembler::MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent) - : MIPSAssembler::MIPSAssembler(assembly, NULL), mParent(parent) -{ -} - -MIPS64Assembler::MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent) - : MIPSAssembler::MIPSAssembler(assembly), mParent(parent) -{ -} - -MIPS64Assembler::~MIPS64Assembler() -{ -} - -void MIPS64Assembler::reset() -{ - if (mAssembly != NULL) { - mBase = mPC = (uint32_t *)mAssembly->base(); - } else { - mPC = mBase = base(); - } - mBranchTargets.clear(); - mLabels.clear(); - mLabelsInverseMapping.clear(); - mComments.clear(); -} - - -void MIPS64Assembler::disassemble(const char* name __unused) -{ - char di_buf[140]; - - bool arm_disasm_fmt = (mParent->mArmDisassemblyBuffer == NULL) ? false : true; - - typedef char dstr[40]; - dstr *lines = (dstr *)mParent->mArmDisassemblyBuffer; - - if (mParent->mArmDisassemblyBuffer != NULL) { - for (int i=0; i<mParent->mArmInstrCount; ++i) { - string_detab(lines[i]); - } - } - - size_t count = pc()-base(); - uint32_t* mipsPC = base(); - - while (count--) { - ssize_t label = mLabelsInverseMapping.indexOfKey(mipsPC); - if (label >= 0) { - ALOGW("%s:\n", mLabelsInverseMapping.valueAt(label)); - } - ssize_t comment = mComments.indexOfKey(mipsPC); - if (comment >= 0) { - ALOGW("; %s\n", mComments.valueAt(comment)); - } - ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); - string_detab(di_buf); - string_pad(di_buf, 30); - ALOGW("%08lx: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf); - mipsPC++; - } -} - -void MIPS64Assembler::fix_branches() -{ - // 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+1)); - *bt.pc |= offset & 0x00FFFF; - } -} - -void MIPS64Assembler::DADDU(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (daddu_fn<<FUNC_SHF) - | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF); -} - -void MIPS64Assembler::DADDIU(int Rt, int Rs, int16_t imm) -{ - *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - -void MIPS64Assembler::DSUBU(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (dsubu_fn<<FUNC_SHF) | - (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ; -} - -void MIPS64Assembler::DSUBIU(int Rt, int Rs, int16_t imm) // really addiu(d, s, -j) -{ - *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | ((-imm) & MSK_16); -} - -void MIPS64Assembler::MUL(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (mul_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) | - (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ; -} - -void MIPS64Assembler::MUH(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (muh_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) | - (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ; -} - -void MIPS64Assembler::CLO(int Rd, int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (17<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF); -} - -void MIPS64Assembler::CLZ(int Rd, int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (16<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF); -} - -void MIPS64Assembler::LD(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (ld_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPS64Assembler::SD(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (sd_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPS64Assembler::LUI(int Rt, int16_t offset) -{ - *mPC++ = (aui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - - -void MIPS64Assembler::JR(int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jalr_fn << FUNC_SHF); - MIPS64Assembler::NOP(); -} - -}; // namespace android: diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.h b/libpixelflinger/codeflinger/MIPS64Assembler.h deleted file mode 100644 index b43e5da04..000000000 --- a/libpixelflinger/codeflinger/MIPS64Assembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp deleted file mode 100644 index 7de8cc11e..000000000 --- a/libpixelflinger/codeflinger/MIPSAssembler.cpp +++ /dev/null @@ -1,1955 +0,0 @@ -/* libs/pixelflinger/codeflinger/MIPSAssembler.cpp -** -** 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. -*/ - - -/* MIPS assembler and ARM->MIPS assembly translator -** -** The approach is to leave the GGLAssembler and associated files largely -** un-changed, still utilizing all Arm instruction generation. Via the -** ArmToMipsAssembler (subclassed from ArmAssemblerInterface) each Arm -** instruction is translated to one or more Mips instructions as necessary. This -** is clearly less efficient than a direct implementation within the -** GGLAssembler, but is far cleaner, more maintainable, and has yielded very -** significant performance gains on Mips compared to the generic pixel pipeline. -** -** -** GGLAssembler changes -** -** - The register allocator has been modified to re-map Arm registers 0-15 to mips -** registers 2-17. Mips register 0 cannot be used as general-purpose register, -** and register 1 has traditional uses as a short-term temporary. -** -** - Added some early bailouts for OUT_OF_REGISTERS in texturing.cpp and -** GGLAssembler.cpp, since this is not fatal, and can be retried at lower -** optimization level. -** -** -** ARMAssembler and ARMAssemblerInterface changes -** -** Refactored ARM address-mode static functions (imm(), reg_imm(), imm12_pre(), etc.) -** to virtual, so they can be overridden in MIPSAssembler. The implementation of these -** functions on ARM is moved from ARMAssemblerInterface.cpp to ARMAssembler.cpp, and -** is unchanged from the original. (This required duplicating 2 of these as static -** functions in ARMAssemblerInterface.cpp so they could be used as static initializers). -*/ - -#define LOG_TAG "MIPSAssembler" - -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> - -#include <cutils/properties.h> -#include <log/log.h> -#include <private/pixelflinger/ggl_context.h> - -#include "CodeCache.h" -#include "MIPSAssembler.h" -#include "mips_disassem.h" - -#define __unused __attribute__((__unused__)) - -// Choose MIPS arch variant following gcc flags -#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 -#define mips32r2 1 -#else -#define mips32r2 0 -#endif - - -#define NOT_IMPLEMENTED() LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__) - - - -// ---------------------------------------------------------------------------- - -namespace android { - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark ArmToMipsAssembler... -#endif - -ArmToMipsAssembler::ArmToMipsAssembler(const sp<Assembly>& assembly, - char *abuf, int linesz, int instr_count) - : ARMAssemblerInterface(), - mArmDisassemblyBuffer(abuf), - mArmLineLength(linesz), - mArmInstrCount(instr_count), - mInum(0), - mAssembly(assembly) -{ - mMips = new MIPSAssembler(assembly, this); - mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *)); - init_conditional_labels(); -} - -ArmToMipsAssembler::~ArmToMipsAssembler() -{ - delete mMips; - free((void *) mArmPC); -} - -uint32_t* ArmToMipsAssembler::pc() const -{ - return mMips->pc(); -} - -uint32_t* ArmToMipsAssembler::base() const -{ - return mMips->base(); -} - -void ArmToMipsAssembler::reset() -{ - cond.labelnum = 0; - mInum = 0; - mMips->reset(); -} - -int ArmToMipsAssembler::getCodegenArch() -{ - return CODEGEN_ARCH_MIPS; -} - -void ArmToMipsAssembler::comment(const char* string) -{ - mMips->comment(string); -} - -void ArmToMipsAssembler::label(const char* theLabel) -{ - mMips->label(theLabel); -} - -void ArmToMipsAssembler::disassemble(const char* name) -{ - mMips->disassemble(name); -} - -void ArmToMipsAssembler::init_conditional_labels() -{ - int i; - for (i=0;i<99; ++i) { - sprintf(cond.label[i], "cond_%d", i); - } -} - - - -#if 0 -#pragma mark - -#pragma mark Prolog/Epilog & Generate... -#endif - -void ArmToMipsAssembler::prolog() -{ - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->ADDIU(R_sp, R_sp, -(5 * 4)); - mMips->SW(R_s0, R_sp, 0); - mMips->SW(R_s1, R_sp, 4); - mMips->SW(R_s2, R_sp, 8); - mMips->SW(R_s3, R_sp, 12); - mMips->SW(R_s4, R_sp, 16); - mMips->MOVE(R_v0, R_a0); // move context * passed in a0 to v0 (arm r0) -} - -void ArmToMipsAssembler::epilog(uint32_t touched __unused) -{ - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->LW(R_s0, R_sp, 0); - mMips->LW(R_s1, R_sp, 4); - mMips->LW(R_s2, R_sp, 8); - mMips->LW(R_s3, R_sp, 12); - mMips->LW(R_s4, R_sp, 16); - mMips->ADDIU(R_sp, R_sp, (5 * 4)); - mMips->JR(R_ra); - -} - -int ArmToMipsAssembler::generate(const char* name) -{ - return mMips->generate(name); -} - -uint32_t* ArmToMipsAssembler::pcForLabel(const char* label) -{ - return mMips->pcForLabel(label); -} - - - -//---------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Addressing modes & shifters... -#endif - - -// do not need this for MIPS, but it is in the Interface (virtual) -int ArmToMipsAssembler::buildImmediate( - uint32_t immediate, uint32_t& rot, uint32_t& imm) -{ - // for MIPS, any 32-bit immediate is OK - rot = 0; - imm = immediate; - return 0; -} - -// shifters... - -bool ArmToMipsAssembler::isValidImmediate(uint32_t immediate __unused) -{ - // for MIPS, any 32-bit immediate is OK - return true; -} - -uint32_t ArmToMipsAssembler::imm(uint32_t immediate) -{ - // ALOGW("immediate value %08x at pc %08x\n", immediate, (int)pc()); - amode.value = immediate; - return AMODE_IMM; -} - -uint32_t ArmToMipsAssembler::reg_imm(int Rm, int type, uint32_t shift) -{ - amode.reg = Rm; - amode.stype = type; - amode.value = shift; - return AMODE_REG_IMM; -} - -uint32_t ArmToMipsAssembler::reg_rrx(int Rm __unused) -{ - // reg_rrx mode is not used in the GLLAssember code at this time - return AMODE_UNSUPPORTED; -} - -uint32_t ArmToMipsAssembler::reg_reg(int Rm __unused, int type __unused, - int Rs __unused) -{ - // reg_reg mode is not used in the GLLAssember code at this time - return AMODE_UNSUPPORTED; -} - - -// addressing modes... -// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMipsAssembler::immed12_pre(int32_t immed12, int W) -{ - LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800, - "LDR(B)/STR(B)/PLD immediate too big (%08x)", - immed12); - amode.value = immed12; - amode.writeback = W; - return AMODE_IMM_12_PRE; -} - -uint32_t ArmToMipsAssembler::immed12_post(int32_t immed12) -{ - LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800, - "LDR(B)/STR(B)/PLD immediate too big (%08x)", - immed12); - - amode.value = immed12; - return AMODE_IMM_12_POST; -} - -uint32_t ArmToMipsAssembler::reg_scale_pre(int Rm, int type, - uint32_t shift, int W) -{ - LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented"); - - amode.reg = Rm; - // amode.stype = type; // more advanced modes not used in GGLAssembler yet - // amode.value = shift; - // amode.writeback = W; - return AMODE_REG_SCALE_PRE; -} - -uint32_t ArmToMipsAssembler::reg_scale_post(int Rm __unused, int type __unused, - uint32_t shift __unused) -{ - LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n"); - return AMODE_UNSUPPORTED; -} - -// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0) -uint32_t ArmToMipsAssembler::immed8_pre(int32_t immed8, int W __unused) -{ - // uint32_t offset = abs(immed8); - - LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n"); - - LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100, - "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)", - immed8); - return AMODE_IMM_8_PRE; -} - -uint32_t ArmToMipsAssembler::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); - amode.value = immed8; - return AMODE_IMM_8_POST; -} - -uint32_t ArmToMipsAssembler::reg_pre(int Rm, int W) -{ - LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented"); - amode.reg = Rm; - return AMODE_REG_PRE; -} - -uint32_t ArmToMipsAssembler::reg_post(int Rm __unused) -{ - LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n"); - return AMODE_UNSUPPORTED; -} - - - -// ---------------------------------------------------------------------------- - -#if 0 -#pragma mark - -#pragma mark Data Processing... -#endif - -// check if the operand registers from a previous CMP or S-bit instruction -// would be overwritten by this instruction. If so, move the value to a -// safe register. -// Note that we cannot tell at _this_ instruction time if a future (conditional) -// instruction will _also_ use this value (a defect of the simple 1-pass, one- -// instruction-at-a-time translation). Therefore we must be conservative and -// save the value before it is overwritten. This costs an extra MOVE instr. - -void ArmToMipsAssembler::protectConditionalOperands(int Rd) -{ - if (Rd == cond.r1) { - mMips->MOVE(R_cmp, cond.r1); - cond.r1 = R_cmp; - } - if (cond.type == CMP_COND && Rd == cond.r2) { - mMips->MOVE(R_cmp2, cond.r2); - cond.r2 = R_cmp2; - } -} - - -// interprets the addressing mode, and generates the common code -// used by the majority of data-processing ops. Many MIPS instructions -// have a register-based form and a different immediate form. See -// opAND below for an example. (this could be inlined) -// -// this works with the imm(), reg_imm() methods above, which are directly -// called by the GLLAssembler. -// note: _signed parameter defaults to false (un-signed) -// note: tmpReg parameter defaults to 1, MIPS register AT -int ArmToMipsAssembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg) -{ - if (op < AMODE_REG) { - source = op; - return SRC_REG; - } else if (op == AMODE_IMM) { - if ((!_signed && amode.value > 0xffff) - || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) { - mMips->LUI(tmpReg, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff)); - } - source = tmpReg; - return SRC_REG; - } else { - source = amode.value; - return SRC_IMM; - } - } else if (op == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break; - case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break; - case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break; - case ROR: if (mips32r2) { - mMips->ROTR(tmpReg, amode.reg, amode.value); - } else { - mMips->RORIsyn(tmpReg, amode.reg, amode.value); - } - break; - } - source = tmpReg; - return SRC_REG; - } else { // adr mode RRX is not used in GGL Assembler at this time - // we are screwed, this should be exception, assert-fail or something - LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n"); - return SRC_ERROR; - } -} - - -void ArmToMipsAssembler::dataProcessing(int opcode, int cc, - int s, int Rd, int Rn, uint32_t Op2) -{ - int src; // src is modified by dataProcAdrModes() - passed as int& - - - if (cc != AL) { - protectConditionalOperands(Rd); - // the branch tests register(s) set by prev CMP or instr with 'S' bit set - // inverse the condition to jump past this conditional instruction - ArmToMipsAssembler::B(cc^1, cond.label[++cond.labelnum]); - } else { - mArmPC[mInum++] = pc(); // save starting PC for this instr - } - - switch (opcode) { - case opAND: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->AND(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ANDI(Rd, Rn, src); - } - break; - - case opADD: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->ADDU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ADDIU(Rd, Rn, src); - } - break; - - case opSUB: - // set "signed" to true for adr modes - if (dataProcAdrModes(Op2, src, true) == SRC_REG) { - mMips->SUBU(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->SUBIU(Rd, Rn, src); - } - break; - - case opEOR: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->XOR(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->XORI(Rd, Rn, src); - } - break; - - case opORR: - if (dataProcAdrModes(Op2, src) == SRC_REG) { - mMips->OR(Rd, Rn, src); - } else { // adr mode was SRC_IMM - mMips->ORI(Rd, Rn, src); - } - break; - - case opBIC: - if (dataProcAdrModes(Op2, src) == SRC_IMM) { - // if we are 16-bit imnmediate, load to AT reg - mMips->ORI(R_at, 0, src); - src = R_at; - } - mMips->NOT(R_at, src); - mMips->AND(Rd, Rn, R_at); - break; - - case opRSB: - if (dataProcAdrModes(Op2, src) == SRC_IMM) { - // if we are 16-bit imnmediate, load to AT reg - mMips->ORI(R_at, 0, src); - src = R_at; - } - mMips->SUBU(Rd, src, Rn); // subu with the parameters reversed - break; - - case opMOV: - if (Op2 < AMODE_REG) { // op2 is reg # in this case - mMips->MOVE(Rd, Op2); - } else if (Op2 == AMODE_IMM) { - if (amode.value > 0xffff) { - mMips->LUI(Rd, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff)); - } - } else { - mMips->ORI(Rd, 0, amode.value); - } - } else if (Op2 == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(Rd, amode.reg, amode.value); break; - case LSR: mMips->SRL(Rd, amode.reg, amode.value); break; - case ASR: mMips->SRA(Rd, amode.reg, amode.value); break; - case ROR: if (mips32r2) { - mMips->ROTR(Rd, amode.reg, amode.value); - } else { - mMips->RORIsyn(Rd, amode.reg, amode.value); - } - break; - } - } - else { - // adr mode RRX is not used in GGL Assembler at this time - mMips->UNIMPL(); - } - break; - - case opMVN: // this is a 1's complement: NOT - if (Op2 < AMODE_REG) { // op2 is reg # in this case - mMips->NOR(Rd, Op2, 0); // NOT is NOR with 0 - break; - } else if (Op2 == AMODE_IMM) { - if (amode.value > 0xffff) { - mMips->LUI(Rd, (amode.value >> 16)); - if (amode.value & 0x0000ffff) { - mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff)); - } - } else { - mMips->ORI(Rd, 0, amode.value); - } - } else if (Op2 == AMODE_REG_IMM) { - switch (amode.stype) { - case LSL: mMips->SLL(Rd, amode.reg, amode.value); break; - case LSR: mMips->SRL(Rd, amode.reg, amode.value); break; - case ASR: mMips->SRA(Rd, amode.reg, amode.value); break; - case ROR: if (mips32r2) { - mMips->ROTR(Rd, amode.reg, amode.value); - } else { - mMips->RORIsyn(Rd, amode.reg, amode.value); - } - break; - } - } - else { - // adr mode RRX is not used in GGL Assembler at this time - mMips->UNIMPL(); - } - mMips->NOR(Rd, Rd, 0); // NOT is NOR with 0 - break; - - case opCMP: - // Either operand of a CMP instr could get overwritten by a subsequent - // conditional instruction, which is ok, _UNLESS_ there is a _second_ - // conditional instruction. Under MIPS, this requires doing the comparison - // again (SLT), and the original operands must be available. (and this - // pattern of multiple conditional instructions from same CMP _is_ used - // in GGL-Assembler) - // - // For now, if a conditional instr overwrites the operands, we will - // move them to dedicated temp regs. This is ugly, and inefficient, - // and should be optimized. - // - // WARNING: making an _Assumption_ that CMP operand regs will NOT be - // trashed by intervening NON-conditional instructions. In the general - // case this is legal, but it is NOT currently done in GGL-Assembler. - - cond.type = CMP_COND; - cond.r1 = Rn; - if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) { - cond.r2 = src; - } else { // adr mode was SRC_IMM - mMips->ORI(R_cmp2, R_zero, src); - cond.r2 = R_cmp2; - } - - break; - - - case opTST: - case opTEQ: - case opCMN: - case opADC: - case opSBC: - case opRSC: - mMips->UNIMPL(); // currently unused in GGL Assembler code - break; - } - - if (cc != AL) { - mMips->label(cond.label[cond.labelnum]); - } - if (s && opcode != opCMP) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - - - -#if 0 -#pragma mark - -#pragma mark Multiply... -#endif - -// multiply, accumulate -void ArmToMipsAssembler::MLA(int cc __unused, int s, - int Rd, int Rm, int Rs, int Rn) { - - mArmPC[mInum++] = pc(); // save starting PC for this instr - - mMips->MUL(R_at, Rm, Rs); - mMips->ADDU(Rd, R_at, Rn); - if (s) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - -void ArmToMipsAssembler::MUL(int cc __unused, int s, - int Rd, int Rm, int Rs) { - mArmPC[mInum++] = pc(); - mMips->MUL(Rd, Rm, Rs); - if (s) { - cond.type = SBIT_COND; - cond.r1 = Rd; - } -} - -void ArmToMipsAssembler::UMULL(int cc __unused, int s, - int RdLo, int RdHi, int Rm, int Rs) { - mArmPC[mInum++] = pc(); - mMips->MULT(Rm, Rs); - mMips->MFHI(RdHi); - mMips->MFLO(RdLo); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n"); - } -} - -void ArmToMipsAssembler::UMUAL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n"); - } -} - -void ArmToMipsAssembler::SMULL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n"); - } -} -void ArmToMipsAssembler::SMUAL(int cc __unused, int s, - int RdLo __unused, int RdHi, int Rm __unused, int Rs __unused) { - 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); - if (s) { - cond.type = SBIT_COND; - cond.r1 = RdHi; // BUG... - LOG_ALWAYS_FATAL("Condition on SMUAL must be on 64-bit result\n"); - } -} - - - -#if 0 -#pragma mark - -#pragma mark Branches... -#endif - -// branches... - -void ArmToMipsAssembler::B(int cc, const char* label) -{ - mArmPC[mInum++] = pc(); - if (cond.type == SBIT_COND) { cond.r2 = R_zero; } - - switch(cc) { - case EQ: mMips->BEQ(cond.r1, cond.r2, label); break; - case NE: mMips->BNE(cond.r1, cond.r2, label); break; - case HS: mMips->BGEU(cond.r1, cond.r2, label); break; - case LO: mMips->BLTU(cond.r1, cond.r2, label); break; - case MI: mMips->BLT(cond.r1, cond.r2, label); break; - case PL: mMips->BGE(cond.r1, cond.r2, label); break; - - case HI: mMips->BGTU(cond.r1, cond.r2, label); break; - case LS: mMips->BLEU(cond.r1, cond.r2, label); break; - case GE: mMips->BGE(cond.r1, cond.r2, label); break; - case LT: mMips->BLT(cond.r1, cond.r2, label); break; - case GT: mMips->BGT(cond.r1, cond.r2, label); break; - case LE: mMips->BLE(cond.r1, cond.r2, label); break; - case AL: mMips->B(label); break; - case NV: /* B Never - no instruction */ break; - - case VS: - case VC: - default: - LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc); - break; - } -} - -void ArmToMipsAssembler::BL(int cc __unused, const char* label __unused) -{ - LOG_ALWAYS_FATAL("branch-and-link not supported yet\n"); - mArmPC[mInum++] = pc(); -} - -// no use for Branches with integer PC, but they're in the Interface class .... -void ArmToMipsAssembler::B(int cc __unused, uint32_t* to_pc __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - -void ArmToMipsAssembler::BL(int cc __unused, uint32_t* to_pc __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - -void ArmToMipsAssembler::BX(int cc __unused, int Rn __unused) -{ - LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n"); - mArmPC[mInum++] = pc(); -} - - - -#if 0 -#pragma mark - -#pragma mark Data Transfer... -#endif - -// data transfer... -void ArmToMipsAssembler::LDR(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert LDR via Arm SP to LW via Mips SP - } - mMips->LW(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->ADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to STR thru Mips SP - } - mMips->LW(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->ADDU(R_at, Rn, amode.reg); - mMips->LW(Rd, R_at, 0); - break; - } -} - -void ArmToMipsAssembler::LDRB(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - mMips->LBU(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->ADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->LBU(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->ADDU(R_at, Rn, amode.reg); - mMips->LBU(Rd, R_at, 0); - break; - } - -} - -void ArmToMipsAssembler::STR(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - if (Rn == ARMAssemblerInterface::SP) { - Rn = R_sp; // convert STR thru Arm SP to SW thru Mips SP - } - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - // If we will writeback, then update the index reg, then store. - // This correctly handles stack-push case. - mMips->ADDIU(Rn, Rn, amode.value); - mMips->SW(Rd, Rn, 0); - } else { - // No writeback so store offset by value - mMips->SW(Rd, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->SW(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); // post index always writes back - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->ADDU(R_at, Rn, amode.reg); - mMips->SW(Rd, R_at, 0); - break; - } -} - -void ArmToMipsAssembler::STRB(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed12_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - amode.writeback = 0; - // fall thru to next case .... - case AMODE_IMM_12_PRE: - mMips->SB(Rd, Rn, amode.value); - if (amode.writeback) { // OPTIONAL writeback on pre-index mode - mMips->ADDIU(Rn, Rn, amode.value); - } - break; - case AMODE_IMM_12_POST: - mMips->SB(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_SCALE_PRE: - // we only support simple base + index, no advanced modes for this one yet - mMips->ADDU(R_at, Rn, amode.reg); - mMips->SB(Rd, R_at, 0); - break; - } -} - -void ArmToMipsAssembler::LDRH(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed8_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - // fall thru to next case .... - case AMODE_IMM_8_PRE: // no support yet for writeback - mMips->LHU(Rd, Rn, amode.value); - break; - case AMODE_IMM_8_POST: - mMips->LHU(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_PRE: - // we only support simple base +/- index - if (amode.reg >= 0) { - mMips->ADDU(R_at, Rn, amode.reg); - } else { - mMips->SUBU(R_at, Rn, abs(amode.reg)); - } - mMips->LHU(Rd, R_at, 0); - break; - } -} - -void ArmToMipsAssembler::LDRSB(int cc __unused, int Rd __unused, - int Rn __unused, uint32_t offset __unused) -{ - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::LDRSH(int cc __unused, int Rd __unused, - int Rn __unused, uint32_t offset __unused) -{ - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::STRH(int cc __unused, int Rd, int Rn, uint32_t offset) -{ - mArmPC[mInum++] = pc(); - // work-around for ARM default address mode of immed8_pre(0) - if (offset > AMODE_UNSUPPORTED) offset = 0; - switch (offset) { - case 0: - amode.value = 0; - // fall thru to next case .... - case AMODE_IMM_8_PRE: // no support yet for writeback - mMips->SH(Rd, Rn, amode.value); - break; - case AMODE_IMM_8_POST: - mMips->SH(Rd, Rn, 0); - mMips->ADDIU(Rn, Rn, amode.value); - break; - case AMODE_REG_PRE: - // we only support simple base +/- index - if (amode.reg >= 0) { - mMips->ADDU(R_at, Rn, amode.reg); - } else { - mMips->SUBU(R_at, Rn, abs(amode.reg)); - } - mMips->SH(Rd, R_at, 0); - break; - } -} - - - -#if 0 -#pragma mark - -#pragma mark Block Data Transfer... -#endif - -// block data transfer... -void ArmToMipsAssembler::LDM(int cc __unused, int dir __unused, - int Rn __unused, int W __unused, uint32_t reg_list __unused) -{ // 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::STM(int cc __unused, int dir __unused, - int Rn __unused, int W __unused, uint32_t reg_list __unused) -{ // FA EA FD ED 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; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - - - -#if 0 -#pragma mark - -#pragma mark Special... -#endif - -// special... -void ArmToMipsAssembler::SWP(int cc __unused, int Rn __unused, - int Rd __unused, int Rm __unused) { - // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::SWPB(int cc __unused, int Rn __unused, - int Rd __unused, int Rm __unused) { - // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::SWI(int cc __unused, uint32_t comment __unused) { - // *mPC++ = (cc<<28) | (0xF<<24) | comment; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - - -#if 0 -#pragma mark - -#pragma mark DSP instructions... -#endif - -// DSP instructions... -void ArmToMipsAssembler::PLD(int Rn __unused, uint32_t offset) { - LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))), - "PLD only P=1, W=0"); - // *mPC++ = 0xF550F000 | (Rn<<16) | offset; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::CLZ(int cc __unused, int Rd, int Rm) -{ - mArmPC[mInum++] = pc(); - mMips->CLZ(Rd, Rm); -} - -void ArmToMipsAssembler::QADD(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::QDADD(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::QSUB(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::QDSUB(int cc __unused, int Rd __unused, - int Rm __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -// 16 x 16 signed multiply (like SMLAxx without the accumulate) -void ArmToMipsAssembler::SMUL(int cc __unused, int xy, - int Rd, int Rm, int Rs) -{ - mArmPC[mInum++] = pc(); - - // the 16 bits may be in the top or bottom half of 32-bit source reg, - // as defined by the codes BB, BT, TB, TT (compressed param xy) - // where x corresponds to Rm and y to Rs - - // select half-reg for Rm - if (xy & xyTB) { - // use top 16-bits - mMips->SRA(R_at, Rm, 16); - } else { - // use bottom 16, but sign-extend to 32 - if (mips32r2) { - mMips->SEH(R_at, Rm); - } else { - mMips->SLL(R_at, Rm, 16); - mMips->SRA(R_at, R_at, 16); - } - } - // select half-reg for Rs - if (xy & xyBT) { - // use top 16-bits - mMips->SRA(R_at2, Rs, 16); - } else { - // use bottom 16, but sign-extend to 32 - if (mips32r2) { - mMips->SEH(R_at2, Rs); - } else { - mMips->SLL(R_at2, Rs, 16); - mMips->SRA(R_at2, R_at2, 16); - } - } - mMips->MUL(Rd, R_at, R_at2); -} - -// signed 32b x 16b multiple, save top 32-bits of 48-bit result -void ArmToMipsAssembler::SMULW(int cc __unused, int y, - int Rd, int Rm, int Rs) -{ - mArmPC[mInum++] = pc(); - - // the selector yT or yB refers to reg Rs - if (y & yT) { - // zero the bottom 16-bits, with 2 shifts, it can affect result - mMips->SRL(R_at, Rs, 16); - mMips->SLL(R_at, R_at, 16); - - } else { - // move low 16-bit half, to high half - mMips->SLL(R_at, Rs, 16); - } - mMips->MULT(Rm, R_at); - mMips->MFHI(Rd); -} - -// 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn -void ArmToMipsAssembler::SMLA(int cc __unused, int xy, - int Rd, int Rm, int Rs, int Rn) -{ - mArmPC[mInum++] = pc(); - - // the 16 bits may be in the top or bottom half of 32-bit source reg, - // as defined by the codes BB, BT, TB, TT (compressed param xy) - // where x corresponds to Rm and y to Rs - - // select half-reg for Rm - if (xy & xyTB) { - // use top 16-bits - mMips->SRA(R_at, Rm, 16); - } else { - // use bottom 16, but sign-extend to 32 - if (mips32r2) { - mMips->SEH(R_at, Rm); - } else { - mMips->SLL(R_at, Rm, 16); - mMips->SRA(R_at, R_at, 16); - } - } - // select half-reg for Rs - if (xy & xyBT) { - // use top 16-bits - mMips->SRA(R_at2, Rs, 16); - } else { - // use bottom 16, but sign-extend to 32 - if (mips32r2) { - mMips->SEH(R_at2, Rs); - } else { - mMips->SLL(R_at2, Rs, 16); - mMips->SRA(R_at2, R_at2, 16); - } - } - - mMips->MUL(R_at, R_at, R_at2); - mMips->ADDU(Rd, R_at, Rn); -} - -void ArmToMipsAssembler::SMLAL(int cc __unused, int xy __unused, - int RdHi __unused, int RdLo __unused, - int Rs __unused, int Rm __unused) -{ - // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -void ArmToMipsAssembler::SMLAW(int cc __unused, int y __unused, - int Rd __unused, int Rm __unused, - int Rs __unused, int Rn __unused) -{ - // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm; - mArmPC[mInum++] = pc(); - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - -// used by ARMv6 version of GGLAssembler::filter32 -void ArmToMipsAssembler::UXTB16(int cc __unused, int Rd, int Rm, int rotate) -{ - mArmPC[mInum++] = pc(); - - //Rd[31:16] := ZeroExtend((Rm ROR (8 * sh))[23:16]), - //Rd[15:0] := ZeroExtend((Rm ROR (8 * sh))[7:0]). sh 0-3. - - mMips->ROTR(Rm, Rm, rotate * 8); - mMips->AND(Rd, Rm, 0x00FF00FF); -} - -void ArmToMipsAssembler::UBFX(int cc __unused, int Rd __unused, - int Rn __unused, int lsb __unused, - int width __unused) -{ - /* Placeholder for UBFX */ - mArmPC[mInum++] = pc(); - - mMips->NOP2(); - NOT_IMPLEMENTED(); -} - - - - - -#if 0 -#pragma mark - -#pragma mark MIPS Assembler... -#endif - - -//************************************************************************** -//************************************************************************** -//************************************************************************** - - -/* mips assembler -** this is a subset of mips32r2, targeted specifically at ARM instruction -** replacement in the pixelflinger/codeflinger code. -** -** To that end, there is no need for floating point, or priviledged -** instructions. This all runs in user space, no float. -** -** The syntax makes no attempt to be as complete as the assember, with -** synthetic instructions, and automatic recognition of immedate operands -** (use the immediate form of the instruction), etc. -** -** We start with mips32r1, and may add r2 and dsp extensions if cpu -** supports. Decision will be made at compile time, based on gcc -** options. (makes sense since android will be built for a a specific -** device) -*/ - -MIPSAssembler::MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent) - : mParent(parent), - mAssembly(assembly) -{ - mBase = mPC = (uint32_t *)assembly->base(); - mDuration = ggl_system_time(); -} - -MIPSAssembler::MIPSAssembler(void* assembly) - : mParent(NULL), mAssembly(NULL) -{ - mBase = mPC = (uint32_t *)assembly; -} - -MIPSAssembler::~MIPSAssembler() -{ -} - - -uint32_t* MIPSAssembler::pc() const -{ - return mPC; -} - -uint32_t* MIPSAssembler::base() const -{ - return mBase; -} - -void MIPSAssembler::reset() -{ - mBase = mPC = (uint32_t *)mAssembly->base(); - mBranchTargets.clear(); - mLabels.clear(); - mLabelsInverseMapping.clear(); - mComments.clear(); -} - - -// convert tabs to spaces, and remove any newline -// works with strings of limited size (makes a temp copy) -#define TABSTOP 8 -void MIPSAssembler::string_detab(char *s) -{ - char *os = s; - char temp[100]; - char *t = temp; - int len = 99; - int i = TABSTOP; - - while (*s && len-- > 0) { - if (*s == '\n') { s++; continue; } - if (*s == '\t') { - s++; - for ( ; i>0; i--) {*t++ = ' '; len--; } - } else { - *t++ = *s++; - } - if (i <= 0) i = TABSTOP; - i--; - } - *t = '\0'; - strcpy(os, temp); -} - -void MIPSAssembler::string_pad(char *s, int padded_len) -{ - int len = strlen(s); - s += len; - for (int i = padded_len - len; i > 0; --i) { - *s++ = ' '; - } - *s = '\0'; -} - -// ---------------------------------------------------------------------------- - -void MIPSAssembler::disassemble(const char* name) -{ - char di_buf[140]; - - if (name) { - ALOGW("%s:\n", name); - } - - bool arm_disasm_fmt = (mParent->mArmDisassemblyBuffer == NULL) ? false : true; - - typedef char dstr[40]; - dstr *lines = (dstr *)mParent->mArmDisassemblyBuffer; - - if (mParent->mArmDisassemblyBuffer != NULL) { - for (int i=0; i<mParent->mArmInstrCount; ++i) { - string_detab(lines[i]); - } - } - - size_t count = pc()-base(); - uint32_t* mipsPC = base(); - while (count--) { - ssize_t label = mLabelsInverseMapping.indexOfKey(mipsPC); - if (label >= 0) { - ALOGW("%s:\n", mLabelsInverseMapping.valueAt(label)); - } - ssize_t comment = mComments.indexOfKey(mipsPC); - if (comment >= 0) { - ALOGW("; %s\n", mComments.valueAt(comment)); - } - // ALOGW("%08x: %08x ", int(i), int(i[0])); - ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); - string_detab(di_buf); - string_pad(di_buf, 30); - ALOGW("0x%p: %08x %s", mipsPC, uint32_t(*mipsPC), di_buf); - mipsPC++; - } -} - -void MIPSAssembler::comment(const char* string) -{ - mComments.add(pc(), string); -} - -void MIPSAssembler::label(const char* theLabel) -{ - mLabels.add(theLabel, pc()); - mLabelsInverseMapping.add(pc(), theLabel); -} - - -void MIPSAssembler::prolog() -{ - // empty - done in ArmToMipsAssembler -} - -void MIPSAssembler::epilog(uint32_t touched __unused) -{ - // empty - done in ArmToMipsAssembler -} - -int MIPSAssembler::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+1)); - *bt.pc |= offset & 0x00FFFF; - } - - mAssembly->resize( int(pc()-base())*4 ); - - // the instruction & data caches are flushed by CodeCache - const int64_t duration = ggl_system_time() - mDuration; - const char * const format = "generated %s (%d ins) at [%p:%p] in %" PRId64 " ns\n"; - ALOGI(format, name, int(pc()-base()), base(), pc(), duration); - - char value[PROPERTY_VALUE_MAX]; - value[0] = '\0'; - - property_get("debug.pf.disasm", value, "0"); - - if (atoi(value) != 0) { - disassemble(name); - } - - return OK; -} - -uint32_t* MIPSAssembler::pcForLabel(const char* label) -{ - return mLabels.valueFor(label); -} - - - -#if 0 -#pragma mark - -#pragma mark Arithmetic... -#endif - -void MIPSAssembler::ADDU(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (addu_fn<<FUNC_SHF) - | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF); -} - -// MD00086 pdf says this is: ADDIU rt, rs, imm -- they do not use Rd -void MIPSAssembler::ADDIU(int Rt, int Rs, int16_t imm) -{ - *mPC++ = (addiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - - -void MIPSAssembler::SUBU(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (subu_fn<<FUNC_SHF) | - (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ; -} - - -void MIPSAssembler::SUBIU(int Rt, int Rs, int16_t imm) // really addiu(d, s, -j) -{ - *mPC++ = (addiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | ((-imm) & MSK_16); -} - - -void MIPSAssembler::NEGU(int Rd, int Rs) // really subu(d, zero, s) -{ - MIPSAssembler::SUBU(Rd, 0, Rs); -} - -void MIPSAssembler::MUL(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec2_op<<OP_SHF) | (mul_fn<<FUNC_SHF) | - (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ; -} - -void MIPSAssembler::MULT(int Rs, int Rt) // dest is hi,lo -{ - *mPC++ = (spec_op<<OP_SHF) | (mult_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - -void MIPSAssembler::MULTU(int Rs, int Rt) // dest is hi,lo -{ - *mPC++ = (spec_op<<OP_SHF) | (multu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - -void MIPSAssembler::MADD(int Rs, int Rt) // hi,lo = hi,lo + Rs * Rt -{ - *mPC++ = (spec2_op<<OP_SHF) | (madd_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - -void MIPSAssembler::MADDU(int Rs, int Rt) // hi,lo = hi,lo + Rs * Rt -{ - *mPC++ = (spec2_op<<OP_SHF) | (maddu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - - -void MIPSAssembler::MSUB(int Rs, int Rt) // hi,lo = hi,lo - Rs * Rt -{ - *mPC++ = (spec2_op<<OP_SHF) | (msub_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - -void MIPSAssembler::MSUBU(int Rs, int Rt) // hi,lo = hi,lo - Rs * Rt -{ - *mPC++ = (spec2_op<<OP_SHF) | (msubu_fn<<FUNC_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF); -} - - -void MIPSAssembler::SEB(int Rd, int Rt) // sign-extend byte (mips32r2) -{ - *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (seb_fn << SA_SHF) | - (Rt<<RT_SHF) | (Rd<<RD_SHF); -} - -void MIPSAssembler::SEH(int Rd, int Rt) // sign-extend half-word (mips32r2) -{ - *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (seh_fn << SA_SHF) | - (Rt<<RT_SHF) | (Rd<<RD_SHF); -} - - - -#if 0 -#pragma mark - -#pragma mark Comparisons... -#endif - -void MIPSAssembler::SLT(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (slt_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::SLTI(int Rt, int Rs, int16_t imm) -{ - *mPC++ = (slti_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - - -void MIPSAssembler::SLTU(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (sltu_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::SLTIU(int Rt, int Rs, int16_t imm) -{ - *mPC++ = (sltiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - - - -#if 0 -#pragma mark - -#pragma mark Logical... -#endif - -void MIPSAssembler::AND(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (and_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::ANDI(int Rt, int Rs, uint16_t imm) // todo: support larger immediate -{ - *mPC++ = (andi_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - - -void MIPSAssembler::OR(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (or_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::ORI(int Rt, int Rs, uint16_t imm) -{ - *mPC++ = (ori_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - -void MIPSAssembler::NOR(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (nor_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::NOT(int Rd, int Rs) -{ - MIPSAssembler::NOR(Rd, Rs, 0); // NOT(d,s) = NOR(d,s,zero) -} - -void MIPSAssembler::XOR(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (xor_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::XORI(int Rt, int Rs, uint16_t imm) // todo: support larger immediate -{ - *mPC++ = (xori_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16); -} - -void MIPSAssembler::SLL(int Rd, int Rt, int shft) -{ - *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF); -} - -void MIPSAssembler::SLLV(int Rd, int Rt, int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (sllv_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::SRL(int Rd, int Rt, int shft) -{ - *mPC++ = (spec_op<<OP_SHF) | (srl_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF); -} - -void MIPSAssembler::SRLV(int Rd, int Rt, int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (srlv_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::SRA(int Rd, int Rt, int shft) -{ - *mPC++ = (spec_op<<OP_SHF) | (sra_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF); -} - -void MIPSAssembler::SRAV(int Rd, int Rt, int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (srav_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::ROTR(int Rd, int Rt, int shft) // mips32r2 -{ - // note weird encoding (SRL + 1) - *mPC++ = (spec_op<<OP_SHF) | (srl_fn<<FUNC_SHF) | - (1<<RS_SHF) | (Rd<<RD_SHF) | (Rt<<RT_SHF) | (shft<<RE_SHF); -} - -void MIPSAssembler::ROTRV(int Rd, int Rt, int Rs) // mips32r2 -{ - // note weird encoding (SRLV + 1) - *mPC++ = (spec_op<<OP_SHF) | (srlv_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (1<<RE_SHF); -} - -// uses at2 register (mapped to some appropriate mips reg) -void MIPSAssembler::RORsyn(int Rd, int Rt, int Rs) -{ - // synthetic: d = t rotated by s - MIPSAssembler::NEGU(R_at2, Rs); - MIPSAssembler::SLLV(R_at2, Rt, R_at2); - MIPSAssembler::SRLV(Rd, Rt, Rs); - MIPSAssembler::OR(Rd, Rd, R_at2); -} - -// immediate version - uses at2 register (mapped to some appropriate mips reg) -void MIPSAssembler::RORIsyn(int Rd, int Rt, int rot) -{ - // synthetic: d = t rotated by immed rot - // d = s >> rot | s << (32-rot) - MIPSAssembler::SLL(R_at2, Rt, 32-rot); - MIPSAssembler::SRL(Rd, Rt, rot); - MIPSAssembler::OR(Rd, Rd, R_at2); -} - -void MIPSAssembler::CLO(int Rd, int Rs) -{ - // Rt field must have same gpr # as Rd - *mPC++ = (spec2_op<<OP_SHF) | (clo_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rd<<RT_SHF); -} - -void MIPSAssembler::CLZ(int Rd, int Rs) -{ - // Rt field must have same gpr # as Rd - *mPC++ = (spec2_op<<OP_SHF) | (clz_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rd<<RT_SHF); -} - -void MIPSAssembler::WSBH(int Rd, int Rt) // mips32r2 -{ - *mPC++ = (spec3_op<<OP_SHF) | (bshfl_fn<<FUNC_SHF) | (wsbh_fn << SA_SHF) | - (Rt<<RT_SHF) | (Rd<<RD_SHF); -} - - - -#if 0 -#pragma mark - -#pragma mark Load/store... -#endif - -void MIPSAssembler::LW(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (lw_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::SW(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (sw_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -// lb is sign-extended -void MIPSAssembler::LB(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (lb_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::LBU(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (lbu_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::SB(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (sb_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -// lh is sign-extended -void MIPSAssembler::LH(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (lh_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::LHU(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (lhu_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::SH(int Rt, int Rbase, int16_t offset) -{ - *mPC++ = (sh_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - -void MIPSAssembler::LUI(int Rt, int16_t offset) -{ - *mPC++ = (lui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); -} - - - -#if 0 -#pragma mark - -#pragma mark Register move... -#endif - -void MIPSAssembler::MOVE(int Rd, int Rs) -{ - // encoded as "or rd, rs, zero" - *mPC++ = (spec_op<<OP_SHF) | (or_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (0<<RT_SHF); -} - -void MIPSAssembler::MOVN(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (movn_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::MOVZ(int Rd, int Rs, int Rt) -{ - *mPC++ = (spec_op<<OP_SHF) | (movz_fn<<FUNC_SHF) | - (Rd<<RD_SHF) | (Rs<<RS_SHF) | (Rt<<RT_SHF); -} - -void MIPSAssembler::MFHI(int Rd) -{ - *mPC++ = (spec_op<<OP_SHF) | (mfhi_fn<<FUNC_SHF) | (Rd<<RD_SHF); -} - -void MIPSAssembler::MFLO(int Rd) -{ - *mPC++ = (spec_op<<OP_SHF) | (mflo_fn<<FUNC_SHF) | (Rd<<RD_SHF); -} - -void MIPSAssembler::MTHI(int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (mthi_fn<<FUNC_SHF) | (Rs<<RS_SHF); -} - -void MIPSAssembler::MTLO(int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (mtlo_fn<<FUNC_SHF) | (Rs<<RS_SHF); -} - - - -#if 0 -#pragma mark - -#pragma mark Branch... -#endif - -// temporarily forcing a NOP into branch-delay slot, just to be safe -// todo: remove NOP, optimze use of delay slots -void MIPSAssembler::B(const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - - // encoded as BEQ zero, zero, offset - *mPC++ = (beq_op<<OP_SHF) | (0<<RT_SHF) - | (0<<RS_SHF) | 0; // offset filled in later - - MIPSAssembler::NOP(); -} - -void MIPSAssembler::BEQ(int Rs, int Rt, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (beq_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - -void MIPSAssembler::BNE(int Rs, int Rt, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (bne_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - -void MIPSAssembler::BLEZ(int Rs, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (blez_op<<OP_SHF) | (0<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - -void MIPSAssembler::BLTZ(int Rs, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (regimm_op<<OP_SHF) | (bltz_fn<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - -void MIPSAssembler::BGTZ(int Rs, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (bgtz_op<<OP_SHF) | (0<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - - -void MIPSAssembler::BGEZ(int Rs, const char* label) -{ - mBranchTargets.add(branch_target_t(label, mPC)); - *mPC++ = (regimm_op<<OP_SHF) | (bgez_fn<<RT_SHF) | (Rs<<RS_SHF) | 0; - MIPSAssembler::NOP(); -} - -void MIPSAssembler::JR(int Rs) -{ - *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jr_fn << FUNC_SHF); - MIPSAssembler::NOP(); -} - - -#if 0 -#pragma mark - -#pragma mark Synthesized Branch... -#endif - -// synthetic variants of branches (using slt & friends) -void MIPSAssembler::BEQZ(int Rs, const char* label) -{ - BEQ(Rs, R_zero, label); -} - -void MIPSAssembler::BNEZ(int Rs __unused, const char* label) -{ - BNE(R_at, R_zero, label); -} - -void MIPSAssembler::BGE(int Rs, int Rt, const char* label) -{ - SLT(R_at, Rs, Rt); - BEQ(R_at, R_zero, label); -} - -void MIPSAssembler::BGEU(int Rs, int Rt, const char* label) -{ - SLTU(R_at, Rs, Rt); - BEQ(R_at, R_zero, label); -} - -void MIPSAssembler::BGT(int Rs, int Rt, const char* label) -{ - SLT(R_at, Rt, Rs); // rev - BNE(R_at, R_zero, label); -} - -void MIPSAssembler::BGTU(int Rs, int Rt, const char* label) -{ - SLTU(R_at, Rt, Rs); // rev - BNE(R_at, R_zero, label); -} - -void MIPSAssembler::BLE(int Rs, int Rt, const char* label) -{ - SLT(R_at, Rt, Rs); // rev - BEQ(R_at, R_zero, label); -} - -void MIPSAssembler::BLEU(int Rs, int Rt, const char* label) -{ - SLTU(R_at, Rt, Rs); // rev - BEQ(R_at, R_zero, label); -} - -void MIPSAssembler::BLT(int Rs, int Rt, const char* label) -{ - SLT(R_at, Rs, Rt); - BNE(R_at, R_zero, label); -} - -void MIPSAssembler::BLTU(int Rs, int Rt, const char* label) -{ - SLTU(R_at, Rs, Rt); - BNE(R_at, R_zero, label); -} - - - - -#if 0 -#pragma mark - -#pragma mark Misc... -#endif - -void MIPSAssembler::NOP(void) -{ - // encoded as "sll zero, zero, 0", which is all zero - *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF); -} - -// using this as special opcode for not-yet-implemented ARM instruction -void MIPSAssembler::NOP2(void) -{ - // encoded as "sll zero, zero, 2", still a nop, but a unique code - *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) | (2 << RE_SHF); -} - -// using this as special opcode for purposefully NOT implemented ARM instruction -void MIPSAssembler::UNIMPL(void) -{ - // encoded as "sll zero, zero, 3", still a nop, but a unique code - *mPC++ = (spec_op<<OP_SHF) | (sll_fn<<FUNC_SHF) | (3 << RE_SHF); -} - - -}; // namespace android: diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h deleted file mode 100644 index c1178b6fe..000000000 --- a/libpixelflinger/codeflinger/MIPSAssembler.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/armreg.h b/libpixelflinger/codeflinger/armreg.h deleted file mode 100644 index fde81ba89..000000000 --- a/libpixelflinger/codeflinger/armreg.h +++ /dev/null @@ -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 */ diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp deleted file mode 100644 index 2cbb00f83..000000000 --- a/libpixelflinger/codeflinger/blending.cpp +++ /dev/null @@ -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 - diff --git a/libpixelflinger/codeflinger/disassem.c b/libpixelflinger/codeflinger/disassem.c deleted file mode 100644 index 5cbd63db8..000000000 --- a/libpixelflinger/codeflinger/disassem.c +++ /dev/null @@ -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 */ diff --git a/libpixelflinger/codeflinger/disassem.h b/libpixelflinger/codeflinger/disassem.h deleted file mode 100644 index c7c60b695..000000000 --- a/libpixelflinger/codeflinger/disassem.h +++ /dev/null @@ -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 */ diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp deleted file mode 100644 index 4db0a4948..000000000 --- a/libpixelflinger/codeflinger/load_store.cpp +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/mips64_disassem.c b/libpixelflinger/codeflinger/mips64_disassem.c deleted file mode 100644 index 852829984..000000000 --- a/libpixelflinger/codeflinger/mips64_disassem.c +++ /dev/null @@ -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)); -} diff --git a/libpixelflinger/codeflinger/mips64_disassem.h b/libpixelflinger/codeflinger/mips64_disassem.h deleted file mode 100644 index c94f04f9b..000000000 --- a/libpixelflinger/codeflinger/mips64_disassem.h +++ /dev/null @@ -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 */ diff --git a/libpixelflinger/codeflinger/mips_disassem.c b/libpixelflinger/codeflinger/mips_disassem.c deleted file mode 100644 index 1fe680675..000000000 --- a/libpixelflinger/codeflinger/mips_disassem.c +++ /dev/null @@ -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)); -} - diff --git a/libpixelflinger/codeflinger/mips_disassem.h b/libpixelflinger/codeflinger/mips_disassem.h deleted file mode 100644 index 2d5b7f551..000000000 --- a/libpixelflinger/codeflinger/mips_disassem.h +++ /dev/null @@ -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 */ diff --git a/libpixelflinger/codeflinger/mips_opcode.h b/libpixelflinger/codeflinger/mips_opcode.h deleted file mode 100644 index 45bb19ea1..000000000 --- a/libpixelflinger/codeflinger/mips_opcode.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp deleted file mode 100644 index e6997bd4b..000000000 --- a/libpixelflinger/codeflinger/texturing.cpp +++ /dev/null @@ -1,1261 +0,0 @@ -/* libs/pixelflinger/codeflinger/texturing.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 <log/log.h> - -#include "GGLAssembler.h" - -namespace android { - -// --------------------------------------------------------------------------- - -// iterators are initialized like this: -// (intToFixedCenter(x) * dx)>>16 + x0 -// ((x<<16 + 0x8000) * dx)>>16 + x0 -// ((x<<16)*dx + (0x8000*dx))>>16 + x0 -// ( (x*dx) + dx>>1 ) + x0 -// (x*dx) + (dx>>1 + x0) - -void GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x) -{ - context_t const* c = mBuilderContext.c; - - if (mSmooth) { - // NOTE: we could take this case in the mDithering + !mSmooth case, - // but this would use up to 4 more registers for the color components - // for only a little added quality. - // Currently, this causes the system to run out of registers in - // some case (see issue #719496) - - comment("compute initial iterated color (smooth and/or dither case)"); - - parts.iterated_packed = 0; - parts.packed = 0; - - // 0x1: color component - // 0x2: iterators - const int optReload = mOptLevel >> 1; - if (optReload >= 3) parts.reload = 0; // reload nothing - else if (optReload == 2) parts.reload = 2; // reload iterators - else if (optReload == 1) parts.reload = 1; // reload colors - else if (optReload <= 0) parts.reload = 3; // reload both - - if (!mSmooth) { - // we're not smoothing (just dithering), we never have to - // reload the iterators - parts.reload &= ~2; - } - - Scratch scratches(registerFile()); - const int t0 = (parts.reload & 1) ? scratches.obtain() : 0; - const int t1 = (parts.reload & 2) ? scratches.obtain() : 0; - for (int i=0 ; i<4 ; i++) { - if (!mInfo[i].iterated) - continue; - - // this component exists in the destination and is not replaced - // by a texture unit. - const int c = (parts.reload & 1) ? t0 : obtainReg(); - if (i==0) CONTEXT_LOAD(c, iterators.ydady); - if (i==1) CONTEXT_LOAD(c, iterators.ydrdy); - if (i==2) CONTEXT_LOAD(c, iterators.ydgdy); - if (i==3) CONTEXT_LOAD(c, iterators.ydbdy); - parts.argb[i].reg = c; - - if (mInfo[i].smooth) { - parts.argb_dx[i].reg = (parts.reload & 2) ? t1 : obtainReg(); - const int dvdx = parts.argb_dx[i].reg; - CONTEXT_LOAD(dvdx, generated_vars.argb[i].dx); - MLA(AL, 0, c, x.reg, dvdx, c); - - // adjust the color iterator to make sure it won't overflow - if (!mAA) { - // this is not needed when we're using anti-aliasing - // because we will (have to) clamp the components - // anyway. - int end = scratches.obtain(); - MOV(AL, 0, end, reg_imm(parts.count.reg, LSR, 16)); - MLA(AL, 1, end, dvdx, end, c); - SUB(MI, 0, c, c, end); - BIC(AL, 0, c, c, reg_imm(c, ASR, 31)); - scratches.recycle(end); - } - } - - if (parts.reload & 1) { - CONTEXT_STORE(c, generated_vars.argb[i].c); - } - } - } else { - // We're not smoothed, so we can - // just use a packed version of the color and extract the - // components as needed (or not at all if we don't blend) - - // figure out if we need the iterated color - int load = 0; - for (int i=0 ; i<4 ; i++) { - component_info_t& info = mInfo[i]; - if ((info.inDest || info.needed) && !info.replaced) - load |= 1; - } - - parts.iterated_packed = 1; - parts.packed = (!mTextureMachine.mask && !mBlending - && !mFog && !mDithering); - parts.reload = 0; - if (load || parts.packed) { - if (mBlending || mDithering || mInfo[GGLFormat::ALPHA].needed) { - comment("load initial iterated color (8888 packed)"); - parts.iterated.setTo(obtainReg(), - &(c->formats[GGL_PIXEL_FORMAT_RGBA_8888])); - CONTEXT_LOAD(parts.iterated.reg, packed8888); - } else { - comment("load initial iterated color (dest format packed)"); - - parts.iterated.setTo(obtainReg(), &mCbFormat); - - // pre-mask the iterated color - const int bits = parts.iterated.size(); - const uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1; - uint32_t mask = 0; - if (mMasking) { - for (int i=0 ; i<4 ; i++) { - const int component_mask = 1<<i; - const int h = parts.iterated.format.c[i].h; - const int l = parts.iterated.format.c[i].l; - if (h && (!(mMasking & component_mask))) { - mask |= ((1<<(h-l))-1) << l; - } - } - } - - if (mMasking && ((mask & size)==0)) { - // none of the components are present in the mask - } else { - CONTEXT_LOAD(parts.iterated.reg, packed); - if (mCbFormat.size == 1) { - AND(AL, 0, parts.iterated.reg, - parts.iterated.reg, imm(0xFF)); - } else if (mCbFormat.size == 2) { - MOV(AL, 0, parts.iterated.reg, - reg_imm(parts.iterated.reg, LSR, 16)); - } - } - - // pre-mask the iterated color - if (mMasking) { - build_and_immediate(parts.iterated.reg, parts.iterated.reg, - mask, bits); - } - } - } - } -} - -void GGLAssembler::build_iterated_color( - component_t& fragment, - const fragment_parts_t& parts, - int component, - Scratch& regs) -{ - fragment.setTo( regs.obtain(), 0, 32, CORRUPTIBLE); - - if (!mInfo[component].iterated) - return; - - if (parts.iterated_packed) { - // iterated colors are packed, extract the one we need - extract(fragment, parts.iterated, component); - } else { - fragment.h = GGL_COLOR_BITS; - fragment.l = GGL_COLOR_BITS - 8; - fragment.flags |= CLEAR_LO; - // iterated colors are held in their own register, - // (smooth and/or dithering case) - if (parts.reload==3) { - // this implies mSmooth - Scratch scratches(registerFile()); - int dx = scratches.obtain(); - CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c); - CONTEXT_LOAD(dx, generated_vars.argb[component].dx); - ADD(AL, 0, dx, fragment.reg, dx); - CONTEXT_STORE(dx, generated_vars.argb[component].c); - } else if (parts.reload & 1) { - CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c); - } else { - // we don't reload, so simply rename the register and mark as - // non CORRUPTIBLE so that the texture env or blending code - // won't modify this (renamed) register - regs.recycle(fragment.reg); - fragment.reg = parts.argb[component].reg; - fragment.flags &= ~CORRUPTIBLE; - } - if (mInfo[component].smooth && mAA) { - // when using smooth shading AND anti-aliasing, we need to clamp - // the iterators because there is always an extra pixel on the - // edges, which most of the time will cause an overflow - // (since technically its outside of the domain). - BIC(AL, 0, fragment.reg, fragment.reg, - reg_imm(fragment.reg, ASR, 31)); - component_sat(fragment); - } - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::decodeLogicOpNeeds(const needs_t& needs) -{ - // gather some informations about the components we need to process... - const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; - switch(opcode) { - case GGL_COPY: - mLogicOp = 0; - break; - case GGL_CLEAR: - case GGL_SET: - mLogicOp = LOGIC_OP; - break; - case GGL_AND: - case GGL_AND_REVERSE: - case GGL_AND_INVERTED: - case GGL_XOR: - case GGL_OR: - case GGL_NOR: - case GGL_EQUIV: - case GGL_OR_REVERSE: - case GGL_OR_INVERTED: - case GGL_NAND: - mLogicOp = LOGIC_OP|LOGIC_OP_SRC|LOGIC_OP_DST; - break; - case GGL_NOOP: - case GGL_INVERT: - mLogicOp = LOGIC_OP|LOGIC_OP_DST; - break; - case GGL_COPY_INVERTED: - mLogicOp = LOGIC_OP|LOGIC_OP_SRC; - break; - }; -} - -void GGLAssembler::decodeTMUNeeds(const needs_t& needs, context_t const* c) -{ - uint8_t replaced=0; - mTextureMachine.mask = 0; - mTextureMachine.activeUnits = 0; - for (int i=GGL_TEXTURE_UNIT_COUNT-1 ; i>=0 ; i--) { - texture_unit_t& tmu = mTextureMachine.tmu[i]; - if (replaced == 0xF) { - // all components are replaced, skip this TMU. - tmu.format_idx = 0; - tmu.mask = 0; - tmu.replaced = replaced; - continue; - } - tmu.format_idx = GGL_READ_NEEDS(T_FORMAT, needs.t[i]); - tmu.format = c->formats[tmu.format_idx]; - tmu.bits = tmu.format.size*8; - tmu.swrap = GGL_READ_NEEDS(T_S_WRAP, needs.t[i]); - tmu.twrap = GGL_READ_NEEDS(T_T_WRAP, needs.t[i]); - tmu.env = ggl_needs_to_env(GGL_READ_NEEDS(T_ENV, needs.t[i])); - tmu.pot = GGL_READ_NEEDS(T_POT, needs.t[i]); - tmu.linear = GGL_READ_NEEDS(T_LINEAR, needs.t[i]) - && tmu.format.size!=3; // XXX: only 8, 16 and 32 modes for now - - // 5551 linear filtering is not supported - if (tmu.format_idx == GGL_PIXEL_FORMAT_RGBA_5551) - tmu.linear = 0; - - tmu.mask = 0; - tmu.replaced = replaced; - - if (tmu.format_idx) { - mTextureMachine.activeUnits++; - if (tmu.format.c[0].h) tmu.mask |= 0x1; - if (tmu.format.c[1].h) tmu.mask |= 0x2; - if (tmu.format.c[2].h) tmu.mask |= 0x4; - if (tmu.format.c[3].h) tmu.mask |= 0x8; - if (tmu.env == GGL_REPLACE) { - replaced |= tmu.mask; - } else if (tmu.env == GGL_DECAL) { - if (!tmu.format.c[GGLFormat::ALPHA].h) { - // if we don't have alpha, decal does nothing - tmu.mask = 0; - } else { - // decal always ignores At - tmu.mask &= ~(1<<GGLFormat::ALPHA); - } - } - } - mTextureMachine.mask |= tmu.mask; - //printf("%d: mask=%08lx, replaced=%08lx\n", - // i, int(tmu.mask), int(tmu.replaced)); - } - mTextureMachine.replaced = replaced; - mTextureMachine.directTexture = 0; - //printf("replaced=%08lx\n", mTextureMachine.replaced); -} - - -void GGLAssembler::init_textures( - tex_coord_t* coords, - const reg_t& x, const reg_t& y) -{ - const needs_t& needs = mBuilderContext.needs; - int Rx = x.reg; - int Ry = y.reg; - - if (mTextureMachine.mask) { - comment("compute texture coordinates"); - } - - // init texture coordinates for each tmu - const int cb_format_idx = GGL_READ_NEEDS(CB_FORMAT, needs.n); - const bool multiTexture = mTextureMachine.activeUnits > 1; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { - const texture_unit_t& tmu = mTextureMachine.tmu[i]; - if (tmu.format_idx == 0) - continue; - if ((tmu.swrap == GGL_NEEDS_WRAP_11) && - (tmu.twrap == GGL_NEEDS_WRAP_11)) - { - // 1:1 texture - pointer_t& txPtr = coords[i].ptr; - txPtr.setTo(obtainReg(), tmu.bits); - CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydsdy); - ADD(AL, 0, Rx, Rx, reg_imm(txPtr.reg, ASR, 16)); // x += (s>>16) - CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydtdy); - ADD(AL, 0, Ry, Ry, reg_imm(txPtr.reg, ASR, 16)); // y += (t>>16) - // merge base & offset - CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].stride); - SMLABB(AL, Rx, Ry, txPtr.reg, Rx); // x+y*stride - CONTEXT_ADDR_LOAD(txPtr.reg, generated_vars.texture[i].data); - base_offset(txPtr, txPtr, Rx); - } else { - Scratch scratches(registerFile()); - reg_t& s = coords[i].s; - reg_t& t = coords[i].t; - // s = (x * dsdx)>>16 + ydsdy - // s = (x * dsdx)>>16 + (y*dsdy)>>16 + s0 - // t = (x * dtdx)>>16 + ydtdy - // t = (x * dtdx)>>16 + (y*dtdy)>>16 + t0 - s.setTo(obtainReg()); - t.setTo(obtainReg()); - const int need_w = GGL_READ_NEEDS(W, needs.n); - if (need_w) { - CONTEXT_LOAD(s.reg, state.texture[i].iterators.ydsdy); - CONTEXT_LOAD(t.reg, state.texture[i].iterators.ydtdy); - } else { - int ydsdy = scratches.obtain(); - int ydtdy = scratches.obtain(); - CONTEXT_LOAD(s.reg, generated_vars.texture[i].dsdx); - CONTEXT_LOAD(ydsdy, state.texture[i].iterators.ydsdy); - CONTEXT_LOAD(t.reg, generated_vars.texture[i].dtdx); - CONTEXT_LOAD(ydtdy, state.texture[i].iterators.ydtdy); - MLA(AL, 0, s.reg, Rx, s.reg, ydsdy); - MLA(AL, 0, t.reg, Rx, t.reg, ydtdy); - } - - if ((mOptLevel&1)==0) { - CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]); - CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]); - recycleReg(s.reg); - recycleReg(t.reg); - } - } - - // direct texture? - if (!multiTexture && !mBlending && !mDithering && !mFog && - cb_format_idx == tmu.format_idx && !tmu.linear && - mTextureMachine.replaced == tmu.mask) - { - mTextureMachine.directTexture = i + 1; - } - } -} - -void GGLAssembler::build_textures( fragment_parts_t& parts, - Scratch& regs) -{ - // We don't have a way to spill registers automatically - // spill depth and AA regs, when we know we may have to. - // build the spill list... - uint32_t spill_list = 0; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { - const texture_unit_t& tmu = mTextureMachine.tmu[i]; - if (tmu.format_idx == 0) - continue; - if (tmu.linear) { - // we may run out of register if we have linear filtering - // at 1 or 4 bytes / pixel on any texture unit. - if (tmu.format.size == 1) { - // if depth and AA enabled, we'll run out of 1 register - if (parts.z.reg > 0 && parts.covPtr.reg > 0) - spill_list |= 1<<parts.covPtr.reg; - } - if (tmu.format.size == 4) { - // if depth or AA enabled, we'll run out of 1 or 2 registers - if (parts.z.reg > 0) - spill_list |= 1<<parts.z.reg; - if (parts.covPtr.reg > 0) - spill_list |= 1<<parts.covPtr.reg; - } - } - } - - Spill spill(registerFile(), *this, spill_list); - - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { - const texture_unit_t& tmu = mTextureMachine.tmu[i]; - if (tmu.format_idx == 0) - continue; - - pointer_t& txPtr = parts.coords[i].ptr; - pixel_t& texel = parts.texel[i]; - - // repeat... - if ((tmu.swrap == GGL_NEEDS_WRAP_11) && - (tmu.twrap == GGL_NEEDS_WRAP_11)) - { // 1:1 textures - comment("fetch texel"); - texel.setTo(regs.obtain(), &tmu.format); - load(txPtr, texel, WRITE_BACK); - } else { - Scratch scratches(registerFile()); - reg_t& s = parts.coords[i].s; - reg_t& t = parts.coords[i].t; - if ((mOptLevel&1)==0) { - comment("reload s/t (multitexture or linear filtering)"); - s.reg = scratches.obtain(); - t.reg = scratches.obtain(); - CONTEXT_LOAD(s.reg, generated_vars.texture[i].spill[0]); - CONTEXT_LOAD(t.reg, generated_vars.texture[i].spill[1]); - } - - if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS) - return; - - comment("compute repeat/clamp"); - int u = scratches.obtain(); - int v = scratches.obtain(); - int width = scratches.obtain(); - int height = scratches.obtain(); - int U = 0; - int V = 0; - - if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS) - return; - - CONTEXT_LOAD(width, generated_vars.texture[i].width); - CONTEXT_LOAD(height, generated_vars.texture[i].height); - - int FRAC_BITS = 0; - if (tmu.linear) { - // linear interpolation - if (tmu.format.size == 1) { - // for 8-bits textures, we can afford - // 7 bits of fractional precision at no - // additional cost (we can't do 8 bits - // because filter8 uses signed 16 bits muls) - FRAC_BITS = 7; - } else if (tmu.format.size == 2) { - // filter16() is internally limited to 4 bits, so: - // FRAC_BITS=2 generates less instructions, - // FRAC_BITS=3,4,5 creates unpleasant artifacts, - // FRAC_BITS=6+ looks good - FRAC_BITS = 6; - } else if (tmu.format.size == 4) { - // filter32() is internally limited to 8 bits, so: - // FRAC_BITS=4 looks good - // FRAC_BITS=5+ looks better, but generates 3 extra ipp - FRAC_BITS = 6; - } else { - // for all other cases we use 4 bits. - FRAC_BITS = 4; - } - } - wrapping(u, s.reg, width, tmu.swrap, FRAC_BITS); - wrapping(v, t.reg, height, tmu.twrap, FRAC_BITS); - - if (tmu.linear) { - comment("compute linear filtering offsets"); - // pixel size scale - const int shift = 31 - gglClz(tmu.format.size); - U = scratches.obtain(); - V = scratches.obtain(); - - if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS) - return; - - // sample the texel center - SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1))); - SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1))); - - // get the fractionnal part of U,V - AND(AL, 0, U, u, imm((1<<FRAC_BITS)-1)); - AND(AL, 0, V, v, imm((1<<FRAC_BITS)-1)); - - // compute width-1 and height-1 - SUB(AL, 0, width, width, imm(1)); - SUB(AL, 0, height, height, imm(1)); - - // get the integer part of U,V and clamp/wrap - // and compute offset to the next texel - if (tmu.swrap == GGL_NEEDS_WRAP_REPEAT) { - // u has already been REPEATed - MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS)); - MOV(MI, 0, u, width); - CMP(AL, u, width); - MOV(LT, 0, width, imm(1 << shift)); - if (shift) - MOV(GE, 0, width, reg_imm(width, LSL, shift)); - RSB(GE, 0, width, width, imm(0)); - } else { - // u has not been CLAMPed yet - // algorithm: - // if ((u>>4) >= width) - // u = width<<4 - // width = 0 - // else - // width = 1<<shift - // u = u>>4; // get integer part - // if (u<0) - // u = 0 - // width = 0 - // generated_vars.rt = width - - CMP(AL, width, reg_imm(u, ASR, FRAC_BITS)); - MOV(LE, 0, u, reg_imm(width, LSL, FRAC_BITS)); - MOV(LE, 0, width, imm(0)); - MOV(GT, 0, width, imm(1 << shift)); - MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS)); - MOV(MI, 0, u, imm(0)); - MOV(MI, 0, width, imm(0)); - } - CONTEXT_STORE(width, generated_vars.rt); - - const int stride = width; - CONTEXT_LOAD(stride, generated_vars.texture[i].stride); - if (tmu.twrap == GGL_NEEDS_WRAP_REPEAT) { - // v has already been REPEATed - MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS)); - MOV(MI, 0, v, height); - CMP(AL, v, height); - MOV(LT, 0, height, imm(1 << shift)); - if (shift) - MOV(GE, 0, height, reg_imm(height, LSL, shift)); - RSB(GE, 0, height, height, imm(0)); - MUL(AL, 0, height, stride, height); - } else { - // v has not been CLAMPed yet - CMP(AL, height, reg_imm(v, ASR, FRAC_BITS)); - MOV(LE, 0, v, reg_imm(height, LSL, FRAC_BITS)); - MOV(LE, 0, height, imm(0)); - if (shift) { - MOV(GT, 0, height, reg_imm(stride, LSL, shift)); - } else { - MOV(GT, 0, height, stride); - } - MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS)); - MOV(MI, 0, v, imm(0)); - MOV(MI, 0, height, imm(0)); - } - CONTEXT_STORE(height, generated_vars.lb); - } - - scratches.recycle(width); - scratches.recycle(height); - - // iterate texture coordinates... - comment("iterate s,t"); - int dsdx = scratches.obtain(); - int dtdx = scratches.obtain(); - - if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS) - return; - - CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx); - CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx); - ADD(AL, 0, s.reg, s.reg, dsdx); - ADD(AL, 0, t.reg, t.reg, dtdx); - if ((mOptLevel&1)==0) { - CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]); - CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]); - scratches.recycle(s.reg); - scratches.recycle(t.reg); - } - scratches.recycle(dsdx); - scratches.recycle(dtdx); - - // merge base & offset... - comment("merge base & offset"); - texel.setTo(regs.obtain(), &tmu.format); - txPtr.setTo(texel.reg, tmu.bits); - int stride = scratches.obtain(); - - if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS) - return; - - CONTEXT_LOAD(stride, generated_vars.texture[i].stride); - CONTEXT_ADDR_LOAD(txPtr.reg, generated_vars.texture[i].data); - SMLABB(AL, u, v, stride, u); // u+v*stride - base_offset(txPtr, txPtr, u); - - // load texel - if (!tmu.linear) { - comment("fetch texel"); - load(txPtr, texel, 0); - } else { - // recycle registers we don't need anymore - scratches.recycle(u); - scratches.recycle(v); - scratches.recycle(stride); - - comment("fetch texel, bilinear"); - switch (tmu.format.size) { - case 1: filter8(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break; - case 2: filter16(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break; - case 3: filter24(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break; - case 4: filter32(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break; - } - } - } - } -} - -void GGLAssembler::build_iterate_texture_coordinates( - const fragment_parts_t& parts) -{ - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { - const texture_unit_t& tmu = mTextureMachine.tmu[i]; - if (tmu.format_idx == 0) - continue; - - if ((tmu.swrap == GGL_NEEDS_WRAP_11) && - (tmu.twrap == GGL_NEEDS_WRAP_11)) - { // 1:1 textures - const pointer_t& txPtr = parts.coords[i].ptr; - ADD(AL, 0, txPtr.reg, txPtr.reg, imm(txPtr.size>>3)); - } else { - Scratch scratches(registerFile()); - int s = parts.coords[i].s.reg; - int t = parts.coords[i].t.reg; - if ((mOptLevel&1)==0) { - s = scratches.obtain(); - t = scratches.obtain(); - CONTEXT_LOAD(s, generated_vars.texture[i].spill[0]); - CONTEXT_LOAD(t, generated_vars.texture[i].spill[1]); - } - int dsdx = scratches.obtain(); - int dtdx = scratches.obtain(); - CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx); - CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx); - ADD(AL, 0, s, s, dsdx); - ADD(AL, 0, t, t, dtdx); - if ((mOptLevel&1)==0) { - CONTEXT_STORE(s, generated_vars.texture[i].spill[0]); - CONTEXT_STORE(t, generated_vars.texture[i].spill[1]); - } - } - } -} - -void GGLAssembler::filter8( - const fragment_parts_t& /*parts*/, - pixel_t& texel, const texture_unit_t& tmu, - int U, int V, pointer_t& txPtr, - int FRAC_BITS) -{ - if (tmu.format.components != GGL_ALPHA && - tmu.format.components != GGL_LUMINANCE) - { - // this is a packed format, and we don't support - // linear filtering (it's probably RGB 332) - // Should not happen with OpenGL|ES - LDRB(AL, texel.reg, txPtr.reg); - return; - } - - // ------------------------ - // about ~22 cycles / pixel - Scratch scratches(registerFile()); - - int pixel= scratches.obtain(); - int d = scratches.obtain(); - int u = scratches.obtain(); - int k = scratches.obtain(); - int rt = scratches.obtain(); - int lb = scratches.obtain(); - - // RB -> U * V - - CONTEXT_LOAD(rt, generated_vars.rt); - CONTEXT_LOAD(lb, generated_vars.lb); - - int offset = pixel; - ADD(AL, 0, offset, lb, rt); - LDRB(AL, pixel, txPtr.reg, reg_scale_pre(offset)); - SMULBB(AL, u, U, V); - SMULBB(AL, d, pixel, u); - RSB(AL, 0, k, u, imm(1<<(FRAC_BITS*2))); - - // LB -> (1-U) * V - RSB(AL, 0, U, U, imm(1<<FRAC_BITS)); - LDRB(AL, pixel, txPtr.reg, reg_scale_pre(lb)); - SMULBB(AL, u, U, V); - SMLABB(AL, d, pixel, u, d); - SUB(AL, 0, k, k, u); - - // LT -> (1-U)*(1-V) - RSB(AL, 0, V, V, imm(1<<FRAC_BITS)); - LDRB(AL, pixel, txPtr.reg); - SMULBB(AL, u, U, V); - SMLABB(AL, d, pixel, u, d); - - // RT -> U*(1-V) - LDRB(AL, pixel, txPtr.reg, reg_scale_pre(rt)); - SUB(AL, 0, u, k, u); - SMLABB(AL, texel.reg, pixel, u, d); - - for (int i=0 ; i<4 ; i++) { - if (!texel.format.c[i].h) continue; - texel.format.c[i].h = FRAC_BITS*2+8; - texel.format.c[i].l = FRAC_BITS*2; // keeping 8 bits in enough - } - texel.format.size = 4; - texel.format.bitsPerPixel = 32; - texel.flags |= CLEAR_LO; -} - -void GGLAssembler::filter16( - const fragment_parts_t& /*parts*/, - pixel_t& texel, const texture_unit_t& tmu, - int U, int V, pointer_t& txPtr, - int FRAC_BITS) -{ - // compute the mask - // XXX: it would be nice if the mask below could be computed - // automatically. - uint32_t mask = 0; - int shift = 0; - int prec = 0; - switch (tmu.format_idx) { - case GGL_PIXEL_FORMAT_RGB_565: - // source: 00000ggg.ggg00000 | rrrrr000.000bbbbb - // result: gggggggg.gggrrrrr | rrrrr0bb.bbbbbbbb - mask = 0x07E0F81F; - shift = 16; - prec = 5; - break; - case GGL_PIXEL_FORMAT_RGBA_4444: - // 0000,1111,0000,1111 | 0000,1111,0000,1111 - mask = 0x0F0F0F0F; - shift = 12; - prec = 4; - break; - case GGL_PIXEL_FORMAT_LA_88: - // 0000,0000,1111,1111 | 0000,0000,1111,1111 - // AALL -> 00AA | 00LL - mask = 0x00FF00FF; - shift = 8; - prec = 8; - break; - default: - // unsupported format, do something sensical... - ALOGE("Unsupported 16-bits texture format (%d)", tmu.format_idx); - LDRH(AL, texel.reg, txPtr.reg); - return; - } - - const int adjust = FRAC_BITS*2 - prec; - const int round = 0; - - // update the texel format - texel.format.size = 4; - texel.format.bitsPerPixel = 32; - texel.flags |= CLEAR_HI|CLEAR_LO; - for (int i=0 ; i<4 ; i++) { - if (!texel.format.c[i].h) continue; - const uint32_t offset = (mask & tmu.format.mask(i)) ? 0 : shift; - texel.format.c[i].h = tmu.format.c[i].h + offset + prec; - texel.format.c[i].l = texel.format.c[i].h - (tmu.format.bits(i) + prec); - } - - // ------------------------ - // about ~40 cycles / pixel - Scratch scratches(registerFile()); - - int pixel= scratches.obtain(); - int d = scratches.obtain(); - int u = scratches.obtain(); - int k = scratches.obtain(); - - // RB -> U * V - int offset = pixel; - CONTEXT_LOAD(offset, generated_vars.rt); - CONTEXT_LOAD(u, generated_vars.lb); - ADD(AL, 0, offset, offset, u); - - LDRH(AL, pixel, txPtr.reg, reg_pre(offset)); - SMULBB(AL, u, U, V); - ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift)); - build_and_immediate(pixel, pixel, mask, 32); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MUL(AL, 0, d, pixel, u); - RSB(AL, 0, k, u, imm(1<<prec)); - - // LB -> (1-U) * V - CONTEXT_LOAD(offset, generated_vars.lb); - RSB(AL, 0, U, U, imm(1<<FRAC_BITS)); - LDRH(AL, pixel, txPtr.reg, reg_pre(offset)); - SMULBB(AL, u, U, V); - ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift)); - build_and_immediate(pixel, pixel, mask, 32); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MLA(AL, 0, d, pixel, u, d); - SUB(AL, 0, k, k, u); - - // LT -> (1-U)*(1-V) - RSB(AL, 0, V, V, imm(1<<FRAC_BITS)); - LDRH(AL, pixel, txPtr.reg); - SMULBB(AL, u, U, V); - ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift)); - build_and_immediate(pixel, pixel, mask, 32); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MLA(AL, 0, d, pixel, u, d); - - // RT -> U*(1-V) - CONTEXT_LOAD(offset, generated_vars.rt); - LDRH(AL, pixel, txPtr.reg, reg_pre(offset)); - SUB(AL, 0, u, k, u); - ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift)); - build_and_immediate(pixel, pixel, mask, 32); - MLA(AL, 0, texel.reg, pixel, u, d); -} - -void GGLAssembler::filter24( - const fragment_parts_t& /*parts*/, - pixel_t& texel, const texture_unit_t& /*tmu*/, - int /*U*/, int /*V*/, pointer_t& txPtr, - int /*FRAC_BITS*/) -{ - // not supported yet (currently disabled) - load(txPtr, texel, 0); -} - -void GGLAssembler::filter32( - const fragment_parts_t& /*parts*/, - pixel_t& texel, const texture_unit_t& /*tmu*/, - int U, int V, pointer_t& txPtr, - int FRAC_BITS) -{ - const int adjust = FRAC_BITS*2 - 8; - const int round = 0; - - // ------------------------ - // about ~38 cycles / pixel - Scratch scratches(registerFile()); - - int pixel= scratches.obtain(); - int dh = scratches.obtain(); - int u = scratches.obtain(); - int k = scratches.obtain(); - - int temp = scratches.obtain(); - int dl = scratches.obtain(); - int mask = scratches.obtain(); - - MOV(AL, 0, mask, imm(0xFF)); - ORR(AL, 0, mask, mask, imm(0xFF0000)); - - // RB -> U * V - int offset = pixel; - CONTEXT_LOAD(offset, generated_vars.rt); - CONTEXT_LOAD(u, generated_vars.lb); - ADD(AL, 0, offset, offset, u); - - LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset)); - SMULBB(AL, u, U, V); - AND(AL, 0, temp, mask, pixel); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MUL(AL, 0, dh, temp, u); - AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8)); - MUL(AL, 0, dl, temp, u); - RSB(AL, 0, k, u, imm(0x100)); - - // LB -> (1-U) * V - CONTEXT_LOAD(offset, generated_vars.lb); - RSB(AL, 0, U, U, imm(1<<FRAC_BITS)); - LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset)); - SMULBB(AL, u, U, V); - AND(AL, 0, temp, mask, pixel); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MLA(AL, 0, dh, temp, u, dh); - AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8)); - MLA(AL, 0, dl, temp, u, dl); - SUB(AL, 0, k, k, u); - - // LT -> (1-U)*(1-V) - RSB(AL, 0, V, V, imm(1<<FRAC_BITS)); - LDR(AL, pixel, txPtr.reg); - SMULBB(AL, u, U, V); - AND(AL, 0, temp, mask, pixel); - if (adjust) { - if (round) - ADD(AL, 0, u, u, imm(1<<(adjust-1))); - MOV(AL, 0, u, reg_imm(u, LSR, adjust)); - } - MLA(AL, 0, dh, temp, u, dh); - AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8)); - MLA(AL, 0, dl, temp, u, dl); - - // RT -> U*(1-V) - CONTEXT_LOAD(offset, generated_vars.rt); - LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset)); - SUB(AL, 0, u, k, u); - AND(AL, 0, temp, mask, pixel); - MLA(AL, 0, dh, temp, u, dh); - AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8)); - MLA(AL, 0, dl, temp, u, dl); - - AND(AL, 0, dh, mask, reg_imm(dh, LSR, 8)); - AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8)); - ORR(AL, 0, texel.reg, dh, dl); -} - -void GGLAssembler::build_texture_environment( - component_t& fragment, - const fragment_parts_t& parts, - int component, - Scratch& regs) -{ - const uint32_t component_mask = 1<<component; - const bool multiTexture = mTextureMachine.activeUnits > 1; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { - texture_unit_t& tmu = mTextureMachine.tmu[i]; - - if (tmu.mask & component_mask) { - // replace or modulate with this texture - if ((tmu.replaced & component_mask) == 0) { - // not replaced by a later tmu... - - Scratch scratches(registerFile()); - pixel_t texel(parts.texel[i]); - - if (multiTexture && - tmu.swrap == GGL_NEEDS_WRAP_11 && - tmu.twrap == GGL_NEEDS_WRAP_11) - { - texel.reg = scratches.obtain(); - texel.flags |= CORRUPTIBLE; - comment("fetch texel (multitexture 1:1)"); - load(parts.coords[i].ptr, texel, WRITE_BACK); - } - - component_t incoming(fragment); - modify(fragment, regs); - - switch (tmu.env) { - case GGL_REPLACE: - extract(fragment, texel, component); - break; - case GGL_MODULATE: - modulate(fragment, incoming, texel, component); - break; - case GGL_DECAL: - decal(fragment, incoming, texel, component); - break; - case GGL_BLEND: - blend(fragment, incoming, texel, component, i); - break; - case GGL_ADD: - add(fragment, incoming, texel, component); - break; - } - } - } - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::wrapping( - int d, - int coord, int size, - int tx_wrap, int tx_linear) -{ - // notes: - // if tx_linear is set, we need 4 extra bits of precision on the result - // SMULL/UMULL is 3 cycles - Scratch scratches(registerFile()); - int c = coord; - if (tx_wrap == GGL_NEEDS_WRAP_REPEAT) { - // UMULL takes 4 cycles (interlocked), and we can get away with - // 2 cycles using SMULWB, but we're loosing 16 bits of precision - // out of 32 (this is not a problem because the iterator keeps - // its full precision) - // UMULL(AL, 0, size, d, c, size); - // note: we can't use SMULTB because it's signed. - MOV(AL, 0, d, reg_imm(c, LSR, 16-tx_linear)); - SMULWB(AL, d, d, size); - } else if (tx_wrap == GGL_NEEDS_WRAP_CLAMP_TO_EDGE) { - if (tx_linear) { - // 1 cycle - MOV(AL, 0, d, reg_imm(coord, ASR, 16-tx_linear)); - } else { - // 4 cycles (common case) - MOV(AL, 0, d, reg_imm(coord, ASR, 16)); - BIC(AL, 0, d, d, reg_imm(d, ASR, 31)); - CMP(AL, d, size); - SUB(GE, 0, d, size, imm(1)); - } - } -} - -// --------------------------------------------------------------------------- - -void GGLAssembler::modulate( - component_t& dest, - const component_t& incoming, - const pixel_t& incomingTexel, int component) -{ - Scratch locals(registerFile()); - integer_t texel(locals.obtain(), 32, CORRUPTIBLE); - extract(texel, incomingTexel, component); - - const int Nt = texel.size(); - // Nt should always be less than 10 bits because it comes - // from the TMU. - - int Ni = incoming.size(); - // Ni could be big because it comes from previous MODULATEs - - if (Nt == 1) { - // texel acts as a bit-mask - // dest = incoming & ((texel << incoming.h)-texel) - RSB(AL, 0, dest.reg, texel.reg, reg_imm(texel.reg, LSL, incoming.h)); - AND(AL, 0, dest.reg, dest.reg, incoming.reg); - dest.l = incoming.l; - dest.h = incoming.h; - dest.flags |= (incoming.flags & CLEAR_LO); - } else if (Ni == 1) { - MOV(AL, 0, dest.reg, reg_imm(incoming.reg, LSL, 31-incoming.h)); - AND(AL, 0, dest.reg, texel.reg, reg_imm(dest.reg, ASR, 31)); - dest.l = 0; - dest.h = Nt; - } else { - int inReg = incoming.reg; - int shift = incoming.l; - if ((Nt + Ni) > 32) { - // we will overflow, reduce the precision of Ni to 8 bits - // (Note Nt cannot be more than 10 bits which happens with - // 565 textures and GGL_LINEAR) - shift += Ni-8; - Ni = 8; - } - - // modulate by the component with the lowest precision - if (Nt >= Ni) { - if (shift) { - // XXX: we should be able to avoid this shift - // when shift==16 && Nt<16 && Ni<16, in which - // we could use SMULBT below. - MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift)); - inReg = dest.reg; - shift = 0; - } - // operation: (Cf*Ct)/((1<<Ni)-1) - // approximated with: Cf*(Ct + Ct>>(Ni-1))>>Ni - // this operation doesn't change texel's size - ADD(AL, 0, dest.reg, inReg, reg_imm(inReg, LSR, Ni-1)); - if (Nt<16 && Ni<16) SMULBB(AL, dest.reg, texel.reg, dest.reg); - else MUL(AL, 0, dest.reg, texel.reg, dest.reg); - dest.l = Ni; - dest.h = Nt + Ni; - } else { - if (shift && (shift != 16)) { - // if shift==16, we can use 16-bits mul instructions later - MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift)); - inReg = dest.reg; - shift = 0; - } - // operation: (Cf*Ct)/((1<<Nt)-1) - // approximated with: Ct*(Cf + Cf>>(Nt-1))>>Nt - // this operation doesn't change incoming's size - Scratch scratches(registerFile()); - int t = (texel.flags & CORRUPTIBLE) ? texel.reg : dest.reg; - if (t == inReg) - t = scratches.obtain(); - ADD(AL, 0, t, texel.reg, reg_imm(texel.reg, LSR, Nt-1)); - if (Nt<16 && Ni<16) { - if (shift==16) SMULBT(AL, dest.reg, t, inReg); - else SMULBB(AL, dest.reg, t, inReg); - } else MUL(AL, 0, dest.reg, t, inReg); - dest.l = Nt; - dest.h = Nt + Ni; - } - - // low bits are not valid - dest.flags |= CLEAR_LO; - - // no need to keep more than 8 bits/component - if (dest.size() > 8) - dest.l = dest.h-8; - } -} - -void GGLAssembler::decal( - component_t& dest, - const component_t& incoming, - const pixel_t& incomingTexel, int component) -{ - // RGBA: - // Cv = Cf*(1 - At) + Ct*At = Cf + (Ct - Cf)*At - // Av = Af - Scratch locals(registerFile()); - integer_t texel(locals.obtain(), 32, CORRUPTIBLE); - integer_t factor(locals.obtain(), 32, CORRUPTIBLE); - extract(texel, incomingTexel, component); - extract(factor, incomingTexel, GGLFormat::ALPHA); - - // no need to keep more than 8-bits for decal - int Ni = incoming.size(); - int shift = incoming.l; - if (Ni > 8) { - shift += Ni-8; - Ni = 8; - } - integer_t incomingNorm(incoming.reg, Ni, incoming.flags); - if (shift) { - MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift)); - incomingNorm.reg = dest.reg; - incomingNorm.flags |= CORRUPTIBLE; - } - ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1)); - build_blendOneMinusFF(dest, factor, incomingNorm, texel); -} - -void GGLAssembler::blend( - component_t& dest, - const component_t& incoming, - const pixel_t& incomingTexel, int component, int tmu) -{ - // RGBA: - // Cv = (1 - Ct)*Cf + Ct*Cc = Cf + (Cc - Cf)*Ct - // Av = At*Af - - if (component == GGLFormat::ALPHA) { - modulate(dest, incoming, incomingTexel, component); - return; - } - - Scratch locals(registerFile()); - integer_t color(locals.obtain(), 8, CORRUPTIBLE); - integer_t factor(locals.obtain(), 32, CORRUPTIBLE); - LDRB(AL, color.reg, mBuilderContext.Rctx, - immed12_pre(GGL_OFFSETOF(state.texture[tmu].env_color[component]))); - extract(factor, incomingTexel, component); - - // no need to keep more than 8-bits for blend - int Ni = incoming.size(); - int shift = incoming.l; - if (Ni > 8) { - shift += Ni-8; - Ni = 8; - } - integer_t incomingNorm(incoming.reg, Ni, incoming.flags); - if (shift) { - MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift)); - incomingNorm.reg = dest.reg; - incomingNorm.flags |= CORRUPTIBLE; - } - ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1)); - build_blendOneMinusFF(dest, factor, incomingNorm, color); -} - -void GGLAssembler::add( - component_t& dest, - const component_t& incoming, - const pixel_t& incomingTexel, int component) -{ - // RGBA: - // Cv = Cf + Ct; - Scratch locals(registerFile()); - - component_t incomingTemp(incoming); - - // use "dest" as a temporary for extracting the texel, unless "dest" - // overlaps "incoming". - integer_t texel(dest.reg, 32, CORRUPTIBLE); - if (dest.reg == incomingTemp.reg) - texel.reg = locals.obtain(); - extract(texel, incomingTexel, component); - - if (texel.s < incomingTemp.size()) { - expand(texel, texel, incomingTemp.size()); - } else if (texel.s > incomingTemp.size()) { - if (incomingTemp.flags & CORRUPTIBLE) { - expand(incomingTemp, incomingTemp, texel.s); - } else { - incomingTemp.reg = locals.obtain(); - expand(incomingTemp, incoming, texel.s); - } - } - - if (incomingTemp.l) { - ADD(AL, 0, dest.reg, texel.reg, - reg_imm(incomingTemp.reg, LSR, incomingTemp.l)); - } else { - ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg); - } - dest.l = 0; - dest.h = texel.size(); - component_sat(dest); -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/libpixelflinger/codeflinger/tinyutils/smartpointer.h b/libpixelflinger/codeflinger/tinyutils/smartpointer.h deleted file mode 100644 index 23a5f7e54..000000000 --- a/libpixelflinger/codeflinger/tinyutils/smartpointer.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/col32cb16blend.S b/libpixelflinger/col32cb16blend.S deleted file mode 100644 index 39f94e164..000000000 --- a/libpixelflinger/col32cb16blend.S +++ /dev/null @@ -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 - - - diff --git a/libpixelflinger/col32cb16blend_neon.S b/libpixelflinger/col32cb16blend_neon.S deleted file mode 100644 index 7ad34b051..000000000 --- a/libpixelflinger/col32cb16blend_neon.S +++ /dev/null @@ -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 - - - diff --git a/libpixelflinger/fixed.cpp b/libpixelflinger/fixed.cpp deleted file mode 100644 index de6b4794f..000000000 --- a/libpixelflinger/fixed.cpp +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/format.cpp b/libpixelflinger/format.cpp deleted file mode 100644 index 6546e8c06..000000000 --- a/libpixelflinger/format.cpp +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/include/pixelflinger/format.h b/libpixelflinger/include/pixelflinger/format.h deleted file mode 100644 index d429477a6..000000000 --- a/libpixelflinger/include/pixelflinger/format.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/include/pixelflinger/pixelflinger.h b/libpixelflinger/include/pixelflinger/pixelflinger.h deleted file mode 100644 index 8a2b4421b..000000000 --- a/libpixelflinger/include/pixelflinger/pixelflinger.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h deleted file mode 100644 index 563b0f119..000000000 --- a/libpixelflinger/include/private/pixelflinger/ggl_context.h +++ /dev/null @@ -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 - diff --git a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h deleted file mode 100644 index 4217a8997..000000000 --- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/picker.cpp b/libpixelflinger/picker.cpp deleted file mode 100644 index aa55229a0..000000000 --- a/libpixelflinger/picker.cpp +++ /dev/null @@ -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 - diff --git a/libpixelflinger/picker.h b/libpixelflinger/picker.h deleted file mode 100644 index 9cdbc3c12..000000000 --- a/libpixelflinger/picker.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/pixelflinger.cpp b/libpixelflinger/pixelflinger.cpp deleted file mode 100644 index fd449b2eb..000000000 --- a/libpixelflinger/pixelflinger.cpp +++ /dev/null @@ -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; -} - diff --git a/libpixelflinger/raster.cpp b/libpixelflinger/raster.cpp deleted file mode 100644 index e95c2c8ab..000000000 --- a/libpixelflinger/raster.cpp +++ /dev/null @@ -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; -} - diff --git a/libpixelflinger/raster.h b/libpixelflinger/raster.h deleted file mode 100644 index 9f0f240aa..000000000 --- a/libpixelflinger/raster.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp deleted file mode 100644 index 4cc23c773..000000000 --- a/libpixelflinger/scanline.cpp +++ /dev/null @@ -1,2373 +0,0 @@ -/* libs/pixelflinger/scanline.cpp -** -** Copyright 2006-2011, 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" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cutils/memory.h> -#include <log/log.h> - -#include "buffer.h" -#include "scanline.h" - -#include "codeflinger/CodeCache.h" -#include "codeflinger/GGLAssembler.h" -#if defined(__arm__) -#include "codeflinger/ARMAssembler.h" -#elif defined(__aarch64__) -#include "codeflinger/Arm64Assembler.h" -#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 -#include "codeflinger/MIPSAssembler.h" -#elif defined(__mips__) && defined(__LP64__) -#include "codeflinger/MIPS64Assembler.h" -#endif -//#include "codeflinger/ARMAssemblerOptimizer.h" - -// ---------------------------------------------------------------------------- - -#define ANDROID_CODEGEN_GENERIC 0 // force generic pixel pipeline -#define ANDROID_CODEGEN_C 1 // hand-written C, fallback generic -#define ANDROID_CODEGEN_ASM 2 // hand-written asm, fallback generic -#define ANDROID_CODEGEN_GENERATED 3 // hand-written asm, fallback codegen - -#ifdef NDEBUG -# define ANDROID_RELEASE -# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED -#else -# define ANDROID_DEBUG -# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED -#endif - -#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))) || defined(__aarch64__) -# define ANDROID_ARM_CODEGEN 1 -#else -# define ANDROID_ARM_CODEGEN 0 -#endif - -#define DEBUG__CODEGEN_ONLY 0 - -/* Set to 1 to dump to the log the states that need a new - * code-generated scanline callback, i.e. those that don't - * have a corresponding shortcut function. - */ -#define DEBUG_NEEDS 0 - -#if defined( __mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)) -#define ASSEMBLY_SCRATCH_SIZE 4096 -#elif defined(__aarch64__) -#define ASSEMBLY_SCRATCH_SIZE 8192 -#else -#define ASSEMBLY_SCRATCH_SIZE 2048 -#endif - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -static void init_y(context_t*, int32_t); -static void init_y_noop(context_t*, int32_t); -static void init_y_packed(context_t*, int32_t); -static void init_y_error(context_t*, int32_t); - -static void step_y__generic(context_t* c); -static void step_y__nop(context_t*); -static void step_y__smooth(context_t* c); -static void step_y__tmu(context_t* c); -static void step_y__w(context_t* c); - -static void scanline(context_t* c); -static void scanline_perspective(context_t* c); -static void scanline_perspective_single(context_t* c); -static void scanline_t32cb16blend(context_t* c); -static void scanline_t32cb16blend_dither(context_t* c); -static void scanline_t32cb16blend_srca(context_t* c); -static void scanline_t32cb16blend_clamp(context_t* c); -static void scanline_t32cb16blend_clamp_dither(context_t* c); -static void scanline_t32cb16blend_clamp_mod(context_t* c); -static void scanline_x32cb16blend_clamp_mod(context_t* c); -static void scanline_t32cb16blend_clamp_mod_dither(context_t* c); -static void scanline_x32cb16blend_clamp_mod_dither(context_t* c); -static void scanline_t32cb16(context_t* c); -static void scanline_t32cb16_dither(context_t* c); -static void scanline_t32cb16_clamp(context_t* c); -static void scanline_t32cb16_clamp_dither(context_t* c); -static void scanline_col32cb16blend(context_t* c); -static void scanline_t16cb16_clamp(context_t* c); -static void scanline_t16cb16blend_clamp_mod(context_t* c); -static void scanline_memcpy(context_t* c); -static void scanline_memset8(context_t* c); -static void scanline_memset16(context_t* c); -static void scanline_memset32(context_t* c); -static void scanline_noop(context_t* c); -static void scanline_set(context_t* c); -static void scanline_clear(context_t* c); - -static void rect_generic(context_t* c, size_t yc); -static void rect_memcpy(context_t* c, size_t yc); - -#if defined( __arm__) -extern "C" void scanline_t32cb16blend_arm(uint16_t*, uint32_t*, size_t); -extern "C" void scanline_t32cb16_arm(uint16_t *dst, uint32_t *src, size_t ct); -extern "C" void scanline_col32cb16blend_neon(uint16_t *dst, uint32_t *col, size_t ct); -extern "C" void scanline_col32cb16blend_arm(uint16_t *dst, uint32_t col, size_t ct); -#elif defined(__aarch64__) -extern "C" void scanline_t32cb16blend_arm64(uint16_t*, uint32_t*, size_t); -extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct); -#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 -extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t); -#elif defined(__mips__) && defined(__LP64__) -extern "C" void scanline_t32cb16blend_mips64(uint16_t*, uint32_t*, size_t); -extern "C" void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t col, size_t ct); -#endif - -// ---------------------------------------------------------------------------- - -static inline uint16_t convertAbgr8888ToRgb565(uint32_t pix) -{ - return uint16_t( ((pix << 8) & 0xf800) | - ((pix >> 5) & 0x07e0) | - ((pix >> 19) & 0x001f) ); -} - -struct shortcut_t { - needs_filter_t filter; - const char* desc; - void (*scanline)(context_t*); - void (*init_y)(context_t*, int32_t); -}; - -// Keep in sync with needs - -/* To understand the values here, have a look at: - * system/core/include/private/pixelflinger/ggl_context.h - * - * Especially the lines defining and using GGL_RESERVE_NEEDS - * - * Quick reminders: - * - the last nibble of the first value is the destination buffer format. - * - the last nibble of the third value is the source texture format - * - formats: 4=rgb565 1=abgr8888 2=xbgr8888 - * - * In the descriptions below: - * - * SRC means we copy the source pixels to the destination - * - * SRC_OVER means we blend the source pixels to the destination - * with dstFactor = 1-srcA, srcFactor=1 (premultiplied source). - * This mode is otherwise called 'blend'. - * - * SRCA_OVER means we blend the source pixels to the destination - * with dstFactor=srcA*(1-srcA) srcFactor=srcA (non-premul source). - * This mode is otherwise called 'blend_srca' - * - * clamp means we fetch source pixels from a texture with u/v clamping - * - * mod means the source pixels are modulated (multiplied) by the - * a/r/g/b of the current context's color. Typically used for - * fade-in / fade-out. - * - * dither means we dither 32 bit values to 16 bits - */ -static shortcut_t shortcuts[] = { - { { { 0x03515104, 0x00000077, { 0x00000A01, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, blend SRC_OVER", scanline_t32cb16blend, init_y_noop }, - { { { 0x03010104, 0x00000077, { 0x00000A01, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC", scanline_t32cb16, init_y_noop }, - /* same as first entry, but with dithering */ - { { { 0x03515104, 0x00000177, { 0x00000A01, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, blend SRC_OVER dither", scanline_t32cb16blend_dither, init_y_noop }, - /* same as second entry, but with dithering */ - { { { 0x03010104, 0x00000177, { 0x00000A01, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC dither", scanline_t32cb16_dither, init_y_noop }, - /* this is used during the boot animation - CHEAT: ignore dithering */ - { { { 0x03545404, 0x00000077, { 0x00000A01, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFEFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, blend dst:ONE_MINUS_SRCA src:SRCA", scanline_t32cb16blend_srca, init_y_noop }, - /* special case for arbitrary texture coordinates (think scaling) */ - { { { 0x03515104, 0x00000077, { 0x00000001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC_OVER clamp", scanline_t32cb16blend_clamp, init_y }, - { { { 0x03515104, 0x00000177, { 0x00000001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC_OVER clamp dither", scanline_t32cb16blend_clamp_dither, init_y }, - /* another case used during emulation */ - { { { 0x03515104, 0x00000077, { 0x00001001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC_OVER clamp modulate", scanline_t32cb16blend_clamp_mod, init_y }, - /* and this */ - { { { 0x03515104, 0x00000077, { 0x00001002, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, x888 tx, SRC_OVER clamp modulate", scanline_x32cb16blend_clamp_mod, init_y }, - { { { 0x03515104, 0x00000177, { 0x00001001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC_OVER clamp modulate dither", scanline_t32cb16blend_clamp_mod_dither, init_y }, - { { { 0x03515104, 0x00000177, { 0x00001002, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, x888 tx, SRC_OVER clamp modulate dither", scanline_x32cb16blend_clamp_mod_dither, init_y }, - { { { 0x03010104, 0x00000077, { 0x00000001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC clamp", scanline_t32cb16_clamp, init_y }, - { { { 0x03010104, 0x00000077, { 0x00000002, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, x888 tx, SRC clamp", scanline_t32cb16_clamp, init_y }, - { { { 0x03010104, 0x00000177, { 0x00000001, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 8888 tx, SRC clamp dither", scanline_t32cb16_clamp_dither, init_y }, - { { { 0x03010104, 0x00000177, { 0x00000002, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, x888 tx, SRC clamp dither", scanline_t32cb16_clamp_dither, init_y }, - { { { 0x03010104, 0x00000077, { 0x00000004, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 565 tx, SRC clamp", scanline_t16cb16_clamp, init_y }, - { { { 0x03515104, 0x00000077, { 0x00001004, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } }, - "565 fb, 565 tx, SRC_OVER clamp", scanline_t16cb16blend_clamp_mod, init_y }, - { { { 0x03515104, 0x00000077, { 0x00000000, 0x00000000 } }, - { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0xFFFFFFFF } } }, - "565 fb, 8888 fixed color", scanline_col32cb16blend, init_y_packed }, - { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } }, - { 0x00000000, 0x00000007, { 0x00000000, 0x00000000 } } }, - "(nop) alpha test", scanline_noop, init_y_noop }, - { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } }, - { 0x00000000, 0x00000070, { 0x00000000, 0x00000000 } } }, - "(nop) depth test", scanline_noop, init_y_noop }, - { { { 0x05000000, 0x00000000, { 0x00000000, 0x00000000 } }, - { 0x0F000000, 0x00000080, { 0x00000000, 0x00000000 } } }, - "(nop) logic_op", scanline_noop, init_y_noop }, - { { { 0xF0000000, 0x00000000, { 0x00000000, 0x00000000 } }, - { 0xF0000000, 0x00000080, { 0x00000000, 0x00000000 } } }, - "(nop) color mask", scanline_noop, init_y_noop }, - { { { 0x0F000000, 0x00000077, { 0x00000000, 0x00000000 } }, - { 0xFF000000, 0x000000F7, { 0x00000000, 0x00000000 } } }, - "(set) logic_op", scanline_set, init_y_noop }, - { { { 0x00000000, 0x00000077, { 0x00000000, 0x00000000 } }, - { 0xFF000000, 0x000000F7, { 0x00000000, 0x00000000 } } }, - "(clear) logic_op", scanline_clear, init_y_noop }, - { { { 0x03000000, 0x00000077, { 0x00000000, 0x00000000 } }, - { 0xFFFFFF00, 0x000000F7, { 0x00000000, 0x00000000 } } }, - "(clear) blending 0/0", scanline_clear, init_y_noop }, - { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } }, - { 0x0000003F, 0x00000000, { 0x00000000, 0x00000000 } } }, - "(error) invalid color-buffer format", scanline_noop, init_y_error }, -}; -static const needs_filter_t noblend1to1 = { - // (disregard dithering, see below) - { 0x03010100, 0x00000077, { 0x00000A00, 0x00000000 } }, - { 0xFFFFFFC0, 0xFFFFFEFF, { 0xFFFFFFC0, 0x0000003F } } -}; -static const needs_filter_t fill16noblend = { - { 0x03010100, 0x00000077, { 0x00000000, 0x00000000 } }, - { 0xFFFFFFC0, 0xFFFFFFFF, { 0x0000003F, 0x0000003F } } -}; - -// ---------------------------------------------------------------------------- - -#if ANDROID_ARM_CODEGEN - -#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)) -static CodeCache gCodeCache(32 * 1024); -#elif defined(__aarch64__) -static CodeCache gCodeCache(48 * 1024); -#else -static CodeCache gCodeCache(12 * 1024); -#endif - -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; } -}; -#endif - -// ---------------------------------------------------------------------------- - -void ggl_init_scanline(context_t* c) -{ - c->init_y = init_y; - c->step_y = step_y__generic; - c->scanline = scanline; -} - -void ggl_uninit_scanline(context_t* c) -{ - if (c->state.buffers.coverage) - free(c->state.buffers.coverage); -#if ANDROID_ARM_CODEGEN - if (c->scanline_as) - c->scanline_as->decStrong(c); -#endif -} - -// ---------------------------------------------------------------------------- - -static void pick_scanline(context_t* c) -{ -#if (!defined(DEBUG__CODEGEN_ONLY) || (DEBUG__CODEGEN_ONLY == 0)) - -#if ANDROID_CODEGEN == ANDROID_CODEGEN_GENERIC - c->init_y = init_y; - c->step_y = step_y__generic; - c->scanline = scanline; - return; -#endif - - //printf("*** needs [%08lx:%08lx:%08lx:%08lx]\n", - // c->state.needs.n, c->state.needs.p, - // c->state.needs.t[0], c->state.needs.t[1]); - - // first handle the special case that we cannot test with a filter - const uint32_t cb_format = GGL_READ_NEEDS(CB_FORMAT, c->state.needs.n); - if (GGL_READ_NEEDS(T_FORMAT, c->state.needs.t[0]) == cb_format) { - if (c->state.needs.match(noblend1to1)) { - // this will match regardless of dithering state, since both - // src and dest have the same format anyway, there is no dithering - // to be done. - const GGLFormat* f = - &(c->formats[GGL_READ_NEEDS(T_FORMAT, c->state.needs.t[0])]); - if ((f->components == GGL_RGB) || - (f->components == GGL_RGBA) || - (f->components == GGL_LUMINANCE) || - (f->components == GGL_LUMINANCE_ALPHA)) - { - // format must have all of RGB components - // (so the current color doesn't show through) - c->scanline = scanline_memcpy; - c->init_y = init_y_noop; - return; - } - } - } - - if (c->state.needs.match(fill16noblend)) { - c->init_y = init_y_packed; - switch (c->formats[cb_format].size) { - case 1: c->scanline = scanline_memset8; return; - case 2: c->scanline = scanline_memset16; return; - case 4: c->scanline = scanline_memset32; return; - } - } - - const int numFilters = sizeof(shortcuts)/sizeof(shortcut_t); - for (int i=0 ; i<numFilters ; i++) { - if (c->state.needs.match(shortcuts[i].filter)) { - c->scanline = shortcuts[i].scanline; - c->init_y = shortcuts[i].init_y; - return; - } - } - -#if DEBUG_NEEDS - ALOGI("Needs: n=0x%08x p=0x%08x t0=0x%08x t1=0x%08x", - c->state.needs.n, c->state.needs.p, - c->state.needs.t[0], c->state.needs.t[1]); -#endif - -#endif // DEBUG__CODEGEN_ONLY - - c->init_y = init_y; - c->step_y = step_y__generic; - -#if ANDROID_ARM_CODEGEN - // we're going to have to generate some code... - // here, generate code for our pixel pipeline - const AssemblyKey<needs_t> key(c->state.needs); - sp<Assembly> assembly = gCodeCache.lookup(key); - if (assembly == 0) { - // create a new assembly region - sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs, - ASSEMBLY_SCRATCH_SIZE); - // initialize our assembler -#if defined(__arm__) - GGLAssembler assembler( new ARMAssembler(a) ); - //GGLAssembler assembler( - // new ARMAssemblerOptimizer(new ARMAssembler(a)) ); -#endif -#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 - GGLAssembler assembler( new ArmToMipsAssembler(a) ); -#elif defined(__mips__) && defined(__LP64__) - GGLAssembler assembler( new ArmToMips64Assembler(a) ); -#elif defined(__aarch64__) - GGLAssembler assembler( new ArmToArm64Assembler(a) ); -#endif - // generate the scanline code for the given needs - bool err = assembler.scanline(c->state.needs, c) != 0; - if (ggl_likely(!err)) { - // finally, cache this assembly - err = gCodeCache.cache(a->key(), a) < 0; - } - if (ggl_unlikely(err)) { - ALOGE("error generating or caching assembly. Reverting to NOP."); - c->scanline = scanline_noop; - c->init_y = init_y_noop; - c->step_y = step_y__nop; - return; - } - assembly = a; - } - - // release the previous assembly - if (c->scanline_as) { - c->scanline_as->decStrong(c); - } - - //ALOGI("using generated pixel-pipeline"); - c->scanline_as = assembly.get(); - c->scanline_as->incStrong(c); // hold on to assembly - c->scanline = (void(*)(context_t* c))assembly->base(); -#else -// ALOGW("using generic (slow) pixel-pipeline"); - c->scanline = scanline; -#endif -} - -void ggl_pick_scanline(context_t* c) -{ - pick_scanline(c); - if ((c->state.enables & GGL_ENABLE_W) && - (c->state.enables & GGL_ENABLE_TMUS)) - { - c->span = c->scanline; - c->scanline = scanline_perspective; - if (!(c->state.enabled_tmu & (c->state.enabled_tmu - 1))) { - // only one TMU enabled - c->scanline = scanline_perspective_single; - } - } -} - -// ---------------------------------------------------------------------------- - -static void blending(context_t* c, pixel_t* fragment, pixel_t* fb); -static void blend_factor(context_t* c, pixel_t* r, uint32_t factor, - const pixel_t* src, const pixel_t* dst); -static void rescale(uint32_t& u, uint8_t& su, uint32_t& v, uint8_t& sv); - -#if ANDROID_ARM_CODEGEN && (ANDROID_CODEGEN == ANDROID_CODEGEN_GENERATED) - -// no need to compile the generic-pipeline, it can't be reached -void scanline(context_t*) -{ -} - -#else - -void rescale(uint32_t& u, uint8_t& su, uint32_t& v, uint8_t& sv) -{ - if (su && sv) { - if (su > sv) { - v = ggl_expand(v, sv, su); - sv = su; - } else if (su < sv) { - u = ggl_expand(u, su, sv); - su = sv; - } - } -} - -void blending(context_t* c, pixel_t* fragment, pixel_t* fb) -{ - rescale(fragment->c[0], fragment->s[0], fb->c[0], fb->s[0]); - rescale(fragment->c[1], fragment->s[1], fb->c[1], fb->s[1]); - rescale(fragment->c[2], fragment->s[2], fb->c[2], fb->s[2]); - rescale(fragment->c[3], fragment->s[3], fb->c[3], fb->s[3]); - - pixel_t sf, df; - blend_factor(c, &sf, c->state.blend.src, fragment, fb); - blend_factor(c, &df, c->state.blend.dst, fragment, fb); - - fragment->c[1] = - gglMulAddx(fragment->c[1], sf.c[1], gglMulx(fb->c[1], df.c[1])); - fragment->c[2] = - gglMulAddx(fragment->c[2], sf.c[2], gglMulx(fb->c[2], df.c[2])); - fragment->c[3] = - gglMulAddx(fragment->c[3], sf.c[3], gglMulx(fb->c[3], df.c[3])); - - if (c->state.blend.alpha_separate) { - blend_factor(c, &sf, c->state.blend.src_alpha, fragment, fb); - blend_factor(c, &df, c->state.blend.dst_alpha, fragment, fb); - } - - fragment->c[0] = - gglMulAddx(fragment->c[0], sf.c[0], gglMulx(fb->c[0], df.c[0])); - - // clamp to 1.0 - if (fragment->c[0] >= (1LU<<fragment->s[0])) - fragment->c[0] = (1<<fragment->s[0])-1; - if (fragment->c[1] >= (1LU<<fragment->s[1])) - fragment->c[1] = (1<<fragment->s[1])-1; - if (fragment->c[2] >= (1LU<<fragment->s[2])) - fragment->c[2] = (1<<fragment->s[2])-1; - if (fragment->c[3] >= (1LU<<fragment->s[3])) - fragment->c[3] = (1<<fragment->s[3])-1; -} - -static inline int blendfactor(uint32_t x, uint32_t size, uint32_t def = 0) -{ - if (!size) - return def; - - // scale to 16 bits - if (size > 16) { - x >>= (size - 16); - } else if (size < 16) { - x = ggl_expand(x, size, 16); - } - x += x >> 15; - return x; -} - -void blend_factor(context_t* /*c*/, pixel_t* r, - uint32_t factor, const pixel_t* src, const pixel_t* dst) -{ - switch (factor) { - case GGL_ZERO: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = 0; - break; - case GGL_ONE: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = FIXED_ONE; - break; - case GGL_DST_COLOR: - r->c[1] = blendfactor(dst->c[1], dst->s[1]); - r->c[2] = blendfactor(dst->c[2], dst->s[2]); - r->c[3] = blendfactor(dst->c[3], dst->s[3]); - r->c[0] = blendfactor(dst->c[0], dst->s[0]); - break; - case GGL_SRC_COLOR: - r->c[1] = blendfactor(src->c[1], src->s[1]); - r->c[2] = blendfactor(src->c[2], src->s[2]); - r->c[3] = blendfactor(src->c[3], src->s[3]); - r->c[0] = blendfactor(src->c[0], src->s[0]); - break; - case GGL_ONE_MINUS_DST_COLOR: - r->c[1] = FIXED_ONE - blendfactor(dst->c[1], dst->s[1]); - r->c[2] = FIXED_ONE - blendfactor(dst->c[2], dst->s[2]); - r->c[3] = FIXED_ONE - blendfactor(dst->c[3], dst->s[3]); - r->c[0] = FIXED_ONE - blendfactor(dst->c[0], dst->s[0]); - break; - case GGL_ONE_MINUS_SRC_COLOR: - r->c[1] = FIXED_ONE - blendfactor(src->c[1], src->s[1]); - r->c[2] = FIXED_ONE - blendfactor(src->c[2], src->s[2]); - r->c[3] = FIXED_ONE - blendfactor(src->c[3], src->s[3]); - r->c[0] = FIXED_ONE - blendfactor(src->c[0], src->s[0]); - break; - case GGL_SRC_ALPHA: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = blendfactor(src->c[0], src->s[0], FIXED_ONE); - break; - case GGL_ONE_MINUS_SRC_ALPHA: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = FIXED_ONE - blendfactor(src->c[0], src->s[0], FIXED_ONE); - break; - case GGL_DST_ALPHA: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = blendfactor(dst->c[0], dst->s[0], FIXED_ONE); - break; - case GGL_ONE_MINUS_DST_ALPHA: - r->c[1] = - r->c[2] = - r->c[3] = - r->c[0] = FIXED_ONE - blendfactor(dst->c[0], dst->s[0], FIXED_ONE); - break; - case GGL_SRC_ALPHA_SATURATE: - // XXX: GGL_SRC_ALPHA_SATURATE - break; - } -} - -static GGLfixed wrapping(int32_t coord, uint32_t size, int tx_wrap) -{ - GGLfixed d; - if (tx_wrap == GGL_REPEAT) { - d = (uint32_t(coord)>>16) * size; - } else if (tx_wrap == GGL_CLAMP) { // CLAMP_TO_EDGE semantics - const GGLfixed clamp_min = FIXED_HALF; - const GGLfixed clamp_max = (size << 16) - FIXED_HALF; - if (coord < clamp_min) coord = clamp_min; - if (coord > clamp_max) coord = clamp_max; - d = coord; - } else { // 1:1 - const GGLfixed clamp_min = 0; - const GGLfixed clamp_max = (size << 16); - if (coord < clamp_min) coord = clamp_min; - if (coord > clamp_max) coord = clamp_max; - d = coord; - } - return d; -} - -static inline -GGLcolor ADJUST_COLOR_ITERATOR(GGLcolor v, GGLcolor dvdx, int len) -{ - const int32_t end = dvdx * (len-1) + v; - if (end < 0) - v -= end; - v &= ~(v>>31); - return v; -} - -void scanline(context_t* c) -{ - const uint32_t enables = c->state.enables; - const int xs = c->iterators.xl; - const int x1 = c->iterators.xr; - int xc = x1 - xs; - const int16_t* covPtr = c->state.buffers.coverage + xs; - - // All iterated values are sampled at the pixel center - - // reset iterators for that scanline... - GGLcolor r, g, b, a; - iterators_t& ci = c->iterators; - if (enables & GGL_ENABLE_SMOOTH) { - r = (xs * c->shade.drdx) + ci.ydrdy; - g = (xs * c->shade.dgdx) + ci.ydgdy; - b = (xs * c->shade.dbdx) + ci.ydbdy; - a = (xs * c->shade.dadx) + ci.ydady; - r = ADJUST_COLOR_ITERATOR(r, c->shade.drdx, xc); - g = ADJUST_COLOR_ITERATOR(g, c->shade.dgdx, xc); - b = ADJUST_COLOR_ITERATOR(b, c->shade.dbdx, xc); - a = ADJUST_COLOR_ITERATOR(a, c->shade.dadx, xc); - } else { - r = ci.ydrdy; - g = ci.ydgdy; - b = ci.ydbdy; - a = ci.ydady; - } - - // z iterators are 1.31 - GGLfixed z = (xs * c->shade.dzdx) + ci.ydzdy; - GGLfixed f = (xs * c->shade.dfdx) + ci.ydfdy; - - struct { - GGLfixed s, t; - } tc[GGL_TEXTURE_UNIT_COUNT]; - if (enables & GGL_ENABLE_TMUS) { - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - if (c->state.texture[i].enable) { - texture_iterators_t& ti = c->state.texture[i].iterators; - if (enables & GGL_ENABLE_W) { - tc[i].s = ti.ydsdy; - tc[i].t = ti.ydtdy; - } else { - tc[i].s = (xs * ti.dsdx) + ti.ydsdy; - tc[i].t = (xs * ti.dtdx) + ti.ydtdy; - } - } - } - } - - pixel_t fragment; - pixel_t texel; - pixel_t fb; - - uint32_t x = xs; - uint32_t y = c->iterators.y; - - while (xc--) { - - { // just a scope - - // read color (convert to 8 bits by keeping only the integer part) - fragment.s[1] = fragment.s[2] = - fragment.s[3] = fragment.s[0] = 8; - fragment.c[1] = r >> (GGL_COLOR_BITS-8); - fragment.c[2] = g >> (GGL_COLOR_BITS-8); - fragment.c[3] = b >> (GGL_COLOR_BITS-8); - fragment.c[0] = a >> (GGL_COLOR_BITS-8); - - // texturing - if (enables & GGL_ENABLE_TMUS) { - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - texture_t& tx = c->state.texture[i]; - if (!tx.enable) - continue; - texture_iterators_t& ti = tx.iterators; - int32_t u, v; - - // s-coordinate - if (tx.s_coord != GGL_ONE_TO_ONE) { - const int w = tx.surface.width; - u = wrapping(tc[i].s, w, tx.s_wrap); - tc[i].s += ti.dsdx; - } else { - u = (((tx.shade.is0>>16) + x)<<16) + FIXED_HALF; - } - - // t-coordinate - if (tx.t_coord != GGL_ONE_TO_ONE) { - const int h = tx.surface.height; - v = wrapping(tc[i].t, h, tx.t_wrap); - tc[i].t += ti.dtdx; - } else { - v = (((tx.shade.it0>>16) + y)<<16) + FIXED_HALF; - } - - // read texture - if (tx.mag_filter == GGL_NEAREST && - tx.min_filter == GGL_NEAREST) - { - u >>= 16; - v >>= 16; - tx.surface.read(&tx.surface, c, u, v, &texel); - } else { - const int w = tx.surface.width; - const int h = tx.surface.height; - u -= FIXED_HALF; - v -= FIXED_HALF; - int u0 = u >> 16; - int v0 = v >> 16; - int u1 = u0 + 1; - int v1 = v0 + 1; - if (tx.s_wrap == GGL_REPEAT) { - if (u0<0) u0 += w; - if (u1<0) u1 += w; - if (u0>=w) u0 -= w; - if (u1>=w) u1 -= w; - } else { - if (u0<0) u0 = 0; - if (u1<0) u1 = 0; - if (u0>=w) u0 = w-1; - if (u1>=w) u1 = w-1; - } - if (tx.t_wrap == GGL_REPEAT) { - if (v0<0) v0 += h; - if (v1<0) v1 += h; - if (v0>=h) v0 -= h; - if (v1>=h) v1 -= h; - } else { - if (v0<0) v0 = 0; - if (v1<0) v1 = 0; - if (v0>=h) v0 = h-1; - if (v1>=h) v1 = h-1; - } - pixel_t texels[4]; - uint32_t mm[4]; - tx.surface.read(&tx.surface, c, u0, v0, &texels[0]); - tx.surface.read(&tx.surface, c, u0, v1, &texels[1]); - tx.surface.read(&tx.surface, c, u1, v0, &texels[2]); - tx.surface.read(&tx.surface, c, u1, v1, &texels[3]); - u = (u >> 12) & 0xF; - v = (v >> 12) & 0xF; - u += u>>3; - v += v>>3; - mm[0] = (0x10 - u) * (0x10 - v); - mm[1] = (0x10 - u) * v; - mm[2] = u * (0x10 - v); - mm[3] = 0x100 - (mm[0] + mm[1] + mm[2]); - for (int j=0 ; j<4 ; j++) { - texel.s[j] = texels[0].s[j]; - if (!texel.s[j]) continue; - texel.s[j] += 8; - texel.c[j] = texels[0].c[j]*mm[0] + - texels[1].c[j]*mm[1] + - texels[2].c[j]*mm[2] + - texels[3].c[j]*mm[3] ; - } - } - - // Texture environnement... - for (int j=0 ; j<4 ; j++) { - uint32_t& Cf = fragment.c[j]; - uint32_t& Ct = texel.c[j]; - uint8_t& sf = fragment.s[j]; - uint8_t& st = texel.s[j]; - uint32_t At = texel.c[0]; - uint8_t sat = texel.s[0]; - switch (tx.env) { - case GGL_REPLACE: - if (st) { - Cf = Ct; - sf = st; - } - break; - case GGL_MODULATE: - if (st) { - uint32_t factor = Ct + (Ct>>(st-1)); - Cf = (Cf * factor) >> st; - } - break; - case GGL_DECAL: - if (sat) { - rescale(Cf, sf, Ct, st); - Cf += ((Ct - Cf) * (At + (At>>(sat-1)))) >> sat; - } - break; - case GGL_BLEND: - if (st) { - uint32_t Cc = tx.env_color[i]; - if (sf>8) Cc = (Cc * ((1<<sf)-1))>>8; - else if (sf<8) Cc = (Cc - (Cc>>(8-sf)))>>(8-sf); - uint32_t factor = Ct + (Ct>>(st-1)); - Cf = ((((1<<st) - factor) * Cf) + Ct*Cc)>>st; - } - break; - case GGL_ADD: - if (st) { - rescale(Cf, sf, Ct, st); - Cf += Ct; - } - break; - } - } - } - } - - // coverage application - if (enables & GGL_ENABLE_AA) { - int16_t cf = *covPtr++; - fragment.c[0] = (int64_t(fragment.c[0]) * cf) >> 15; - } - - // alpha-test - if (enables & GGL_ENABLE_ALPHA_TEST) { - GGLcolor ref = c->state.alpha_test.ref; - GGLcolor alpha = (uint64_t(fragment.c[0]) * - ((1<<GGL_COLOR_BITS)-1)) / ((1<<fragment.s[0])-1); - switch (c->state.alpha_test.func) { - case GGL_NEVER: goto discard; - case GGL_LESS: if (alpha<ref) break; goto discard; - case GGL_EQUAL: if (alpha==ref) break; goto discard; - case GGL_LEQUAL: if (alpha<=ref) break; goto discard; - case GGL_GREATER: if (alpha>ref) break; goto discard; - case GGL_NOTEQUAL: if (alpha!=ref) break; goto discard; - case GGL_GEQUAL: if (alpha>=ref) break; goto discard; - } - } - - // depth test - if (c->state.buffers.depth.format) { - if (enables & GGL_ENABLE_DEPTH_TEST) { - surface_t* cb = &(c->state.buffers.depth); - uint16_t* p = (uint16_t*)(cb->data)+(x+(cb->stride*y)); - uint16_t zz = uint32_t(z)>>(16); - uint16_t depth = *p; - switch (c->state.depth_test.func) { - case GGL_NEVER: goto discard; - case GGL_LESS: if (zz<depth) break; goto discard; - case GGL_EQUAL: if (zz==depth) break; goto discard; - case GGL_LEQUAL: if (zz<=depth) break; goto discard; - case GGL_GREATER: if (zz>depth) break; goto discard; - case GGL_NOTEQUAL: if (zz!=depth) break; goto discard; - case GGL_GEQUAL: if (zz>=depth) break; goto discard; - } - // depth buffer is not enabled, if depth-test is not enabled -/* - fragment.s[1] = fragment.s[2] = - fragment.s[3] = fragment.s[0] = 8; - fragment.c[1] = - fragment.c[2] = - fragment.c[3] = - fragment.c[0] = 255 - (zz>>8); -*/ - if (c->state.mask.depth) { - *p = zz; - } - } - } - - // fog - if (enables & GGL_ENABLE_FOG) { - for (int i=1 ; i<=3 ; i++) { - GGLfixed fc = (c->state.fog.color[i] * 0x10000) / 0xFF; - uint32_t& c = fragment.c[i]; - uint8_t& s = fragment.s[i]; - c = (c * 0x10000) / ((1<<s)-1); - c = gglMulAddx(c, f, gglMulx(fc, 0x10000 - f)); - s = 16; - } - } - - // blending - if (enables & GGL_ENABLE_BLENDING) { - fb.c[1] = fb.c[2] = fb.c[3] = fb.c[0] = 0; // placate valgrind - fb.s[1] = fb.s[2] = fb.s[3] = fb.s[0] = 0; - c->state.buffers.color.read( - &(c->state.buffers.color), c, x, y, &fb); - blending( c, &fragment, &fb ); - } - - // write - c->state.buffers.color.write( - &(c->state.buffers.color), c, x, y, &fragment); - } - -discard: - // iterate... - x += 1; - if (enables & GGL_ENABLE_SMOOTH) { - r += c->shade.drdx; - g += c->shade.dgdx; - b += c->shade.dbdx; - a += c->shade.dadx; - } - z += c->shade.dzdx; - f += c->shade.dfdx; - } -} - -#endif // ANDROID_ARM_CODEGEN && (ANDROID_CODEGEN == ANDROID_CODEGEN_GENERATED) - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Scanline -#endif - -/* Used to parse a 32-bit source texture linearly. Usage is: - * - * horz_iterator32 hi(context); - * while (...) { - * uint32_t src_pixel = hi.get_pixel32(); - * ... - * } - * - * Use only for one-to-one texture mapping. - */ -struct horz_iterator32 { - explicit horz_iterator32(context_t* c) { - const int x = c->iterators.xl; - const int y = c->iterators.y; - texture_t& tx = c->state.texture[0]; - const int32_t u = (tx.shade.is0>>16) + x; - const int32_t v = (tx.shade.it0>>16) + y; - m_src = reinterpret_cast<uint32_t*>(tx.surface.data)+(u+(tx.surface.stride*v)); - } - uint32_t get_pixel32() { - return *m_src++; - } -protected: - uint32_t* m_src; -}; - -/* A variant for 16-bit source textures. */ -struct horz_iterator16 { - explicit horz_iterator16(context_t* c) { - const int x = c->iterators.xl; - const int y = c->iterators.y; - texture_t& tx = c->state.texture[0]; - const int32_t u = (tx.shade.is0>>16) + x; - const int32_t v = (tx.shade.it0>>16) + y; - m_src = reinterpret_cast<uint16_t*>(tx.surface.data)+(u+(tx.surface.stride*v)); - } - uint16_t get_pixel16() { - return *m_src++; - } -protected: - uint16_t* m_src; -}; - -/* A clamp iterator is used to iterate inside a texture with GGL_CLAMP. - * After initialization, call get_src16() or get_src32() to get the current - * texture pixel value. - */ -struct clamp_iterator { - explicit clamp_iterator(context_t* c) { - const int xs = c->iterators.xl; - texture_t& tx = c->state.texture[0]; - texture_iterators_t& ti = tx.iterators; - m_s = (xs * ti.dsdx) + ti.ydsdy; - m_t = (xs * ti.dtdx) + ti.ydtdy; - m_ds = ti.dsdx; - m_dt = ti.dtdx; - m_width_m1 = tx.surface.width - 1; - m_height_m1 = tx.surface.height - 1; - m_data = tx.surface.data; - m_stride = tx.surface.stride; - } - uint16_t get_pixel16() { - int u, v; - get_uv(u, v); - uint16_t* src = reinterpret_cast<uint16_t*>(m_data) + (u + (m_stride*v)); - return src[0]; - } - uint32_t get_pixel32() { - int u, v; - get_uv(u, v); - uint32_t* src = reinterpret_cast<uint32_t*>(m_data) + (u + (m_stride*v)); - return src[0]; - } -private: - void get_uv(int& u, int& v) { - int uu = m_s >> 16; - int vv = m_t >> 16; - if (uu < 0) - uu = 0; - if (uu > m_width_m1) - uu = m_width_m1; - if (vv < 0) - vv = 0; - if (vv > m_height_m1) - vv = m_height_m1; - u = uu; - v = vv; - m_s += m_ds; - m_t += m_dt; - } - - GGLfixed m_s, m_t; - GGLfixed m_ds, m_dt; - int m_width_m1, m_height_m1; - uint8_t* m_data; - int m_stride; -}; - -/* - * The 'horizontal clamp iterator' variant corresponds to the case where - * the 'v' coordinate doesn't change. This is useful to avoid one mult and - * extra adds / checks per pixels, if the blending/processing operation after - * this is very fast. - */ -static int is_context_horizontal(const context_t* c) { - return (c->state.texture[0].iterators.dtdx == 0); -} - -struct horz_clamp_iterator { - uint16_t get_pixel16() { - int u = m_s >> 16; - m_s += m_ds; - if (u < 0) - u = 0; - if (u > m_width_m1) - u = m_width_m1; - const uint16_t* src = reinterpret_cast<const uint16_t*>(m_data); - return src[u]; - } - uint32_t get_pixel32() { - int u = m_s >> 16; - m_s += m_ds; - if (u < 0) - u = 0; - if (u > m_width_m1) - u = m_width_m1; - const uint32_t* src = reinterpret_cast<const uint32_t*>(m_data); - return src[u]; - } -protected: - void init(const context_t* c, int shift); - GGLfixed m_s; - GGLfixed m_ds; - int m_width_m1; - const uint8_t* m_data; -}; - -void horz_clamp_iterator::init(const context_t* c, int shift) -{ - const int xs = c->iterators.xl; - const texture_t& tx = c->state.texture[0]; - const texture_iterators_t& ti = tx.iterators; - m_s = (xs * ti.dsdx) + ti.ydsdy; - m_ds = ti.dsdx; - m_width_m1 = tx.surface.width-1; - m_data = tx.surface.data; - - GGLfixed t = (xs * ti.dtdx) + ti.ydtdy; - int v = t >> 16; - if (v < 0) - v = 0; - else if (v >= (int)tx.surface.height) - v = (int)tx.surface.height-1; - - m_data += (tx.surface.stride*v) << shift; -} - -struct horz_clamp_iterator16 : horz_clamp_iterator { - explicit horz_clamp_iterator16(const context_t* c) { - init(c,1); - }; -}; - -struct horz_clamp_iterator32 : horz_clamp_iterator { - explicit horz_clamp_iterator32(context_t* c) { - init(c,2); - }; -}; - -/* This is used to perform dithering operations. - */ -struct ditherer { - explicit ditherer(const context_t* c) { - const int x = c->iterators.xl; - const int y = c->iterators.y; - m_line = &c->ditherMatrix[ ((y & GGL_DITHER_MASK)<<GGL_DITHER_ORDER_SHIFT) ]; - m_index = x & GGL_DITHER_MASK; - } - void step(void) { - m_index++; - } - int get_value(void) { - int ret = m_line[m_index & GGL_DITHER_MASK]; - m_index++; - return ret; - } - uint16_t abgr8888ToRgb565(uint32_t s) { - uint32_t r = s & 0xff; - uint32_t g = (s >> 8) & 0xff; - uint32_t b = (s >> 16) & 0xff; - return rgb888ToRgb565(r,g,b); - } - /* The following assumes that r/g/b are in the 0..255 range each */ - uint16_t rgb888ToRgb565(uint32_t& r, uint32_t& g, uint32_t &b) { - int threshold = get_value(); - /* dither in on GGL_DITHER_BITS, and each of r, g, b is on 8 bits */ - r += (threshold >> (GGL_DITHER_BITS-8 +5)); - g += (threshold >> (GGL_DITHER_BITS-8 +6)); - b += (threshold >> (GGL_DITHER_BITS-8 +5)); - if (r > 0xff) - r = 0xff; - if (g > 0xff) - g = 0xff; - if (b > 0xff) - b = 0xff; - return uint16_t(((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3)); - } -protected: - const uint8_t* m_line; - int m_index; -}; - -/* This structure is used to blend (SRC_OVER) 32-bit source pixels - * onto 16-bit destination ones. Usage is simply: - * - * blender.blend(<32-bit-src-pixel-value>,<ptr-to-16-bit-dest-pixel>) - */ -struct blender_32to16 { - explicit blender_32to16(context_t* /*c*/) { } - void write(uint32_t s, uint16_t* dst) { - if (s == 0) - return; - s = GGL_RGBA_TO_HOST(s); - int sA = (s>>24); - if (sA == 0xff) { - *dst = convertAbgr8888ToRgb565(s); - } else { - int f = 0x100 - (sA + (sA>>7)); - int sR = (s >> ( 3))&0x1F; - int sG = (s >> ( 8+2))&0x3F; - int sB = (s >> (16+3))&0x1F; - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR += (f*dR)>>8; - sG += (f*dG)>>8; - sB += (f*dB)>>8; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } - } - void write(uint32_t s, uint16_t* dst, ditherer& di) { - if (s == 0) { - di.step(); - return; - } - s = GGL_RGBA_TO_HOST(s); - int sA = (s>>24); - if (sA == 0xff) { - *dst = di.abgr8888ToRgb565(s); - } else { - int threshold = di.get_value() << (8 - GGL_DITHER_BITS); - int f = 0x100 - (sA + (sA>>7)); - int sR = (s >> ( 3))&0x1F; - int sG = (s >> ( 8+2))&0x3F; - int sB = (s >> (16+3))&0x1F; - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = ((sR << 8) + f*dR + threshold)>>8; - sG = ((sG << 8) + f*dG + threshold)>>8; - sB = ((sB << 8) + f*dB + threshold)>>8; - if (sR > 0x1f) sR = 0x1f; - if (sG > 0x3f) sG = 0x3f; - if (sB > 0x1f) sB = 0x1f; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } - } -}; - -/* This blender does the same for the 'blend_srca' operation. - * where dstFactor=srcA*(1-srcA) srcFactor=srcA - */ -struct blender_32to16_srcA { - explicit blender_32to16_srcA(const context_t* /*c*/) { } - void write(uint32_t s, uint16_t* dst) { - if (!s) { - return; - } - uint16_t d = *dst; - s = GGL_RGBA_TO_HOST(s); - int sR = (s >> ( 3))&0x1F; - int sG = (s >> ( 8+2))&0x3F; - int sB = (s >> (16+3))&0x1F; - int sA = (s>>24); - int f1 = (sA + (sA>>7)); - int f2 = 0x100-f1; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (f1*sR + f2*dR)>>8; - sG = (f1*sG + f2*dG)>>8; - sB = (f1*sB + f2*dB)>>8; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } -}; - -/* Common init code the modulating blenders */ -struct blender_modulate { - void init(const context_t* c) { - const int r = c->iterators.ydrdy >> (GGL_COLOR_BITS-8); - const int g = c->iterators.ydgdy >> (GGL_COLOR_BITS-8); - const int b = c->iterators.ydbdy >> (GGL_COLOR_BITS-8); - const int a = c->iterators.ydady >> (GGL_COLOR_BITS-8); - m_r = r + (r >> 7); - m_g = g + (g >> 7); - m_b = b + (b >> 7); - m_a = a + (a >> 7); - } -protected: - int m_r, m_g, m_b, m_a; -}; - -/* This blender does a normal blend after modulation. - */ -struct blender_32to16_modulate : blender_modulate { - explicit blender_32to16_modulate(const context_t* c) { - init(c); - } - void write(uint32_t s, uint16_t* dst) { - // blend source and destination - if (!s) { - return; - } - s = GGL_RGBA_TO_HOST(s); - - /* We need to modulate s */ - uint32_t sA = (s >> 24); - uint32_t sB = (s >> 16) & 0xff; - uint32_t sG = (s >> 8) & 0xff; - uint32_t sR = s & 0xff; - - sA = (sA*m_a) >> 8; - /* Keep R/G/B scaled to 5.8 or 6.8 fixed float format */ - sR = (sR*m_r) >> (8 - 5); - sG = (sG*m_g) >> (8 - 6); - sB = (sB*m_b) >> (8 - 5); - - /* Now do a normal blend */ - int f = 0x100 - (sA + (sA>>7)); - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (sR + f*dR)>>8; - sG = (sG + f*dG)>>8; - sB = (sB + f*dB)>>8; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } - void write(uint32_t s, uint16_t* dst, ditherer& di) { - // blend source and destination - if (!s) { - di.step(); - return; - } - s = GGL_RGBA_TO_HOST(s); - - /* We need to modulate s */ - uint32_t sA = (s >> 24); - uint32_t sB = (s >> 16) & 0xff; - uint32_t sG = (s >> 8) & 0xff; - uint32_t sR = s & 0xff; - - sA = (sA*m_a) >> 8; - /* keep R/G/B scaled to 5.8 or 6.8 fixed float format */ - sR = (sR*m_r) >> (8 - 5); - sG = (sG*m_g) >> (8 - 6); - sB = (sB*m_b) >> (8 - 5); - - /* Scale threshold to 0.8 fixed float format */ - int threshold = di.get_value() << (8 - GGL_DITHER_BITS); - int f = 0x100 - (sA + (sA>>7)); - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (sR + f*dR + threshold)>>8; - sG = (sG + f*dG + threshold)>>8; - sB = (sB + f*dB + threshold)>>8; - if (sR > 0x1f) sR = 0x1f; - if (sG > 0x3f) sG = 0x3f; - if (sB > 0x1f) sB = 0x1f; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } -}; - -/* same as 32to16_modulate, except that the input is xRGB, instead of ARGB */ -struct blender_x32to16_modulate : blender_modulate { - explicit blender_x32to16_modulate(const context_t* c) { - init(c); - } - void write(uint32_t s, uint16_t* dst) { - s = GGL_RGBA_TO_HOST(s); - - uint32_t sB = (s >> 16) & 0xff; - uint32_t sG = (s >> 8) & 0xff; - uint32_t sR = s & 0xff; - - /* Keep R/G/B in 5.8 or 6.8 format */ - sR = (sR*m_r) >> (8 - 5); - sG = (sG*m_g) >> (8 - 6); - sB = (sB*m_b) >> (8 - 5); - - int f = 0x100 - m_a; - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (sR + f*dR)>>8; - sG = (sG + f*dG)>>8; - sB = (sB + f*dB)>>8; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } - void write(uint32_t s, uint16_t* dst, ditherer& di) { - s = GGL_RGBA_TO_HOST(s); - - uint32_t sB = (s >> 16) & 0xff; - uint32_t sG = (s >> 8) & 0xff; - uint32_t sR = s & 0xff; - - sR = (sR*m_r) >> (8 - 5); - sG = (sG*m_g) >> (8 - 6); - sB = (sB*m_b) >> (8 - 5); - - /* Now do a normal blend */ - int threshold = di.get_value() << (8 - GGL_DITHER_BITS); - int f = 0x100 - m_a; - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (sR + f*dR + threshold)>>8; - sG = (sG + f*dG + threshold)>>8; - sB = (sB + f*dB + threshold)>>8; - if (sR > 0x1f) sR = 0x1f; - if (sG > 0x3f) sG = 0x3f; - if (sB > 0x1f) sB = 0x1f; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } -}; - -/* Same as above, but source is 16bit rgb565 */ -struct blender_16to16_modulate : blender_modulate { - explicit blender_16to16_modulate(const context_t* c) { - init(c); - } - void write(uint16_t s16, uint16_t* dst) { - uint32_t s = s16; - - uint32_t sR = s >> 11; - uint32_t sG = (s >> 5) & 0x3f; - uint32_t sB = s & 0x1f; - - sR = (sR*m_r); - sG = (sG*m_g); - sB = (sB*m_b); - - int f = 0x100 - m_a; - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - sR = (sR + f*dR)>>8; - sG = (sG + f*dG)>>8; - sB = (sB + f*dB)>>8; - *dst = uint16_t((sR<<11)|(sG<<5)|sB); - } -}; - -/* This is used to iterate over a 16-bit destination color buffer. - * Usage is: - * - * dst_iterator16 di(context); - * while (di.count--) { - * <do stuff with dest pixel at di.dst> - * di.dst++; - * } - */ -struct dst_iterator16 { - explicit dst_iterator16(const context_t* c) { - const int x = c->iterators.xl; - const int width = c->iterators.xr - x; - const int32_t y = c->iterators.y; - const surface_t* cb = &(c->state.buffers.color); - count = width; - dst = reinterpret_cast<uint16_t*>(cb->data) + (x+(cb->stride*y)); - } - int count; - uint16_t* dst; -}; - - -static void scanline_t32cb16_clamp(context_t* c) -{ - dst_iterator16 di(c); - - if (is_context_horizontal(c)) { - /* Special case for simple horizontal scaling */ - horz_clamp_iterator32 ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - *di.dst++ = convertAbgr8888ToRgb565(s); - } - } else { - /* General case */ - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - *di.dst++ = convertAbgr8888ToRgb565(s); - } - } -} - -static void scanline_t32cb16_dither(context_t* c) -{ - horz_iterator32 si(c); - dst_iterator16 di(c); - ditherer dither(c); - - while (di.count--) { - uint32_t s = si.get_pixel32(); - *di.dst++ = dither.abgr8888ToRgb565(s); - } -} - -static void scanline_t32cb16_clamp_dither(context_t* c) -{ - dst_iterator16 di(c); - ditherer dither(c); - - if (is_context_horizontal(c)) { - /* Special case for simple horizontal scaling */ - horz_clamp_iterator32 ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - *di.dst++ = dither.abgr8888ToRgb565(s); - } - } else { - /* General case */ - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - *di.dst++ = dither.abgr8888ToRgb565(s); - } - } -} - -static void scanline_t32cb16blend_dither(context_t* c) -{ - dst_iterator16 di(c); - ditherer dither(c); - blender_32to16 bl(c); - horz_iterator32 hi(c); - while (di.count--) { - uint32_t s = hi.get_pixel32(); - bl.write(s, di.dst, dither); - di.dst++; - } -} - -static void scanline_t32cb16blend_clamp(context_t* c) -{ - dst_iterator16 di(c); - blender_32to16 bl(c); - - if (is_context_horizontal(c)) { - horz_clamp_iterator32 ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst); - di.dst++; - } - } else { - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst); - di.dst++; - } - } -} - -static void scanline_t32cb16blend_clamp_dither(context_t* c) -{ - dst_iterator16 di(c); - ditherer dither(c); - blender_32to16 bl(c); - - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst, dither); - di.dst++; - } -} - -void scanline_t32cb16blend_clamp_mod(context_t* c) -{ - dst_iterator16 di(c); - blender_32to16_modulate bl(c); - - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst); - di.dst++; - } -} - -void scanline_t32cb16blend_clamp_mod_dither(context_t* c) -{ - dst_iterator16 di(c); - blender_32to16_modulate bl(c); - ditherer dither(c); - - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst, dither); - di.dst++; - } -} - -/* Variant of scanline_t32cb16blend_clamp_mod with a xRGB texture */ -void scanline_x32cb16blend_clamp_mod(context_t* c) -{ - dst_iterator16 di(c); - blender_x32to16_modulate bl(c); - - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst); - di.dst++; - } -} - -void scanline_x32cb16blend_clamp_mod_dither(context_t* c) -{ - dst_iterator16 di(c); - blender_x32to16_modulate bl(c); - ditherer dither(c); - - clamp_iterator ci(c); - while (di.count--) { - uint32_t s = ci.get_pixel32(); - bl.write(s, di.dst, dither); - di.dst++; - } -} - -void scanline_t16cb16_clamp(context_t* c) -{ - dst_iterator16 di(c); - - /* Special case for simple horizontal scaling */ - if (is_context_horizontal(c)) { - horz_clamp_iterator16 ci(c); - while (di.count--) { - *di.dst++ = ci.get_pixel16(); - } - } else { - clamp_iterator ci(c); - while (di.count--) { - *di.dst++ = ci.get_pixel16(); - } - } -} - - - -template <typename T, typename U> -static inline __attribute__((const)) -T interpolate(int y, T v0, U dvdx, U dvdy) { - // interpolates in pixel's centers - // v = v0 + (y + 0.5) * dvdy + (0.5 * dvdx) - return (y * dvdy) + (v0 + ((dvdy + dvdx) >> 1)); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void init_y(context_t* c, int32_t ys) -{ - const uint32_t enables = c->state.enables; - - // compute iterators... - iterators_t& ci = c->iterators; - - // sample in the center - ci.y = ys; - - if (enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_W|GGL_ENABLE_FOG)) { - ci.ydzdy = interpolate(ys, c->shade.z0, c->shade.dzdx, c->shade.dzdy); - ci.ydwdy = interpolate(ys, c->shade.w0, c->shade.dwdx, c->shade.dwdy); - ci.ydfdy = interpolate(ys, c->shade.f0, c->shade.dfdx, c->shade.dfdy); - } - - if (ggl_unlikely(enables & GGL_ENABLE_SMOOTH)) { - ci.ydrdy = interpolate(ys, c->shade.r0, c->shade.drdx, c->shade.drdy); - ci.ydgdy = interpolate(ys, c->shade.g0, c->shade.dgdx, c->shade.dgdy); - ci.ydbdy = interpolate(ys, c->shade.b0, c->shade.dbdx, c->shade.dbdy); - ci.ydady = interpolate(ys, c->shade.a0, c->shade.dadx, c->shade.dady); - c->step_y = step_y__smooth; - } else { - ci.ydrdy = c->shade.r0; - ci.ydgdy = c->shade.g0; - ci.ydbdy = c->shade.b0; - ci.ydady = c->shade.a0; - // XXX: do only if needed, or make sure this is fast - c->packed = ggl_pack_color(c, c->state.buffers.color.format, - ci.ydrdy, ci.ydgdy, ci.ydbdy, ci.ydady); - c->packed8888 = ggl_pack_color(c, GGL_PIXEL_FORMAT_RGBA_8888, - ci.ydrdy, ci.ydgdy, ci.ydbdy, ci.ydady); - } - - // initialize the variables we need in the shader - generated_vars_t& gen = c->generated_vars; - gen.argb[GGLFormat::ALPHA].c = ci.ydady; - gen.argb[GGLFormat::ALPHA].dx = c->shade.dadx; - gen.argb[GGLFormat::RED ].c = ci.ydrdy; - gen.argb[GGLFormat::RED ].dx = c->shade.drdx; - gen.argb[GGLFormat::GREEN].c = ci.ydgdy; - gen.argb[GGLFormat::GREEN].dx = c->shade.dgdx; - gen.argb[GGLFormat::BLUE ].c = ci.ydbdy; - gen.argb[GGLFormat::BLUE ].dx = c->shade.dbdx; - gen.dzdx = c->shade.dzdx; - gen.f = ci.ydfdy; - gen.dfdx = c->shade.dfdx; - - if (enables & GGL_ENABLE_TMUS) { - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - texture_t& t = c->state.texture[i]; - if (!t.enable) continue; - - texture_iterators_t& ti = t.iterators; - if (t.s_coord == GGL_ONE_TO_ONE && t.t_coord == GGL_ONE_TO_ONE) { - // we need to set all of these to 0 because in some cases - // step_y__generic() or step_y__tmu() will be used and - // therefore will update dtdy, however, in 1:1 mode - // this is always done by the scanline rasterizer. - ti.dsdx = ti.dsdy = ti.dtdx = ti.dtdy = 0; - ti.ydsdy = t.shade.is0; - ti.ydtdy = t.shade.it0; - } else { - const int adjustSWrap = ((t.s_wrap==GGL_CLAMP)?0:16); - const int adjustTWrap = ((t.t_wrap==GGL_CLAMP)?0:16); - ti.sscale = t.shade.sscale + adjustSWrap; - ti.tscale = t.shade.tscale + adjustTWrap; - if (!(enables & GGL_ENABLE_W)) { - // S coordinate - const int32_t sscale = ti.sscale; - const int32_t sy = interpolate(ys, - t.shade.is0, t.shade.idsdx, t.shade.idsdy); - if (sscale>=0) { - ti.ydsdy= sy << sscale; - ti.dsdx = t.shade.idsdx << sscale; - ti.dsdy = t.shade.idsdy << sscale; - } else { - ti.ydsdy= sy >> -sscale; - ti.dsdx = t.shade.idsdx >> -sscale; - ti.dsdy = t.shade.idsdy >> -sscale; - } - // T coordinate - const int32_t tscale = ti.tscale; - const int32_t ty = interpolate(ys, - t.shade.it0, t.shade.idtdx, t.shade.idtdy); - if (tscale>=0) { - ti.ydtdy= ty << tscale; - ti.dtdx = t.shade.idtdx << tscale; - ti.dtdy = t.shade.idtdy << tscale; - } else { - ti.ydtdy= ty >> -tscale; - ti.dtdx = t.shade.idtdx >> -tscale; - ti.dtdy = t.shade.idtdy >> -tscale; - } - } - } - // mirror for generated code... - generated_tex_vars_t& gen = c->generated_vars.texture[i]; - gen.width = t.surface.width; - gen.height = t.surface.height; - gen.stride = t.surface.stride; - gen.data = uintptr_t(t.surface.data); - gen.dsdx = ti.dsdx; - gen.dtdx = ti.dtdx; - } - } - - // choose the y-stepper - c->step_y = step_y__nop; - if (enables & GGL_ENABLE_FOG) { - c->step_y = step_y__generic; - } else if (enables & GGL_ENABLE_TMUS) { - if (enables & GGL_ENABLE_SMOOTH) { - c->step_y = step_y__generic; - } else if (enables & GGL_ENABLE_W) { - c->step_y = step_y__w; - } else { - c->step_y = step_y__tmu; - } - } else { - if (enables & GGL_ENABLE_SMOOTH) { - c->step_y = step_y__smooth; - } - } - - // choose the rectangle blitter - c->rect = rect_generic; - if ((c->step_y == step_y__nop) && - (c->scanline == scanline_memcpy)) - { - c->rect = rect_memcpy; - } -} - -void init_y_packed(context_t* c, int32_t y0) -{ - uint8_t f = c->state.buffers.color.format; - c->packed = ggl_pack_color(c, f, - c->shade.r0, c->shade.g0, c->shade.b0, c->shade.a0); - c->packed8888 = ggl_pack_color(c, GGL_PIXEL_FORMAT_RGBA_8888, - c->shade.r0, c->shade.g0, c->shade.b0, c->shade.a0); - c->iterators.y = y0; - c->step_y = step_y__nop; - // choose the rectangle blitter - c->rect = rect_generic; - if (c->scanline == scanline_memcpy) { - c->rect = rect_memcpy; - } -} - -void init_y_noop(context_t* c, int32_t y0) -{ - c->iterators.y = y0; - c->step_y = step_y__nop; - // choose the rectangle blitter - c->rect = rect_generic; - if (c->scanline == scanline_memcpy) { - c->rect = rect_memcpy; - } -} - -void init_y_error(context_t* c, int32_t y0) -{ - // woooops, shoud never happen, - // fail gracefully (don't display anything) - init_y_noop(c, y0); - ALOGE("color-buffer has an invalid format!"); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void step_y__generic(context_t* c) -{ - const uint32_t enables = c->state.enables; - - // iterate... - iterators_t& ci = c->iterators; - ci.y += 1; - - if (enables & GGL_ENABLE_SMOOTH) { - ci.ydrdy += c->shade.drdy; - ci.ydgdy += c->shade.dgdy; - ci.ydbdy += c->shade.dbdy; - ci.ydady += c->shade.dady; - } - - const uint32_t mask = - GGL_ENABLE_DEPTH_TEST | - GGL_ENABLE_W | - GGL_ENABLE_FOG; - if (enables & mask) { - ci.ydzdy += c->shade.dzdy; - ci.ydwdy += c->shade.dwdy; - ci.ydfdy += c->shade.dfdy; - } - - if ((enables & GGL_ENABLE_TMUS) && (!(enables & GGL_ENABLE_W))) { - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - if (c->state.texture[i].enable) { - texture_iterators_t& ti = c->state.texture[i].iterators; - ti.ydsdy += ti.dsdy; - ti.ydtdy += ti.dtdy; - } - } - } -} - -void step_y__nop(context_t* c) -{ - c->iterators.y += 1; - c->iterators.ydzdy += c->shade.dzdy; -} - -void step_y__smooth(context_t* c) -{ - iterators_t& ci = c->iterators; - ci.y += 1; - ci.ydrdy += c->shade.drdy; - ci.ydgdy += c->shade.dgdy; - ci.ydbdy += c->shade.dbdy; - ci.ydady += c->shade.dady; - ci.ydzdy += c->shade.dzdy; -} - -void step_y__w(context_t* c) -{ - iterators_t& ci = c->iterators; - ci.y += 1; - ci.ydzdy += c->shade.dzdy; - ci.ydwdy += c->shade.dwdy; -} - -void step_y__tmu(context_t* c) -{ - iterators_t& ci = c->iterators; - ci.y += 1; - ci.ydzdy += c->shade.dzdy; - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - if (c->state.texture[i].enable) { - texture_iterators_t& ti = c->state.texture[i].iterators; - ti.ydsdy += ti.dsdy; - ti.ydtdy += ti.dtdy; - } - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -void scanline_perspective(context_t* c) -{ - struct { - union { - struct { - int32_t s, sq; - int32_t t, tq; - } sqtq; - struct { - int32_t v, q; - } st[2]; - }; - } tc[GGL_TEXTURE_UNIT_COUNT] __attribute__((aligned(16))); - - // XXX: we should have a special case when dwdx = 0 - - // 32 pixels spans works okay. 16 is a lot better, - // but hey, it's a software renderer... - const uint32_t SPAN_BITS = 5; - const uint32_t ys = c->iterators.y; - const uint32_t xs = c->iterators.xl; - const uint32_t x1 = c->iterators.xr; - const uint32_t xc = x1 - xs; - uint32_t remainder = xc & ((1<<SPAN_BITS)-1); - uint32_t numSpans = xc >> SPAN_BITS; - - const iterators_t& ci = c->iterators; - int32_t w0 = (xs * c->shade.dwdx) + ci.ydwdy; - int32_t q0 = gglRecipQ(w0, 30); - const int iwscale = 32 - gglClz(q0); - - const int32_t dwdx = c->shade.dwdx << SPAN_BITS; - int32_t xl = c->iterators.xl; - - // We process s & t with a loop to reduce the code size - // (and i-cache pressure). - - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - const texture_t& tmu = c->state.texture[i]; - if (!tmu.enable) continue; - int32_t s = tmu.shade.is0 + - (tmu.shade.idsdy * ys) + (tmu.shade.idsdx * xs) + - ((tmu.shade.idsdx + tmu.shade.idsdy)>>1); - int32_t t = tmu.shade.it0 + - (tmu.shade.idtdy * ys) + (tmu.shade.idtdx * xs) + - ((tmu.shade.idtdx + tmu.shade.idtdy)>>1); - tc[i].sqtq.s = s; - tc[i].sqtq.t = t; - tc[i].sqtq.sq = gglMulx(s, q0, iwscale); - tc[i].sqtq.tq = gglMulx(t, q0, iwscale); - } - - int32_t span = 0; - do { - int32_t w1; - if (ggl_likely(numSpans)) { - w1 = w0 + dwdx; - } else { - if (remainder) { - // finish off the scanline... - span = remainder; - w1 = (c->shade.dwdx * span) + w0; - } else { - break; - } - } - int32_t q1 = gglRecipQ(w1, 30); - for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { - texture_t& tmu = c->state.texture[i]; - if (!tmu.enable) continue; - texture_iterators_t& ti = tmu.iterators; - - for (int j=0 ; j<2 ; j++) { - int32_t v = tc[i].st[j].v; - if (span) v += (tmu.shade.st[j].dx)*span; - else v += (tmu.shade.st[j].dx)<<SPAN_BITS; - const int32_t v0 = tc[i].st[j].q; - const int32_t v1 = gglMulx(v, q1, iwscale); - int32_t dvdx = v1 - v0; - if (span) dvdx /= span; - else dvdx >>= SPAN_BITS; - tc[i].st[j].v = v; - tc[i].st[j].q = v1; - - const int scale = ti.st[j].scale + (iwscale - 30); - if (scale >= 0) { - ti.st[j].ydvdy = v0 << scale; - ti.st[j].dvdx = dvdx << scale; - } else { - ti.st[j].ydvdy = v0 >> -scale; - ti.st[j].dvdx = dvdx >> -scale; - } - } - generated_tex_vars_t& gen = c->generated_vars.texture[i]; - gen.dsdx = ti.st[0].dvdx; - gen.dtdx = ti.st[1].dvdx; - } - c->iterators.xl = xl; - c->iterators.xr = xl = xl + (span ? span : (1<<SPAN_BITS)); - w0 = w1; - q0 = q1; - c->span(c); - } while(numSpans--); -} - -void scanline_perspective_single(context_t* c) -{ - // 32 pixels spans works okay. 16 is a lot better, - // but hey, it's a software renderer... - const uint32_t SPAN_BITS = 5; - const uint32_t ys = c->iterators.y; - const uint32_t xs = c->iterators.xl; - const uint32_t x1 = c->iterators.xr; - const uint32_t xc = x1 - xs; - - const iterators_t& ci = c->iterators; - int32_t w = (xs * c->shade.dwdx) + ci.ydwdy; - int32_t iw = gglRecipQ(w, 30); - const int iwscale = 32 - gglClz(iw); - - const int i = 31 - gglClz(c->state.enabled_tmu); - generated_tex_vars_t& gen = c->generated_vars.texture[i]; - texture_t& tmu = c->state.texture[i]; - texture_iterators_t& ti = tmu.iterators; - const int sscale = ti.sscale + (iwscale - 30); - const int tscale = ti.tscale + (iwscale - 30); - int32_t s = tmu.shade.is0 + - (tmu.shade.idsdy * ys) + (tmu.shade.idsdx * xs) + - ((tmu.shade.idsdx + tmu.shade.idsdy)>>1); - int32_t t = tmu.shade.it0 + - (tmu.shade.idtdy * ys) + (tmu.shade.idtdx * xs) + - ((tmu.shade.idtdx + tmu.shade.idtdy)>>1); - int32_t s0 = gglMulx(s, iw, iwscale); - int32_t t0 = gglMulx(t, iw, iwscale); - int32_t xl = c->iterators.xl; - - int32_t sq, tq, dsdx, dtdx; - int32_t premainder = xc & ((1<<SPAN_BITS)-1); - uint32_t numSpans = xc >> SPAN_BITS; - if (c->shade.dwdx == 0) { - // XXX: we could choose to do this if the error is small enough - numSpans = 0; - premainder = xc; - goto no_perspective; - } - - if (premainder) { - w += c->shade.dwdx * premainder; - iw = gglRecipQ(w, 30); -no_perspective: - s += tmu.shade.idsdx * premainder; - t += tmu.shade.idtdx * premainder; - sq = gglMulx(s, iw, iwscale); - tq = gglMulx(t, iw, iwscale); - dsdx = (sq - s0) / premainder; - dtdx = (tq - t0) / premainder; - c->iterators.xl = xl; - c->iterators.xr = xl = xl + premainder; - goto finish; - } - - while (numSpans--) { - w += c->shade.dwdx << SPAN_BITS; - s += tmu.shade.idsdx << SPAN_BITS; - t += tmu.shade.idtdx << SPAN_BITS; - iw = gglRecipQ(w, 30); - sq = gglMulx(s, iw, iwscale); - tq = gglMulx(t, iw, iwscale); - dsdx = (sq - s0) >> SPAN_BITS; - dtdx = (tq - t0) >> SPAN_BITS; - c->iterators.xl = xl; - c->iterators.xr = xl = xl + (1<<SPAN_BITS); -finish: - if (sscale >= 0) { - ti.ydsdy = s0 << sscale; - ti.dsdx = dsdx << sscale; - } else { - ti.ydsdy = s0 >>-sscale; - ti.dsdx = dsdx >>-sscale; - } - if (tscale >= 0) { - ti.ydtdy = t0 << tscale; - ti.dtdx = dtdx << tscale; - } else { - ti.ydtdy = t0 >>-tscale; - ti.dtdx = dtdx >>-tscale; - } - s0 = sq; - t0 = tq; - gen.dsdx = ti.dsdx; - gen.dtdx = ti.dtdx; - c->span(c); - } -} - -// ---------------------------------------------------------------------------- - -void scanline_col32cb16blend(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - union { - uint16_t* dst; - uint32_t* dst32; - }; - dst = reinterpret_cast<uint16_t*>(cb->data) + (x+(cb->stride*y)); - -#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__arm__)) -#if defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN - scanline_col32cb16blend_neon(dst, &(c->packed8888), ct); -#else // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN - scanline_col32cb16blend_arm(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); -#endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN -#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__)) - scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); -#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__mips__) && defined(__LP64__))) - scanline_col32cb16blend_mips64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); -#else - uint32_t s = GGL_RGBA_TO_HOST(c->packed8888); - int sA = (s>>24); - int f = 0x100 - (sA + (sA>>7)); - while (ct--) { - uint16_t d = *dst; - int dR = (d>>11)&0x1f; - int dG = (d>>5)&0x3f; - int dB = (d)&0x1f; - int sR = (s >> ( 3))&0x1F; - int sG = (s >> ( 8+2))&0x3F; - int sB = (s >> (16+3))&0x1F; - sR += (f*dR)>>8; - sG += (f*dG)>>8; - sB += (f*dB)>>8; - *dst++ = uint16_t((sR<<11)|(sG<<5)|sB); - } -#endif - -} - -void scanline_t32cb16(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - union { - uint16_t* dst; - uint32_t* dst32; - }; - dst = reinterpret_cast<uint16_t*>(cb->data) + (x+(cb->stride*y)); - - surface_t* tex = &(c->state.texture[0].surface); - const int32_t u = (c->state.texture[0].shade.is0>>16) + x; - const int32_t v = (c->state.texture[0].shade.it0>>16) + y; - uint32_t *src = reinterpret_cast<uint32_t*>(tex->data)+(u+(tex->stride*v)); - uint32_t s, d; - - if (ct==1 || uintptr_t(dst)&2) { -last_one: - s = GGL_RGBA_TO_HOST( *src++ ); - *dst++ = convertAbgr8888ToRgb565(s); - ct--; - } - - while (ct >= 2) { -#if BYTE_ORDER == BIG_ENDIAN - s = GGL_RGBA_TO_HOST( *src++ ); - d = convertAbgr8888ToRgb565_hi16(s); - - s = GGL_RGBA_TO_HOST( *src++ ); - d |= convertAbgr8888ToRgb565(s); -#else - s = GGL_RGBA_TO_HOST( *src++ ); - d = convertAbgr8888ToRgb565(s); - - s = GGL_RGBA_TO_HOST( *src++ ); - d |= convertAbgr8888ToRgb565(s) << 16; -#endif - *dst32++ = d; - ct -= 2; - } - - if (ct > 0) { - goto last_one; - } -} - -void scanline_t32cb16blend(context_t* c) -{ -#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || defined(__aarch64__) || \ - (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))))) - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - uint16_t* dst = reinterpret_cast<uint16_t*>(cb->data) + (x+(cb->stride*y)); - - surface_t* tex = &(c->state.texture[0].surface); - const int32_t u = (c->state.texture[0].shade.is0>>16) + x; - const int32_t v = (c->state.texture[0].shade.it0>>16) + y; - uint32_t *src = reinterpret_cast<uint32_t*>(tex->data)+(u+(tex->stride*v)); - -#ifdef __arm__ - scanline_t32cb16blend_arm(dst, src, ct); -#elif defined(__aarch64__) - scanline_t32cb16blend_arm64(dst, src, ct); -#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 - scanline_t32cb16blend_mips(dst, src, ct); -#elif defined(__mips__) && defined(__LP64__) - scanline_t32cb16blend_mips64(dst, src, ct); -#endif -#else - dst_iterator16 di(c); - horz_iterator32 hi(c); - blender_32to16 bl(c); - while (di.count--) { - uint32_t s = hi.get_pixel32(); - bl.write(s, di.dst); - di.dst++; - } -#endif -} - -void scanline_t32cb16blend_srca(context_t* c) -{ - dst_iterator16 di(c); - horz_iterator32 hi(c); - blender_32to16_srcA blender(c); - - while (di.count--) { - uint32_t s = hi.get_pixel32(); - blender.write(s,di.dst); - di.dst++; - } -} - -void scanline_t16cb16blend_clamp_mod(context_t* c) -{ - const int a = c->iterators.ydady >> (GGL_COLOR_BITS-8); - if (a == 0) { - return; - } - - if (a == 255) { - scanline_t16cb16_clamp(c); - return; - } - - dst_iterator16 di(c); - blender_16to16_modulate blender(c); - clamp_iterator ci(c); - - while (di.count--) { - uint16_t s = ci.get_pixel16(); - blender.write(s, di.dst); - di.dst++; - } -} - -void scanline_memcpy(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - const GGLFormat* fp = &(c->formats[cb->format]); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + - (x + (cb->stride * y)) * fp->size; - - surface_t* tex = &(c->state.texture[0].surface); - const int32_t u = (c->state.texture[0].shade.is0>>16) + x; - const int32_t v = (c->state.texture[0].shade.it0>>16) + y; - uint8_t *src = reinterpret_cast<uint8_t*>(tex->data) + - (u + (tex->stride * v)) * fp->size; - - const size_t size = ct * fp->size; - memcpy(dst, src, size); -} - -void scanline_memset8(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + (x+(cb->stride*y)); - uint32_t packed = c->packed; - memset(dst, packed, ct); -} - -void scanline_memset16(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - uint16_t* dst = reinterpret_cast<uint16_t*>(cb->data) + (x+(cb->stride*y)); - uint32_t packed = c->packed; - android_memset16(dst, packed, ct*2); -} - -void scanline_memset32(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - uint32_t* dst = reinterpret_cast<uint32_t*>(cb->data) + (x+(cb->stride*y)); - uint32_t packed = GGL_HOST_TO_RGBA(c->packed); - android_memset32(dst, packed, ct*4); -} - -void scanline_clear(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - const GGLFormat* fp = &(c->formats[cb->format]); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + - (x + (cb->stride * y)) * fp->size; - const size_t size = ct * fp->size; - memset(dst, 0, size); -} - -void scanline_set(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - const GGLFormat* fp = &(c->formats[cb->format]); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + - (x + (cb->stride * y)) * fp->size; - const size_t size = ct * fp->size; - memset(dst, 0xFF, size); -} - -void scanline_noop(context_t* /*c*/) -{ -} - -void rect_generic(context_t* c, size_t yc) -{ - do { - c->scanline(c); - c->step_y(c); - } while (--yc); -} - -void rect_memcpy(context_t* c, size_t yc) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - const GGLFormat* fp = &(c->formats[cb->format]); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + - (x + (cb->stride * y)) * fp->size; - - surface_t* tex = &(c->state.texture[0].surface); - const int32_t u = (c->state.texture[0].shade.is0>>16) + x; - const int32_t v = (c->state.texture[0].shade.it0>>16) + y; - uint8_t *src = reinterpret_cast<uint8_t*>(tex->data) + - (u + (tex->stride * v)) * fp->size; - - if (cb->stride == tex->stride && ct == size_t(cb->stride)) { - memcpy(dst, src, ct * fp->size * yc); - } else { - const size_t size = ct * fp->size; - const size_t dbpr = cb->stride * fp->size; - const size_t sbpr = tex->stride * fp->size; - do { - memcpy(dst, src, size); - dst += dbpr; - src += sbpr; - } while (--yc); - } -} -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libpixelflinger/scanline.h b/libpixelflinger/scanline.h deleted file mode 100644 index b6f4d3746..000000000 --- a/libpixelflinger/scanline.h +++ /dev/null @@ -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 diff --git a/libpixelflinger/t32cb16blend.S b/libpixelflinger/t32cb16blend.S deleted file mode 100644 index 5e4995a20..000000000 --- a/libpixelflinger/t32cb16blend.S +++ /dev/null @@ -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 diff --git a/libpixelflinger/tests/Android.bp b/libpixelflinger/tests/Android.bp deleted file mode 100644 index e20dd931a..000000000 --- a/libpixelflinger/tests/Android.bp +++ /dev/null @@ -1,17 +0,0 @@ -cc_defaults { - name: "pixelflinger-tests", - - cflags: [ - "-Wall", - "-Werror", - ], - - header_libs: ["libpixelflinger_internal"], - static_libs: [ - "libbase", - "libcutils", - "liblog", - "libpixelflinger", - "libutils", - ], -} diff --git a/libpixelflinger/tests/arch-arm64/Android.bp b/libpixelflinger/tests/arch-arm64/Android.bp deleted file mode 100644 index 2f5586aa9..000000000 --- a/libpixelflinger/tests/arch-arm64/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -cc_defaults { - name: "pixelflinger-tests-arm64", - defaults: ["pixelflinger-tests"], - - enabled: false, - arch: { - arm64: { - enabled: true, - }, - }, -} diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.bp b/libpixelflinger/tests/arch-arm64/assembler/Android.bp deleted file mode 100644 index 003f48576..000000000 --- a/libpixelflinger/tests/arch-arm64/assembler/Android.bp +++ /dev/null @@ -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", - ], -} diff --git a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp deleted file mode 100644 index 63642c4b1..000000000 --- a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S b/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S deleted file mode 100644 index 3f900f854..000000000 --- a/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S +++ /dev/null @@ -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 - diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp deleted file mode 100644 index e640aeb74..000000000 --- a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp +++ /dev/null @@ -1,6 +0,0 @@ -cc_test { - name: "test-pixelflinger-arm64-col32cb16blend", - defaults: ["pixelflinger-tests-arm64"], - - srcs: ["col32cb16blend_test.c"], -} diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-arm64/col32cb16blend/col32cb16blend_test.c deleted file mode 100644 index c6a301723..000000000 --- a/libpixelflinger/tests/arch-arm64/col32cb16blend/col32cb16blend_test.c +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.bp b/libpixelflinger/tests/arch-arm64/disassembler/Android.bp deleted file mode 100644 index 38dc99a5b..000000000 --- a/libpixelflinger/tests/arch-arm64/disassembler/Android.bp +++ /dev/null @@ -1,6 +0,0 @@ -cc_test { - name: "test-pixelflinger-arm64-disassembler-test", - defaults: ["pixelflinger-tests-arm64"], - - srcs: ["arm64_diassembler_test.cpp"], -} diff --git a/libpixelflinger/tests/arch-arm64/disassembler/arm64_diassembler_test.cpp b/libpixelflinger/tests/arch-arm64/disassembler/arm64_diassembler_test.cpp deleted file mode 100644 index af3183b1b..000000000 --- a/libpixelflinger/tests/arch-arm64/disassembler/arm64_diassembler_test.cpp +++ /dev/null @@ -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; - } -} diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp deleted file mode 100644 index 9d060d136..000000000 --- a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp +++ /dev/null @@ -1,6 +0,0 @@ -cc_test { - name: "test-pixelflinger-arm64-t32cb16blend", - defaults: ["pixelflinger-tests-arm64"], - - srcs: ["t32cb16blend_test.c"], -} diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/t32cb16blend_test.c b/libpixelflinger/tests/arch-arm64/t32cb16blend/t32cb16blend_test.c deleted file mode 100644 index afb36fb47..000000000 --- a/libpixelflinger/tests/arch-arm64/t32cb16blend/t32cb16blend_test.c +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/tests/codegen/Android.bp b/libpixelflinger/tests/codegen/Android.bp deleted file mode 100644 index 7e4bcfb3c..000000000 --- a/libpixelflinger/tests/codegen/Android.bp +++ /dev/null @@ -1,12 +0,0 @@ -cc_test { - name: "test-opengl-codegen", - defaults: ["pixelflinger-tests"], - - srcs: ["codegen.cpp"], - - arch: { - arm: { - instruction_set: "arm", - }, - }, -} diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp deleted file mode 100644 index dce4ed72c..000000000 --- a/libpixelflinger/tests/codegen/codegen.cpp +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/tests/gglmul/Android.bp b/libpixelflinger/tests/gglmul/Android.bp deleted file mode 100644 index 288337b71..000000000 --- a/libpixelflinger/tests/gglmul/Android.bp +++ /dev/null @@ -1,12 +0,0 @@ -cc_test { - name: "test-pixelflinger-gglmul", - - srcs: ["gglmul_test.cpp"], - - header_libs: ["libpixelflinger_internal"], - - cflags: [ - "-Wall", - "-Werror", - ], -} diff --git a/libpixelflinger/tests/gglmul/gglmul_test.cpp b/libpixelflinger/tests/gglmul/gglmul_test.cpp deleted file mode 100644 index 5d460d622..000000000 --- a/libpixelflinger/tests/gglmul/gglmul_test.cpp +++ /dev/null @@ -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; -} diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp deleted file mode 100644 index 06ad2373c..000000000 --- a/libpixelflinger/trap.cpp +++ /dev/null @@ -1,1173 +0,0 @@ -/* libs/pixelflinger/trap.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-trap" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -#include <cutils/memory.h> -#include <log/log.h> - -#include "trap.h" -#include "picker.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -// enable to see triangles edges -#define DEBUG_TRANGLES 0 - -// ---------------------------------------------------------------------------- - -static void pointx_validate(void *con, const GGLcoord* c, GGLcoord r); -static void pointx(void *con, const GGLcoord* c, GGLcoord r); -static void aa_pointx(void *con, const GGLcoord* c, GGLcoord r); -static void aa_nice_pointx(void *con, const GGLcoord* c, GGLcoord r); - -static void linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w); -static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w); -static void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w); - -static void recti_validate(void* c, GGLint l, GGLint t, GGLint r, GGLint b); -static void recti(void* c, GGLint l, GGLint t, GGLint r, GGLint b); - -static void trianglex_validate(void*, - const GGLcoord*, const GGLcoord*, const GGLcoord*); -static void trianglex_small(void*, - const GGLcoord*, const GGLcoord*, const GGLcoord*); -static void trianglex_big(void*, - const GGLcoord*, const GGLcoord*, const GGLcoord*); -static void aa_trianglex(void*, - const GGLcoord*, const GGLcoord*, const GGLcoord*); -static void trianglex_debug(void* con, - const GGLcoord*, const GGLcoord*, const GGLcoord*); - -static void aapolyx(void* con, - const GGLcoord* pts, int count); - -static inline int min(int a, int b) CONST; -static inline int max(int a, int b) CONST; -static inline int min(int a, int b, int c) CONST; -static inline int max(int a, int b, int c) CONST; - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Tools -#endif - -inline int min(int a, int b) { - return a<b ? a : b; -} -inline int max(int a, int b) { - return a<b ? b : a; -} -inline int min(int a, int b, int c) { - return min(a,min(b,c)); -} -inline int max(int a, int b, int c) { - return max(a,max(b,c)); -} - -template <typename T> -static inline void swap(T& a, T& b) { - T t(a); - a = b; - b = t; -} - -static void -triangle_dump_points( const GGLcoord* v0, - const GGLcoord* v1, - const GGLcoord* v2 ) -{ - float tri = 1.0f / TRI_ONE; - ALOGD(" P0=(%.3f, %.3f) [%08x, %08x]\n" - " P1=(%.3f, %.3f) [%08x, %08x]\n" - " P2=(%.3f, %.3f) [%08x, %08x]\n", - v0[0]*tri, v0[1]*tri, v0[0], v0[1], - v1[0]*tri, v1[1]*tri, v1[0], v1[1], - v2[0]*tri, v2[1]*tri, v2[0], v2[1] ); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Misc -#endif - -void ggl_init_trap(context_t* c) -{ - ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE|GGL_TMU_STATE|GGL_CB_STATE); -} - -void ggl_state_changed(context_t* c, int flags) -{ - if (ggl_likely(!c->dirty)) { - c->procs.pointx = pointx_validate; - c->procs.linex = linex_validate; - c->procs.recti = recti_validate; - c->procs.trianglex = trianglex_validate; - } - c->dirty |= uint32_t(flags); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Point -#endif - -void pointx_validate(void *con, const GGLcoord* v, GGLcoord rad) -{ - GGL_CONTEXT(c, con); - ggl_pick(c); - if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { - if (c->state.enables & GGL_ENABLE_POINT_AA_NICE) { - c->procs.pointx = aa_nice_pointx; - } else { - c->procs.pointx = aa_pointx; - } - } else { - c->procs.pointx = pointx; - } - c->procs.pointx(con, v, rad); -} - -void pointx(void *con, const GGLcoord* v, GGLcoord rad) -{ - GGL_CONTEXT(c, con); - GGLcoord halfSize = TRI_ROUND(rad) >> 1; - if (halfSize == 0) - halfSize = TRI_HALF; - GGLcoord xc = v[0]; - GGLcoord yc = v[1]; - if (halfSize & TRI_HALF) { // size odd - xc = TRI_FLOOR(xc) + TRI_HALF; - yc = TRI_FLOOR(yc) + TRI_HALF; - } else { // size even - xc = TRI_ROUND(xc); - yc = TRI_ROUND(yc); - } - GGLint l = (xc - halfSize) >> TRI_FRACTION_BITS; - GGLint t = (yc - halfSize) >> TRI_FRACTION_BITS; - GGLint r = (xc + halfSize) >> TRI_FRACTION_BITS; - GGLint b = (yc + halfSize) >> TRI_FRACTION_BITS; - recti(c, l, t, r, b); -} - -// This way of computing the coverage factor, is more accurate and gives -// better results for small circles, but it is also a lot slower. -// Here we use super-sampling. -static int32_t coverageNice(GGLcoord x, GGLcoord y, - GGLcoord rmin, GGLcoord rmax, GGLcoord rr) -{ - const GGLcoord d2 = x*x + y*y; - if (d2 >= rmax) return 0; - if (d2 < rmin) return 0x7FFF; - - const int kSamples = 4; - const int kInc = 4; // 1/4 = 0.25 - const int kCoverageUnit = 1; // 1/(4^2) = 0.0625 - const GGLcoord kCoordOffset = -6; // -0.375 - - int hits = 0; - int x_sample = x + kCoordOffset; - for (int i=0 ; i<kSamples ; i++, x_sample += kInc) { - const int xval = rr - (x_sample * x_sample); - int y_sample = y + kCoordOffset; - for (int j=0 ; j<kSamples ; j++, y_sample += kInc) { - if (xval - (y_sample * y_sample) > 0) - hits += kCoverageUnit; - } - } - return min(0x7FFF, hits << (15 - kSamples)); -} - - -void aa_nice_pointx(void *con, const GGLcoord* v, GGLcoord size) -{ - GGL_CONTEXT(c, con); - - GGLcoord rad = ((size + 1)>>1); - GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS; - GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS; - GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; - GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; - GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF; - GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF; - - // scissor... - if (l < GGLint(c->state.scissor.left)) { - xstart += TRI_FROM_INT(c->state.scissor.left-l); - l = GGLint(c->state.scissor.left); - } - if (t < GGLint(c->state.scissor.top)) { - ystart += TRI_FROM_INT(c->state.scissor.top-t); - t = GGLint(c->state.scissor.top); - } - if (r > GGLint(c->state.scissor.right)) { - r = GGLint(c->state.scissor.right); - } - if (b > GGLint(c->state.scissor.bottom)) { - b = GGLint(c->state.scissor.bottom); - } - - int xc = r - l; - int yc = b - t; - if (xc>0 && yc>0) { - int16_t* covPtr = c->state.buffers.coverage; - const int32_t sqr2Over2 = 0xC; // rounded up - GGLcoord rr = rad*rad; - GGLcoord rmin = (rad - sqr2Over2)*(rad - sqr2Over2); - GGLcoord rmax = (rad + sqr2Over2)*(rad + sqr2Over2); - GGLcoord y = ystart; - c->iterators.xl = l; - c->iterators.xr = r; - c->init_y(c, t); - do { - // compute coverage factors for each pixel - GGLcoord x = xstart; - for (int i=l ; i<r ; i++) { - covPtr[i] = coverageNice(x, y, rmin, rmax, rr); - x += TRI_ONE; - } - y += TRI_ONE; - c->scanline(c); - c->step_y(c); - } while (--yc); - } -} - -// This is a cheap way of computing the coverage factor for a circle. -// We just lerp between the circles of radii r-sqrt(2)/2 and r+sqrt(2)/2 -static inline int32_t coverageFast(GGLcoord x, GGLcoord y, - GGLcoord rmin, GGLcoord rmax, GGLcoord scale) -{ - const GGLcoord d2 = x*x + y*y; - if (d2 >= rmax) return 0; - if (d2 < rmin) return 0x7FFF; - return 0x7FFF - (d2-rmin)*scale; -} - -void aa_pointx(void *con, const GGLcoord* v, GGLcoord size) -{ - GGL_CONTEXT(c, con); - - GGLcoord rad = ((size + 1)>>1); - GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS; - GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS; - GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; - GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; - GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF; - GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF; - - // scissor... - if (l < GGLint(c->state.scissor.left)) { - xstart += TRI_FROM_INT(c->state.scissor.left-l); - l = GGLint(c->state.scissor.left); - } - if (t < GGLint(c->state.scissor.top)) { - ystart += TRI_FROM_INT(c->state.scissor.top-t); - t = GGLint(c->state.scissor.top); - } - if (r > GGLint(c->state.scissor.right)) { - r = GGLint(c->state.scissor.right); - } - if (b > GGLint(c->state.scissor.bottom)) { - b = GGLint(c->state.scissor.bottom); - } - - int xc = r - l; - int yc = b - t; - if (xc>0 && yc>0) { - int16_t* covPtr = c->state.buffers.coverage; - rad <<= 4; - const int32_t sqr2Over2 = 0xB5; // fixed-point 24.8 - GGLcoord rmin = rad - sqr2Over2; - GGLcoord rmax = rad + sqr2Over2; - GGLcoord scale; - rmin *= rmin; - rmax *= rmax; - scale = 0x800000 / (rmax - rmin); - rmin >>= 8; - rmax >>= 8; - - GGLcoord y = ystart; - c->iterators.xl = l; - c->iterators.xr = r; - c->init_y(c, t); - - do { - // compute coverage factors for each pixel - GGLcoord x = xstart; - for (int i=l ; i<r ; i++) { - covPtr[i] = coverageFast(x, y, rmin, rmax, scale); - x += TRI_ONE; - } - y += TRI_ONE; - c->scanline(c); - c->step_y(c); - } while (--yc); - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Line -#endif - -void linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w) -{ - GGL_CONTEXT(c, con); - ggl_pick(c); - if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { - c->procs.linex = aa_linex; - } else { - c->procs.linex = linex; - } - c->procs.linex(con, v0, v1, w); -} - -static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width) -{ - GGLcoord v[4][2]; - v[0][0] = v0[0]; v[0][1] = v0[1]; - v[1][0] = v1[0]; v[1][1] = v1[1]; - v0 = v[0]; - v1 = v[1]; - const GGLcoord dx = abs(v0[0] - v1[0]); - const GGLcoord dy = abs(v0[1] - v1[1]); - GGLcoord nx, ny; - nx = ny = 0; - - GGLcoord halfWidth = TRI_ROUND(width) >> 1; - if (halfWidth == 0) - halfWidth = TRI_HALF; - - ((dx > dy) ? ny : nx) = halfWidth; - v[2][0] = v1[0]; v[2][1] = v1[1]; - v[3][0] = v0[0]; v[3][1] = v0[1]; - v[0][0] += nx; v[0][1] += ny; - v[1][0] += nx; v[1][1] += ny; - v[2][0] -= nx; v[2][1] -= ny; - v[3][0] -= nx; v[3][1] -= ny; - trianglex_big(con, v[0], v[1], v[2]); - trianglex_big(con, v[0], v[2], v[3]); -} - -static void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width) -{ - GGLcoord v[4][2]; - v[0][0] = v0[0]; v[0][1] = v0[1]; - v[1][0] = v1[0]; v[1][1] = v1[1]; - v0 = v[0]; - v1 = v[1]; - - const GGLcoord dx = v0[0] - v1[0]; - const GGLcoord dy = v0[1] - v1[1]; - GGLcoord nx = -dy; - GGLcoord ny = dx; - - // generally, this will be well below 1.0 - const GGLfixed norm = gglMulx(width, gglSqrtRecipx(nx*nx+ny*ny), 4); - nx = gglMulx(nx, norm, 21); - ny = gglMulx(ny, norm, 21); - - v[2][0] = v1[0]; v[2][1] = v1[1]; - v[3][0] = v0[0]; v[3][1] = v0[1]; - v[0][0] += nx; v[0][1] += ny; - v[1][0] += nx; v[1][1] += ny; - v[2][0] -= nx; v[2][1] -= ny; - v[3][0] -= nx; v[3][1] -= ny; - aapolyx(con, v[0], 4); -} - - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Rect -#endif - -void recti_validate(void *con, GGLint l, GGLint t, GGLint r, GGLint b) -{ - GGL_CONTEXT(c, con); - ggl_pick(c); - c->procs.recti = recti; - c->procs.recti(con, l, t, r, b); -} - -void recti(void* con, GGLint l, GGLint t, GGLint r, GGLint b) -{ - GGL_CONTEXT(c, con); - - // scissor... - if (l < GGLint(c->state.scissor.left)) - l = GGLint(c->state.scissor.left); - if (t < GGLint(c->state.scissor.top)) - t = GGLint(c->state.scissor.top); - if (r > GGLint(c->state.scissor.right)) - r = GGLint(c->state.scissor.right); - if (b > GGLint(c->state.scissor.bottom)) - b = GGLint(c->state.scissor.bottom); - - int xc = r - l; - int yc = b - t; - if (xc>0 && yc>0) { - c->iterators.xl = l; - c->iterators.xr = r; - c->init_y(c, t); - c->rect(c, yc); - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Triangle / Debugging -#endif - -static void scanline_set(context_t* c) -{ - int32_t x = c->iterators.xl; - size_t ct = c->iterators.xr - x; - int32_t y = c->iterators.y; - surface_t* cb = &(c->state.buffers.color); - const GGLFormat* fp = &(c->formats[cb->format]); - uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) + - (x + (cb->stride * y)) * fp->size; - const size_t size = ct * fp->size; - memset(dst, 0xFF, size); -} - -static void trianglex_debug(void* con, - const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2) -{ - GGL_CONTEXT(c, con); - if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { - aa_trianglex(con,v0,v1,v2); - } else { - trianglex_big(con,v0,v1,v2); - } - void (*save_scanline)(context_t*) = c->scanline; - c->scanline = scanline_set; - linex(con, v0, v1, TRI_ONE); - linex(con, v1, v2, TRI_ONE); - linex(con, v2, v0, TRI_ONE); - c->scanline = save_scanline; -} - -static void trianglex_xor(void* con, - const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2) -{ - trianglex_big(con,v0,v1,v2); - trianglex_small(con,v0,v1,v2); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Triangle -#endif - -void trianglex_validate(void *con, - const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2) -{ - GGL_CONTEXT(c, con); - ggl_pick(c); - if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { - c->procs.trianglex = DEBUG_TRANGLES ? trianglex_debug : aa_trianglex; - } else { - c->procs.trianglex = DEBUG_TRANGLES ? trianglex_debug : trianglex_big; - } - c->procs.trianglex(con, v0, v1, v2); -} - -// ---------------------------------------------------------------------------- - -void trianglex_small(void* con, - const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2) -{ - GGL_CONTEXT(c, con); - - // vertices are in 28.4 fixed point, which allows - // us to use 32 bits multiplies below. - int32_t x0 = v0[0]; - int32_t y0 = v0[1]; - int32_t x1 = v1[0]; - int32_t y1 = v1[1]; - int32_t x2 = v2[0]; - int32_t y2 = v2[1]; - - int32_t dx01 = x0 - x1; - int32_t dy20 = y2 - y0; - int32_t dy01 = y0 - y1; - int32_t dx20 = x2 - x0; - - // The code below works only with CCW triangles - // so if we get a CW triangle, we need to swap two of its vertices - if (dx01*dy20 < dy01*dx20) { - swap(x0, x1); - swap(y0, y1); - dx01 = x0 - x1; - dy01 = y0 - y1; - dx20 = x2 - x0; - dy20 = y2 - y0; - } - int32_t dx12 = x1 - x2; - int32_t dy12 = y1 - y2; - - // bounding box & scissor - const int32_t bminx = TRI_FLOOR(min(x0, x1, x2)) >> TRI_FRACTION_BITS; - const int32_t bminy = TRI_FLOOR(min(y0, y1, y2)) >> TRI_FRACTION_BITS; - const int32_t bmaxx = TRI_CEIL( max(x0, x1, x2)) >> TRI_FRACTION_BITS; - const int32_t bmaxy = TRI_CEIL( max(y0, y1, y2)) >> TRI_FRACTION_BITS; - const int32_t minx = max(bminx, c->state.scissor.left); - const int32_t miny = max(bminy, c->state.scissor.top); - const int32_t maxx = min(bmaxx, c->state.scissor.right); - const int32_t maxy = min(bmaxy, c->state.scissor.bottom); - if ((minx >= maxx) || (miny >= maxy)) - return; // too small or clipped out... - - // step equations to the bounding box and snap to pixel center - const int32_t my = (miny << TRI_FRACTION_BITS) + TRI_HALF; - const int32_t mx = (minx << TRI_FRACTION_BITS) + TRI_HALF; - int32_t ey0 = dy01 * (x0 - mx) - dx01 * (y0 - my); - int32_t ey1 = dy12 * (x1 - mx) - dx12 * (y1 - my); - int32_t ey2 = dy20 * (x2 - mx) - dx20 * (y2 - my); - - // right-exclusive fill rule, to avoid rare cases - // of over drawing - if (dy01<0 || (dy01 == 0 && dx01>0)) ey0++; - if (dy12<0 || (dy12 == 0 && dx12>0)) ey1++; - if (dy20<0 || (dy20 == 0 && dx20>0)) ey2++; - - c->init_y(c, miny); - for (int32_t y = miny; y < maxy; y++) { - int32_t ex0 = ey0; - int32_t ex1 = ey1; - int32_t ex2 = ey2; - int32_t xl, xr; - for (xl=minx ; xl<maxx ; xl++) { - if (ex0>0 && ex1>0 && ex2>0) - break; // all strictly positive - ex0 -= dy01 << TRI_FRACTION_BITS; - ex1 -= dy12 << TRI_FRACTION_BITS; - ex2 -= dy20 << TRI_FRACTION_BITS; - } - xr = xl; - for ( ; xr<maxx ; xr++) { - if (!(ex0>0 && ex1>0 && ex2>0)) - break; // not all strictly positive - ex0 -= dy01 << TRI_FRACTION_BITS; - ex1 -= dy12 << TRI_FRACTION_BITS; - ex2 -= dy20 << TRI_FRACTION_BITS; - } - - if (xl < xr) { - c->iterators.xl = xl; - c->iterators.xr = xr; - c->scanline(c); - } - c->step_y(c); - - ey0 += dx01 << TRI_FRACTION_BITS; - ey1 += dx12 << TRI_FRACTION_BITS; - ey2 += dx20 << TRI_FRACTION_BITS; - } -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -// the following routine fills a triangle via edge stepping, which -// unfortunately requires divisions in the setup phase to get right, -// it should probably only be used for relatively large trianges - - -// x = y*DX/DY (ou DX and DY are constants, DY > 0, et y >= 0) -// -// for an equation of the type: -// x' = y*K/2^p (with K and p constants "carefully chosen") -// -// We can now do a DDA without precision loss. We define 'e' by: -// x' - x = y*(DX/DY - K/2^p) = y*e -// -// If we choose K = round(DX*2^p/DY) then, -// abs(e) <= 1/2^(p+1) by construction -// -// therefore abs(x'-x) = y*abs(e) <= y/2^(p+1) <= DY/2^(p+1) <= DMAX/2^(p+1) -// -// which means that if DMAX <= 2^p, therefore abs(x-x') <= 1/2, including -// at the last line. In fact, it's even a strict inequality except in one -// extrem case (DY == DMAX et e = +/- 1/2) -// -// Applying that to our coordinates, we need 2^p >= 4096*16 = 65536 -// so p = 16 is enough, we're so lucky! - -const int TRI_ITERATORS_BITS = 16; - -struct Edge -{ - int32_t x; // edge position in 16.16 coordinates - int32_t x_incr; // on each step, increment x by that amount - int32_t y_top; // starting scanline, 16.4 format - int32_t y_bot; -}; - -static void -edge_dump( Edge* edge ) -{ - ALOGI( " top=%d (%.3f) bot=%d (%.3f) x=%d (%.3f) ix=%d (%.3f)", - edge->y_top, edge->y_top/float(TRI_ONE), - edge->y_bot, edge->y_bot/float(TRI_ONE), - edge->x, edge->x/float(FIXED_ONE), - edge->x_incr, edge->x_incr/float(FIXED_ONE) ); -} - -static void -triangle_dump_edges( Edge* edges, - int count ) -{ - ALOGI( "%d edge%s:\n", count, count == 1 ? "" : "s" ); - for ( ; count > 0; count--, edges++ ) - edge_dump( edges ); -} - -// the following function sets up an edge, it assumes -// that ymin and ymax are in already in the 'reduced' -// format -static __attribute__((noinline)) -void edge_setup( - Edge* edges, - int* pcount, - const GGLcoord* p1, - const GGLcoord* p2, - int32_t ymin, - int32_t ymax ) -{ - const GGLfixed* top = p1; - const GGLfixed* bot = p2; - Edge* edge = edges + *pcount; - - if (top[1] > bot[1]) { - swap(top, bot); - } - - int y1 = top[1] | 1; - int y2 = bot[1] | 1; - int dy = y2 - y1; - - if ( dy == 0 || y1 > ymax || y2 < ymin ) - return; - - if ( y1 > ymin ) - ymin = TRI_SNAP_NEXT_HALF(y1); - - if ( y2 < ymax ) - ymax = TRI_SNAP_PREV_HALF(y2); - - if ( ymin > ymax ) // when the edge doesn't cross any scanline - return; - - const int x1 = top[0]; - const int dx = bot[0] - x1; - const int shift = TRI_ITERATORS_BITS - TRI_FRACTION_BITS; - - // setup edge fields - // We add 0.5 to edge->x here because it simplifies the rounding - // in triangle_sweep_edges() -- this doesn't change the ordering of 'x' - edge->x = (x1 << shift) + (1LU << (TRI_ITERATORS_BITS-1)); - edge->x_incr = 0; - edge->y_top = ymin; - edge->y_bot = ymax; - - if (ggl_likely(ymin <= ymax && dx)) { - edge->x_incr = gglDivQ16(dx, dy); - } - if (ggl_likely(y1 < ymin)) { - int32_t xadjust = (edge->x_incr * (ymin-y1)) >> TRI_FRACTION_BITS; - edge->x += xadjust; - } - - ++*pcount; -} - - -static void -triangle_sweep_edges( Edge* left, - Edge* right, - int ytop, - int ybot, - context_t* c ) -{ - int count = ((ybot - ytop)>>TRI_FRACTION_BITS) + 1; - if (count<=0) return; - - // sort the edges horizontally - if ((left->x > right->x) || - ((left->x == right->x) && (left->x_incr > right->x_incr))) { - swap(left, right); - } - - int left_x = left->x; - int right_x = right->x; - const int left_xi = left->x_incr; - const int right_xi = right->x_incr; - left->x += left_xi * count; - right->x += right_xi * count; - - const int xmin = c->state.scissor.left; - const int xmax = c->state.scissor.right; - do { - // horizontal scissoring - const int32_t xl = max(left_x >> TRI_ITERATORS_BITS, xmin); - const int32_t xr = min(right_x >> TRI_ITERATORS_BITS, xmax); - left_x += left_xi; - right_x += right_xi; - // invoke the scanline rasterizer - if (ggl_likely(xl < xr)) { - c->iterators.xl = xl; - c->iterators.xr = xr; - c->scanline(c); - } - c->step_y(c); - } while (--count); -} - - -void trianglex_big(void* con, - const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2) -{ - GGL_CONTEXT(c, con); - - Edge edges[3]; - int num_edges = 0; - int32_t ymin = TRI_FROM_INT(c->state.scissor.top) + TRI_HALF; - int32_t ymax = TRI_FROM_INT(c->state.scissor.bottom) - TRI_HALF; - - edge_setup( edges, &num_edges, v0, v1, ymin, ymax ); - edge_setup( edges, &num_edges, v0, v2, ymin, ymax ); - edge_setup( edges, &num_edges, v1, v2, ymin, ymax ); - - if (ggl_unlikely(num_edges<2)) // for really tiny triangles that don't - return; // cross any scanline centers - - Edge* left = &edges[0]; - Edge* right = &edges[1]; - Edge* other = &edges[2]; - int32_t y_top = min(left->y_top, right->y_top); - int32_t y_bot = max(left->y_bot, right->y_bot); - - if (ggl_likely(num_edges==3)) { - y_top = min(y_top, edges[2].y_top); - y_bot = max(y_bot, edges[2].y_bot); - if (edges[0].y_top > y_top) { - other = &edges[0]; - left = &edges[2]; - } else if (edges[1].y_top > y_top) { - other = &edges[1]; - right = &edges[2]; - } - } - - c->init_y(c, y_top >> TRI_FRACTION_BITS); - - int32_t y_mid = min(left->y_bot, right->y_bot); - triangle_sweep_edges( left, right, y_top, y_mid, c ); - - // second scanline sweep loop, if necessary - y_mid += TRI_ONE; - if (y_mid <= y_bot) { - ((left->y_bot == y_bot) ? right : left) = other; - if (other->y_top < y_mid) { - other->x += other->x_incr; - } - triangle_sweep_edges( left, right, y_mid, y_bot, c ); - } -} - -void aa_trianglex(void* con, - const GGLcoord* a, const GGLcoord* b, const GGLcoord* c) -{ - GGLcoord pts[6] = { a[0], a[1], b[0], b[1], c[0], c[1] }; - aapolyx(con, pts, 3); -} - -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif - -struct AAEdge -{ - GGLfixed x; // edge position in 12.16 coordinates - GGLfixed x_incr; // on each y step, increment x by that amount - GGLfixed y_incr; // on each x step, increment y by that amount - int16_t y_top; // starting scanline, 12.4 format - int16_t y_bot; // starting scanline, 12.4 format - void dump(); -}; - -void AAEdge::dump() -{ - float tri = 1.0f / TRI_ONE; - float iter = 1.0f / (1<<TRI_ITERATORS_BITS); - float fix = 1.0f / FIXED_ONE; - ALOGD( "x=%08x (%.3f), " - "x_incr=%08x (%.3f), y_incr=%08x (%.3f), " - "y_top=%08x (%.3f), y_bot=%08x (%.3f) ", - x, x*fix, - x_incr, x_incr*iter, - y_incr, y_incr*iter, - y_top, y_top*tri, - y_bot, y_bot*tri ); -} - -// the following function sets up an edge, it assumes -// that ymin and ymax are in already in the 'reduced' -// format -static __attribute__((noinline)) -void aa_edge_setup( - AAEdge* edges, - int* pcount, - const GGLcoord* p1, - const GGLcoord* p2, - int32_t ymin, - int32_t ymax ) -{ - const GGLfixed* top = p1; - const GGLfixed* bot = p2; - AAEdge* edge = edges + *pcount; - - if (top[1] > bot[1]) - swap(top, bot); - - int y1 = top[1]; - int y2 = bot[1]; - int dy = y2 - y1; - - if (dy==0 || y1>ymax || y2<ymin) - return; - - if (y1 > ymin) - ymin = y1; - - if (y2 < ymax) - ymax = y2; - - const int x1 = top[0]; - const int dx = bot[0] - x1; - const int shift = FIXED_BITS - TRI_FRACTION_BITS; - - // setup edge fields - edge->x = x1 << shift; - edge->x_incr = 0; - edge->y_top = ymin; - edge->y_bot = ymax; - edge->y_incr = 0x7FFFFFFF; - - if (ggl_likely(ymin <= ymax && dx)) { - edge->x_incr = gglDivQ16(dx, dy); - if (dx != 0) { - edge->y_incr = abs(gglDivQ16(dy, dx)); - } - } - if (ggl_likely(y1 < ymin)) { - int32_t xadjust = (edge->x_incr * (ymin-y1)) - >> (TRI_FRACTION_BITS + TRI_ITERATORS_BITS - FIXED_BITS); - edge->x += xadjust; - } - - ++*pcount; -} - - -typedef int (*compar_t)(const void*, const void*); -static int compare_edges(const AAEdge *e0, const AAEdge *e1) { - if (e0->y_top > e1->y_top) return 1; - if (e0->y_top < e1->y_top) return -1; - if (e0->x > e1->x) return 1; - if (e0->x < e1->x) return -1; - if (e0->x_incr > e1->x_incr) return 1; - if (e0->x_incr < e1->x_incr) return -1; - return 0; // same edges, should never happen -} - -static inline -void SET_COVERAGE(int16_t*& p, int32_t value, ssize_t n) -{ - android_memset16((uint16_t*)p, value, n*2); - p += n; -} - -static inline -void ADD_COVERAGE(int16_t*& p, int32_t value) -{ - value = *p + value; - if (value >= 0x8000) - value = 0x7FFF; - *p++ = value; -} - -static inline -void SUB_COVERAGE(int16_t*& p, int32_t value) -{ - value = *p - value; - value &= ~(value>>31); - *p++ = value; -} - -void aapolyx(void* con, - const GGLcoord* pts, int count) -{ - /* - * NOTE: This routine assumes that the polygon has been clipped to the - * viewport already, that is, no vertex lies outside of the framebuffer. - * If this happens, the code below won't corrupt memory but the - * coverage values may not be correct. - */ - - GGL_CONTEXT(c, con); - - // we do only quads for now (it's used for thick lines) - if ((count>4) || (count<2)) return; - - // take scissor into account - const int xmin = c->state.scissor.left; - const int xmax = c->state.scissor.right; - if (xmin >= xmax) return; - - // generate edges from the vertices - int32_t ymin = TRI_FROM_INT(c->state.scissor.top); - int32_t ymax = TRI_FROM_INT(c->state.scissor.bottom); - if (ymin >= ymax) return; - - AAEdge edges[4]; - int num_edges = 0; - GGLcoord const * p = pts; - for (int i=0 ; i<count-1 ; i++, p+=2) { - aa_edge_setup(edges, &num_edges, p, p+2, ymin, ymax); - } - aa_edge_setup(edges, &num_edges, p, pts, ymin, ymax ); - if (ggl_unlikely(num_edges<2)) - return; - - // sort the edge list top to bottom, left to right. - qsort(edges, num_edges, sizeof(AAEdge), (compar_t)compare_edges); - - int16_t* const covPtr = c->state.buffers.coverage; - memset(covPtr+xmin, 0, (xmax-xmin)*sizeof(*covPtr)); - - // now, sweep all edges in order - // start with the 2 first edges. We know that they share their top - // vertex, by construction. - int i = 2; - AAEdge* left = &edges[0]; - AAEdge* right = &edges[1]; - int32_t yt = left->y_top; - GGLfixed l = left->x; - GGLfixed r = right->x; - int retire = 0; - int16_t* coverage; - - // at this point we can initialize the rasterizer - c->init_y(c, yt>>TRI_FRACTION_BITS); - c->iterators.xl = xmax; - c->iterators.xr = xmin; - - do { - int32_t y = min(min(left->y_bot, right->y_bot), TRI_FLOOR(yt + TRI_ONE)); - const int32_t shift = TRI_FRACTION_BITS + TRI_ITERATORS_BITS - FIXED_BITS; - const int cf_shift = (1 + TRI_FRACTION_BITS*2 + TRI_ITERATORS_BITS - 15); - - // compute xmin and xmax for the left edge - GGLfixed l_min = gglMulAddx(left->x_incr, y - left->y_top, left->x, shift); - GGLfixed l_max = l; - l = l_min; - if (l_min > l_max) - swap(l_min, l_max); - - // compute xmin and xmax for the right edge - GGLfixed r_min = gglMulAddx(right->x_incr, y - right->y_top, right->x, shift); - GGLfixed r_max = r; - r = r_min; - if (r_min > r_max) - swap(r_min, r_max); - - // make sure we're not touching coverage values outside of the - // framebuffer - l_min &= ~(l_min>>31); - r_min &= ~(r_min>>31); - l_max &= ~(l_max>>31); - r_max &= ~(r_max>>31); - if (gglFixedToIntFloor(l_min) >= xmax) l_min = gglIntToFixed(xmax)-1; - if (gglFixedToIntFloor(r_min) >= xmax) r_min = gglIntToFixed(xmax)-1; - if (gglFixedToIntCeil(l_max) >= xmax) l_max = gglIntToFixed(xmax)-1; - if (gglFixedToIntCeil(r_max) >= xmax) r_max = gglIntToFixed(xmax)-1; - - // compute the integer versions of the above - const GGLfixed l_min_i = gglFloorx(l_min); - const GGLfixed l_max_i = gglCeilx (l_max); - const GGLfixed r_min_i = gglFloorx(r_min); - const GGLfixed r_max_i = gglCeilx (r_max); - - // clip horizontally using the scissor - const int xml = max(xmin, gglFixedToIntFloor(l_min_i)); - const int xmr = min(xmax, gglFixedToIntFloor(r_max_i)); - - // if we just stepped to a new scanline, render the previous one. - // and clear the coverage buffer - if (retire) { - if (c->iterators.xl < c->iterators.xr) - c->scanline(c); - c->step_y(c); - memset(covPtr+xmin, 0, (xmax-xmin)*sizeof(*covPtr)); - c->iterators.xl = xml; - c->iterators.xr = xmr; - } else { - // update the horizontal range of this scanline - c->iterators.xl = min(c->iterators.xl, xml); - c->iterators.xr = max(c->iterators.xr, xmr); - } - - coverage = covPtr + gglFixedToIntFloor(l_min_i); - if (l_min_i == gglFloorx(l_max)) { - - /* - * fully traverse this pixel vertically - * l_max - * +-----/--+ yt - * | / | - * | / | - * | / | - * +-/------+ y - * l_min (l_min_i + TRI_ONE) - */ - - GGLfixed dx = l_max - l_min; - int32_t dy = y - yt; - int cf = gglMulx((dx >> 1) + (l_min_i + FIXED_ONE - l_max), dy, - FIXED_BITS + TRI_FRACTION_BITS - 15); - ADD_COVERAGE(coverage, cf); - // all pixels on the right have cf = 1.0 - } else { - /* - * spans several pixels in one scanline - * l_max - * +--------+--/-----+ yt - * | |/ | - * | /| | - * | / | | - * +---/----+--------+ y - * l_min (l_min_i + TRI_ONE) - */ - - // handle the first pixel separately... - const int32_t y_incr = left->y_incr; - int32_t dx = TRI_FROM_FIXED(l_min_i - l_min) + TRI_ONE; - int32_t cf = (dx * dx * y_incr) >> cf_shift; - ADD_COVERAGE(coverage, cf); - - // following pixels get covered by y_incr, but we need - // to fix-up the cf to account for previous partial pixel - dx = TRI_FROM_FIXED(l_min - l_min_i); - cf -= (dx * dx * y_incr) >> cf_shift; - for (int x = l_min_i+FIXED_ONE ; x < l_max_i-FIXED_ONE ; x += FIXED_ONE) { - cf += y_incr >> (TRI_ITERATORS_BITS-15); - ADD_COVERAGE(coverage, cf); - } - - // and the last pixel - dx = TRI_FROM_FIXED(l_max - l_max_i) - TRI_ONE; - cf += (dx * dx * y_incr) >> cf_shift; - ADD_COVERAGE(coverage, cf); - } - - // now, fill up all fully covered pixels - coverage = covPtr + gglFixedToIntFloor(l_max_i); - int cf = ((y - yt) << (15 - TRI_FRACTION_BITS)); - if (ggl_likely(cf >= 0x8000)) { - SET_COVERAGE(coverage, 0x7FFF, ((r_max - l_max_i)>>FIXED_BITS)+1); - } else { - for (int x=l_max_i ; x<r_max ; x+=FIXED_ONE) { - ADD_COVERAGE(coverage, cf); - } - } - - // subtract the coverage of the right edge - coverage = covPtr + gglFixedToIntFloor(r_min_i); - if (r_min_i == gglFloorx(r_max)) { - GGLfixed dx = r_max - r_min; - int32_t dy = y - yt; - int cf = gglMulx((dx >> 1) + (r_min_i + FIXED_ONE - r_max), dy, - FIXED_BITS + TRI_FRACTION_BITS - 15); - SUB_COVERAGE(coverage, cf); - // all pixels on the right have cf = 1.0 - } else { - // handle the first pixel separately... - const int32_t y_incr = right->y_incr; - int32_t dx = TRI_FROM_FIXED(r_min_i - r_min) + TRI_ONE; - int32_t cf = (dx * dx * y_incr) >> cf_shift; - SUB_COVERAGE(coverage, cf); - - // following pixels get covered by y_incr, but we need - // to fix-up the cf to account for previous partial pixel - dx = TRI_FROM_FIXED(r_min - r_min_i); - cf -= (dx * dx * y_incr) >> cf_shift; - for (int x = r_min_i+FIXED_ONE ; x < r_max_i-FIXED_ONE ; x += FIXED_ONE) { - cf += y_incr >> (TRI_ITERATORS_BITS-15); - SUB_COVERAGE(coverage, cf); - } - - // and the last pixel - dx = TRI_FROM_FIXED(r_max - r_max_i) - TRI_ONE; - cf += (dx * dx * y_incr) >> cf_shift; - SUB_COVERAGE(coverage, cf); - } - - // did we reach the end of an edge? if so, get a new one. - if (y == left->y_bot || y == right->y_bot) { - // bail out if we're done - if (i>=num_edges) - break; - if (y == left->y_bot) - left = &edges[i++]; - if (y == right->y_bot) - right = &edges[i++]; - } - - // next scanline - yt = y; - - // did we just finish a scanline? - retire = (y << (32-TRI_FRACTION_BITS)) == 0; - } while (true); - - // render the last scanline - if (c->iterators.xl < c->iterators.xr) - c->scanline(c); -} - -}; // namespace android diff --git a/libpixelflinger/trap.h b/libpixelflinger/trap.h deleted file mode 100644 index 7cce7b3e1..000000000 --- a/libpixelflinger/trap.h +++ /dev/null @@ -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 diff --git a/libstats/pull/Android.bp b/libstats/pull/Android.bp new file mode 100644 index 000000000..a8b4a4faf --- /dev/null +++ b/libstats/pull/Android.bp @@ -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, +} diff --git a/libstats/pull/OWNERS b/libstats/pull/OWNERS new file mode 100644 index 000000000..7855774a7 --- /dev/null +++ b/libstats/pull/OWNERS @@ -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 diff --git a/libstats/pull/TEST_MAPPING b/libstats/pull/TEST_MAPPING new file mode 100644 index 000000000..76f4f0271 --- /dev/null +++ b/libstats/pull/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit" : [ + { + "name" : "libstatspull_test" + } + ] +}
\ No newline at end of file diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h new file mode 100644 index 000000000..17df58435 --- /dev/null +++ b/libstats/pull/include/stats_pull_atom_callback.h @@ -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 diff --git a/libstats/pull/libstatspull.map.txt b/libstats/pull/libstatspull.map.txt new file mode 100644 index 000000000..e0e851a15 --- /dev/null +++ b/libstats/pull/libstatspull.map.txt @@ -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: + *; +}; diff --git a/libstats/pull/libstatspull_test.xml b/libstats/pull/libstatspull_test.xml new file mode 100644 index 000000000..233fc1f18 --- /dev/null +++ b/libstats/pull/libstatspull_test.xml @@ -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. +--> +<configuration description="Runs libstatspull_test."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-native" /> + <option name="test-suite-tag" value="mts" /> + + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="cleanup" value="true" /> + <option name="push" value="libstatspull_test->/data/local/tmp/libstatspull_test" /> + <option name="append-bitness" value="true" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="module-name" value="libstatspull_test" /> + </test> + + <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> + <option name="mainline-module-package-name" value="com.google.android.os.statsd" /> + </object> +</configuration> diff --git a/libstats/pull/stats_pull_atom_callback.cpp b/libstats/pull/stats_pull_atom_callback.cpp new file mode 100644 index 000000000..478cae760 --- /dev/null +++ b/libstats/pull/stats_pull_atom_callback.cpp @@ -0,0 +1,260 @@ +/* + * 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. + */ + +#include <map> +#include <thread> +#include <vector> + +#include <stats_event.h> +#include <stats_pull_atom_callback.h> + +#include <aidl/android/os/BnPullAtomCallback.h> +#include <aidl/android/os/IPullAtomResultReceiver.h> +#include <aidl/android/os/IStatsd.h> +#include <aidl/android/util/StatsEventParcel.h> +#include <android/binder_auto_utils.h> +#include <android/binder_ibinder.h> +#include <android/binder_manager.h> + +using Status = ::ndk::ScopedAStatus; +using aidl::android::os::BnPullAtomCallback; +using aidl::android::os::IPullAtomResultReceiver; +using aidl::android::os::IStatsd; +using aidl::android::util::StatsEventParcel; +using ::ndk::SharedRefBase; + +struct AStatsEventList { + std::vector<AStatsEvent*> data; +}; + +AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data) { + AStatsEvent* event = AStatsEvent_obtain(); + pull_data->data.push_back(event); + return event; +} + +static const int64_t DEFAULT_COOL_DOWN_MILLIS = 1000LL; // 1 second. +static const int64_t DEFAULT_TIMEOUT_MILLIS = 2000LL; // 2 seconds. + +struct AStatsManager_PullAtomMetadata { + int64_t cool_down_millis; + int64_t timeout_millis; + std::vector<int32_t> additive_fields; +}; + +AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain() { + AStatsManager_PullAtomMetadata* metadata = new AStatsManager_PullAtomMetadata(); + metadata->cool_down_millis = DEFAULT_COOL_DOWN_MILLIS; + metadata->timeout_millis = DEFAULT_TIMEOUT_MILLIS; + metadata->additive_fields = std::vector<int32_t>(); + return metadata; +} + +void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata) { + delete metadata; +} + +void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata, + int64_t cool_down_millis) { + metadata->cool_down_millis = cool_down_millis; +} + +int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata) { + return metadata->cool_down_millis; +} + +void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata, + int64_t timeout_millis) { + metadata->timeout_millis = timeout_millis; +} + +int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata) { + return metadata->timeout_millis; +} + +void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata, + int32_t* additive_fields, + int32_t num_fields) { + metadata->additive_fields.assign(additive_fields, additive_fields + num_fields); +} + +int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields( + AStatsManager_PullAtomMetadata* metadata) { + return metadata->additive_fields.size(); +} + +void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata, + int32_t* fields) { + std::copy(metadata->additive_fields.begin(), metadata->additive_fields.end(), fields); +} + +class StatsPullAtomCallbackInternal : public BnPullAtomCallback { + public: + StatsPullAtomCallbackInternal(const AStatsManager_PullAtomCallback callback, void* cookie, + const int64_t coolDownMillis, const int64_t timeoutMillis, + const std::vector<int32_t> additiveFields) + : mCallback(callback), + mCookie(cookie), + mCoolDownMillis(coolDownMillis), + mTimeoutMillis(timeoutMillis), + mAdditiveFields(additiveFields) {} + + Status onPullAtom(int32_t atomTag, + const std::shared_ptr<IPullAtomResultReceiver>& resultReceiver) override { + AStatsEventList statsEventList; + int successInt = mCallback(atomTag, &statsEventList, mCookie); + bool success = successInt == AStatsManager_PULL_SUCCESS; + + // Convert stats_events into StatsEventParcels. + std::vector<StatsEventParcel> parcels; + for (int i = 0; i < statsEventList.data.size(); i++) { + size_t size; + uint8_t* buffer = AStatsEvent_getBuffer(statsEventList.data[i], &size); + + StatsEventParcel p; + // vector.assign() creates a copy, but this is inevitable unless + // stats_event.h/c uses a vector as opposed to a buffer. + p.buffer.assign(buffer, buffer + size); + parcels.push_back(std::move(p)); + } + + Status status = resultReceiver->pullFinished(atomTag, success, parcels); + if (!status.isOk()) { + std::vector<StatsEventParcel> emptyParcels; + resultReceiver->pullFinished(atomTag, /*success=*/false, emptyParcels); + } + for (int i = 0; i < statsEventList.data.size(); i++) { + AStatsEvent_release(statsEventList.data[i]); + } + return Status::ok(); + } + + int64_t getCoolDownMillis() const { return mCoolDownMillis; } + int64_t getTimeoutMillis() const { return mTimeoutMillis; } + const std::vector<int32_t>& getAdditiveFields() const { return mAdditiveFields; } + + private: + const AStatsManager_PullAtomCallback mCallback; + void* mCookie; + const int64_t mCoolDownMillis; + const int64_t mTimeoutMillis; + const std::vector<int32_t> mAdditiveFields; +}; + +static std::mutex pullAtomMutex; +static std::shared_ptr<IStatsd> sStatsd = nullptr; + +static std::map<int32_t, std::shared_ptr<StatsPullAtomCallbackInternal>> mPullers; +static std::shared_ptr<IStatsd> getStatsService(); + +static void binderDied(void* /*cookie*/) { + { + std::lock_guard<std::mutex> lock(pullAtomMutex); + sStatsd = nullptr; + } + + std::shared_ptr<IStatsd> statsService = getStatsService(); + if (statsService == nullptr) { + return; + } + + // Since we do not want to make an IPC with the lock held, we first create a + // copy of the data with the lock held before iterating through the map. + std::map<int32_t, std::shared_ptr<StatsPullAtomCallbackInternal>> pullersCopy; + { + std::lock_guard<std::mutex> lock(pullAtomMutex); + pullersCopy = mPullers; + } + for (const auto& it : pullersCopy) { + statsService->registerNativePullAtomCallback(it.first, it.second->getCoolDownMillis(), + it.second->getTimeoutMillis(), + it.second->getAdditiveFields(), it.second); + } +} + +static ::ndk::ScopedAIBinder_DeathRecipient sDeathRecipient( + AIBinder_DeathRecipient_new(binderDied)); + +static std::shared_ptr<IStatsd> getStatsService() { + std::lock_guard<std::mutex> lock(pullAtomMutex); + if (!sStatsd) { + // Fetch statsd + ::ndk::SpAIBinder binder(AServiceManager_getService("stats")); + sStatsd = IStatsd::fromBinder(binder); + if (sStatsd) { + AIBinder_linkToDeath(binder.get(), sDeathRecipient.get(), /*cookie=*/nullptr); + } + } + return sStatsd; +} + +void registerStatsPullAtomCallbackBlocking(int32_t atomTag, + std::shared_ptr<StatsPullAtomCallbackInternal> cb) { + const std::shared_ptr<IStatsd> statsService = getStatsService(); + if (statsService == nullptr) { + // Statsd not available + return; + } + + statsService->registerNativePullAtomCallback( + atomTag, cb->getCoolDownMillis(), cb->getTimeoutMillis(), cb->getAdditiveFields(), cb); +} + +void unregisterStatsPullAtomCallbackBlocking(int32_t atomTag) { + const std::shared_ptr<IStatsd> statsService = getStatsService(); + if (statsService == nullptr) { + // Statsd not available + return; + } + + statsService->unregisterNativePullAtomCallback(atomTag); +} + +void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata, + AStatsManager_PullAtomCallback callback, void* cookie) { + int64_t coolDownMillis = + metadata == nullptr ? DEFAULT_COOL_DOWN_MILLIS : metadata->cool_down_millis; + int64_t timeoutMillis = metadata == nullptr ? DEFAULT_TIMEOUT_MILLIS : metadata->timeout_millis; + + std::vector<int32_t> additiveFields; + if (metadata != nullptr) { + additiveFields = metadata->additive_fields; + } + + std::shared_ptr<StatsPullAtomCallbackInternal> callbackBinder = + SharedRefBase::make<StatsPullAtomCallbackInternal>(callback, cookie, coolDownMillis, + timeoutMillis, additiveFields); + + { + std::lock_guard<std::mutex> lg(pullAtomMutex); + // Always add to the map. If statsd is dead, we will add them when it comes back. + mPullers[atom_tag] = callbackBinder; + } + + std::thread registerThread(registerStatsPullAtomCallbackBlocking, atom_tag, callbackBinder); + registerThread.detach(); +} + +void AStatsManager_clearPullAtomCallback(int32_t atom_tag) { + { + std::lock_guard<std::mutex> lg(pullAtomMutex); + // Always remove the puller from our map. + // If statsd is down, we will not register it when it comes back. + mPullers.erase(atom_tag); + } + std::thread unregisterThread(unregisterStatsPullAtomCallbackBlocking, atom_tag); + unregisterThread.detach(); +} diff --git a/libstats/pull/tests/pull_atom_metadata_test.cpp b/libstats/pull/tests/pull_atom_metadata_test.cpp new file mode 100644 index 000000000..abc8e47af --- /dev/null +++ b/libstats/pull/tests/pull_atom_metadata_test.cpp @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#include <gtest/gtest.h> + +#include <stats_pull_atom_callback.h> + +namespace { + +static const int64_t DEFAULT_COOL_DOWN_MILLIS = 1000LL; // 1 second. +static const int64_t DEFAULT_TIMEOUT_MILLIS = 2000LL; // 2 seconds. + +} // anonymous namespace + +TEST(AStatsManager_PullAtomMetadataTest, TestEmpty) { + AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0); + AStatsManager_PullAtomMetadata_release(metadata); +} + +TEST(AStatsManager_PullAtomMetadataTest, TestSetTimeoutMillis) { + int64_t timeoutMillis = 500; + AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); + AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), timeoutMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0); + AStatsManager_PullAtomMetadata_release(metadata); +} + +TEST(AStatsManager_PullAtomMetadataTest, TestSetCoolDownMillis) { + int64_t coolDownMillis = 10000; + AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); + AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), coolDownMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), 0); + AStatsManager_PullAtomMetadata_release(metadata); +} + +TEST(AStatsManager_PullAtomMetadataTest, TestSetAdditiveFields) { + const int numFields = 3; + int inputFields[numFields] = {2, 4, 6}; + AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); + AStatsManager_PullAtomMetadata_setAdditiveFields(metadata, inputFields, numFields); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), DEFAULT_COOL_DOWN_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), DEFAULT_TIMEOUT_MILLIS); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), numFields); + int outputFields[numFields]; + AStatsManager_PullAtomMetadata_getAdditiveFields(metadata, outputFields); + for (int i = 0; i < numFields; i++) { + EXPECT_EQ(inputFields[i], outputFields[i]); + } + AStatsManager_PullAtomMetadata_release(metadata); +} + +TEST(AStatsManager_PullAtomMetadataTest, TestSetAllElements) { + int64_t timeoutMillis = 500; + int64_t coolDownMillis = 10000; + const int numFields = 3; + int inputFields[numFields] = {2, 4, 6}; + + AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain(); + AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, timeoutMillis); + AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, coolDownMillis); + AStatsManager_PullAtomMetadata_setAdditiveFields(metadata, inputFields, numFields); + + EXPECT_EQ(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), coolDownMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), timeoutMillis); + EXPECT_EQ(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), numFields); + int outputFields[numFields]; + AStatsManager_PullAtomMetadata_getAdditiveFields(metadata, outputFields); + for (int i = 0; i < numFields; i++) { + EXPECT_EQ(inputFields[i], outputFields[i]); + } + AStatsManager_PullAtomMetadata_release(metadata); +} diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp index cbc65ff1c..a63a5b63b 100644 --- a/libstats/push_compat/Android.bp +++ b/libstats/push_compat/Android.bp @@ -38,7 +38,6 @@ cc_defaults { ], shared_libs: [ "liblog", - "libutils", ], } @@ -46,6 +45,9 @@ cc_library { name: "libstatspush_compat", defaults: ["libstatspush_compat_defaults"], export_include_dirs: ["include"], + export_header_lib_headers: [ + "libstatssocket_headers", + ], static_libs: ["libgtest_prod"], apex_available: ["com.android.resolv"], min_sdk_version: "29", diff --git a/libstats/push_compat/StatsEventCompat.cpp b/libstats/push_compat/StatsEventCompat.cpp index edfa070ed..12a5dd4a7 100644 --- a/libstats/push_compat/StatsEventCompat.cpp +++ b/libstats/push_compat/StatsEventCompat.cpp @@ -15,41 +15,42 @@ */ #include "include/StatsEventCompat.h" + +#include <chrono> + +#include <android-base/chrono_utils.h> #include <android-base/properties.h> #include <android/api-level.h> #include <android/log.h> #include <dlfcn.h> -#include <utils/SystemClock.h> +using android::base::boot_clock; using android::base::GetProperty; const static int kStatsEventTag = 1937006964; - -/* Checking ro.build.version.release is fragile, as the release field is - * an opaque string without structural guarantees. However, testing confirms - * that on Q devices, the property is "10," and on R, it is "R." Until - * android_get_device_api_level() is updated, this is the only solution. - * - * TODO(b/146019024): migrate to android_get_device_api_level() - */ const bool StatsEventCompat::mPlatformAtLeastR = - GetProperty("ro.build.version.codename", "") == "R" || - android_get_device_api_level() > __ANDROID_API_Q__; + android_get_device_api_level() >= __ANDROID_API_R__; -// definitions of static class variables +// initializations of static class variables bool StatsEventCompat::mAttemptedLoad = false; -struct stats_event_api_table* StatsEventCompat::mStatsEventApi = nullptr; std::mutex StatsEventCompat::mLoadLock; +AStatsEventApi StatsEventCompat::mAStatsEventApi; + +static int64_t elapsedRealtimeNano() { + return std::chrono::time_point_cast<std::chrono::nanoseconds>(boot_clock::now()) + .time_since_epoch() + .count(); +} StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) { // guard loading because StatsEventCompat might be called from multithreaded // environment { std::lock_guard<std::mutex> lg(mLoadLock); - if (!mAttemptedLoad) { + if (!mAttemptedLoad && mPlatformAtLeastR) { void* handle = dlopen("libstatssocket.so", RTLD_NOW); if (handle) { - mStatsEventApi = (struct stats_event_api_table*)dlsym(handle, "table"); + initializeApiTableLocked(handle); } else { ALOGE("dlopen failed: %s\n", dlerror()); } @@ -57,61 +58,93 @@ StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) { mAttemptedLoad = true; } - if (mStatsEventApi) { - mEventR = mStatsEventApi->obtain(); - } else if (!mPlatformAtLeastR) { - mEventQ << android::elapsedRealtimeNano(); + if (useRSchema()) { + mEventR = mAStatsEventApi.obtain(); + } else if (useQSchema()) { + mEventQ << elapsedRealtimeNano(); } } StatsEventCompat::~StatsEventCompat() { - if (mStatsEventApi) mStatsEventApi->release(mEventR); + if (useRSchema()) mAStatsEventApi.release(mEventR); +} + +// Populates the AStatsEventApi struct by calling dlsym to find the address of +// each API function. +void StatsEventCompat::initializeApiTableLocked(void* handle) { + mAStatsEventApi.obtain = (AStatsEvent* (*)())dlsym(handle, "AStatsEvent_obtain"); + mAStatsEventApi.build = (void (*)(AStatsEvent*))dlsym(handle, "AStatsEvent_build"); + mAStatsEventApi.write = (int (*)(AStatsEvent*))dlsym(handle, "AStatsEvent_write"); + mAStatsEventApi.release = (void (*)(AStatsEvent*))dlsym(handle, "AStatsEvent_release"); + mAStatsEventApi.setAtomId = + (void (*)(AStatsEvent*, uint32_t))dlsym(handle, "AStatsEvent_setAtomId"); + mAStatsEventApi.writeInt32 = + (void (*)(AStatsEvent*, int32_t))dlsym(handle, "AStatsEvent_writeInt32"); + mAStatsEventApi.writeInt64 = + (void (*)(AStatsEvent*, int64_t))dlsym(handle, "AStatsEvent_writeInt64"); + mAStatsEventApi.writeFloat = + (void (*)(AStatsEvent*, float))dlsym(handle, "AStatsEvent_writeFloat"); + mAStatsEventApi.writeBool = + (void (*)(AStatsEvent*, bool))dlsym(handle, "AStatsEvent_writeBool"); + mAStatsEventApi.writeByteArray = (void (*)(AStatsEvent*, const uint8_t*, size_t))dlsym( + handle, "AStatsEvent_writeByteArray"); + mAStatsEventApi.writeString = + (void (*)(AStatsEvent*, const char*))dlsym(handle, "AStatsEvent_writeString"); + mAStatsEventApi.writeAttributionChain = + (void (*)(AStatsEvent*, const uint32_t*, const char* const*, uint8_t))dlsym( + handle, "AStatsEvent_writeAttributionChain"); + mAStatsEventApi.addBoolAnnotation = + (void (*)(AStatsEvent*, uint8_t, bool))dlsym(handle, "AStatsEvent_addBoolAnnotation"); + mAStatsEventApi.addInt32Annotation = (void (*)(AStatsEvent*, uint8_t, int32_t))dlsym( + handle, "AStatsEvent_addInt32Annotation"); + + mAStatsEventApi.initialized = true; } void StatsEventCompat::setAtomId(int32_t atomId) { - if (mStatsEventApi) { - mStatsEventApi->set_atom_id(mEventR, (uint32_t)atomId); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.setAtomId(mEventR, (uint32_t)atomId); + } else if (useQSchema()) { mEventQ << atomId; } } void StatsEventCompat::writeInt32(int32_t value) { - if (mStatsEventApi) { - mStatsEventApi->write_int32(mEventR, value); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeInt32(mEventR, value); + } else if (useQSchema()) { mEventQ << value; } } void StatsEventCompat::writeInt64(int64_t value) { - if (mStatsEventApi) { - mStatsEventApi->write_int64(mEventR, value); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeInt64(mEventR, value); + } else if (useQSchema()) { mEventQ << value; } } void StatsEventCompat::writeFloat(float value) { - if (mStatsEventApi) { - mStatsEventApi->write_float(mEventR, value); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeFloat(mEventR, value); + } else if (useQSchema()) { mEventQ << value; } } void StatsEventCompat::writeBool(bool value) { - if (mStatsEventApi) { - mStatsEventApi->write_bool(mEventR, value); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeBool(mEventR, value); + } else if (useQSchema()) { mEventQ << value; } } void StatsEventCompat::writeByteArray(const char* buffer, size_t length) { - if (mStatsEventApi) { - mStatsEventApi->write_byte_array(mEventR, (const uint8_t*)buffer, length); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeByteArray(mEventR, reinterpret_cast<const uint8_t*>(buffer), length); + } else if (useQSchema()) { mEventQ.AppendCharArray(buffer, length); } } @@ -119,19 +152,19 @@ void StatsEventCompat::writeByteArray(const char* buffer, size_t length) { void StatsEventCompat::writeString(const char* value) { if (value == nullptr) value = ""; - if (mStatsEventApi) { - mStatsEventApi->write_string8(mEventR, value); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeString(mEventR, value); + } else if (useQSchema()) { mEventQ << value; } } void StatsEventCompat::writeAttributionChain(const int32_t* uids, size_t numUids, const vector<const char*>& tags) { - if (mStatsEventApi) { - mStatsEventApi->write_attribution_chain(mEventR, (const uint32_t*)uids, tags.data(), - (uint8_t)numUids); - } else if (!mPlatformAtLeastR) { + if (useRSchema()) { + mAStatsEventApi.writeAttributionChain(mEventR, (const uint32_t*)uids, tags.data(), + (uint8_t)numUids); + } else if (useQSchema()) { mEventQ.begin(); for (size_t i = 0; i < numUids; i++) { mEventQ.begin(); @@ -148,26 +181,8 @@ void StatsEventCompat::writeKeyValuePairs(const map<int, int32_t>& int32Map, const map<int, int64_t>& int64Map, const map<int, const char*>& stringMap, const map<int, float>& floatMap) { - if (mStatsEventApi) { - vector<struct key_value_pair> pairs; - - for (const auto& it : int32Map) { - pairs.push_back({.key = it.first, .valueType = INT32_TYPE, .int32Value = it.second}); - } - for (const auto& it : int64Map) { - pairs.push_back({.key = it.first, .valueType = INT64_TYPE, .int64Value = it.second}); - } - for (const auto& it : stringMap) { - pairs.push_back({.key = it.first, .valueType = STRING_TYPE, .stringValue = it.second}); - } - for (const auto& it : floatMap) { - pairs.push_back({.key = it.first, .valueType = FLOAT_TYPE, .floatValue = it.second}); - } - - mStatsEventApi->write_key_value_pairs(mEventR, pairs.data(), (uint8_t)pairs.size()); - } - - else if (!mPlatformAtLeastR) { + // AStatsEvent does not support key value pairs. + if (useQSchema()) { mEventQ.begin(); writeKeyValuePairMap(int32Map); writeKeyValuePairMap(int64Map); @@ -194,28 +209,35 @@ template void StatsEventCompat::writeKeyValuePairMap<float>(const map<int, float template void StatsEventCompat::writeKeyValuePairMap<const char*>(const map<int, const char*>&); void StatsEventCompat::addBoolAnnotation(uint8_t annotationId, bool value) { - if (mStatsEventApi) mStatsEventApi->add_bool_annotation(mEventR, annotationId, value); + if (useRSchema()) { + mAStatsEventApi.addBoolAnnotation(mEventR, annotationId, value); + } // Don't do anything if on Q. } void StatsEventCompat::addInt32Annotation(uint8_t annotationId, int32_t value) { - if (mStatsEventApi) mStatsEventApi->add_int32_annotation(mEventR, annotationId, value); + if (useRSchema()) { + mAStatsEventApi.addInt32Annotation(mEventR, annotationId, value); + } // Don't do anything if on Q. } int StatsEventCompat::writeToSocket() { - if (mStatsEventApi) { - mStatsEventApi->build(mEventR); - return mStatsEventApi->write(mEventR); + if (useRSchema()) { + return mAStatsEventApi.write(mEventR); } - if (!mPlatformAtLeastR) return mEventQ.write(LOG_ID_STATS); + if (useQSchema()) return mEventQ.write(LOG_ID_STATS); - // We reach here only if we're on R, but libstatspush_compat was unable to + // We reach here only if we're on R, but libstatssocket was unable to // be loaded using dlopen. return -ENOLINK; } -bool StatsEventCompat::usesNewSchema() { - return mStatsEventApi != nullptr; +bool StatsEventCompat::useRSchema() { + return mPlatformAtLeastR && mAStatsEventApi.initialized; +} + +bool StatsEventCompat::useQSchema() { + return !mPlatformAtLeastR; } diff --git a/libstats/push_compat/include/StatsEventCompat.h b/libstats/push_compat/include/StatsEventCompat.h index a8cde681c..00bf48bf5 100644 --- a/libstats/push_compat/include/StatsEventCompat.h +++ b/libstats/push_compat/include/StatsEventCompat.h @@ -26,6 +26,26 @@ using std::map; using std::vector; +struct AStatsEventApi { + // Indicates whether the below function pointers have been set using dlsym. + bool initialized = false; + + AStatsEvent* (*obtain)(void); + void (*build)(AStatsEvent*); + int (*write)(AStatsEvent*); + void (*release)(AStatsEvent*); + void (*setAtomId)(AStatsEvent*, uint32_t); + void (*writeInt32)(AStatsEvent*, int32_t); + void (*writeInt64)(AStatsEvent*, int64_t); + void (*writeFloat)(AStatsEvent*, float); + void (*writeBool)(AStatsEvent*, bool); + void (*writeByteArray)(AStatsEvent*, const uint8_t*, size_t); + void (*writeString)(AStatsEvent*, const char*); + void (*writeAttributionChain)(AStatsEvent*, const uint32_t*, const char* const*, uint8_t); + void (*addBoolAnnotation)(AStatsEvent*, uint8_t, bool); + void (*addInt32Annotation)(AStatsEvent*, uint8_t, int32_t); +}; + class StatsEventCompat { public: StatsEventCompat(); @@ -57,15 +77,18 @@ class StatsEventCompat { const static bool mPlatformAtLeastR; static bool mAttemptedLoad; static std::mutex mLoadLock; - static struct stats_event_api_table* mStatsEventApi; + static AStatsEventApi mAStatsEventApi; // non-static member variables - struct stats_event* mEventR = nullptr; + AStatsEvent* mEventR = nullptr; stats_event_list mEventQ; template <class T> void writeKeyValuePairMap(const map<int, T>& keyValuePairMap); - bool usesNewSchema(); + void initializeApiTableLocked(void* handle); + bool useRSchema(); + bool useQSchema(); + FRIEND_TEST(StatsEventCompatTest, TestDynamicLoading); }; diff --git a/libstats/push_compat/tests/StatsEventCompat_test.cpp b/libstats/push_compat/tests/StatsEventCompat_test.cpp index 2be24ec10..2a70db503 100644 --- a/libstats/push_compat/tests/StatsEventCompat_test.cpp +++ b/libstats/push_compat/tests/StatsEventCompat_test.cpp @@ -21,18 +21,9 @@ using android::base::GetProperty; -/* Checking ro.build.version.release is fragile, as the release field is - * an opaque string without structural guarantees. However, testing confirms - * that on Q devices, the property is "10," and on R, it is "R." Until - * android_get_device_api_level() is updated, this is the only solution. - * - * - * TODO(b/146019024): migrate to android_get_device_api_level() - */ -const static bool mPlatformAtLeastR = GetProperty("ro.build.version.release", "") == "R" || - android_get_device_api_level() > __ANDROID_API_Q__; +const static bool mPlatformAtLeastR = android_get_device_api_level() >= __ANDROID_API_R__; TEST(StatsEventCompatTest, TestDynamicLoading) { StatsEventCompat event; - EXPECT_EQ(mPlatformAtLeastR, event.usesNewSchema()); + EXPECT_EQ(mPlatformAtLeastR, event.useRSchema()); } diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp index 6882ab28b..bf79ea244 100644 --- a/libstats/socket/Android.bp +++ b/libstats/socket/Android.bp @@ -17,37 +17,68 @@ // ========================================================================= // Native library to write stats log to statsd socket on Android R and later // ========================================================================= -cc_library { - name: "libstatssocket", +cc_defaults { + name: "libstatssocket_defaults", srcs: [ "stats_buffer_writer.c", "stats_event.c", - // TODO(b/145573568): Remove stats_event_list once stats_event - // migration is complete. - "stats_event_list.c", + "stats_socket.c", "statsd_writer.c", ], - host_supported: true, + export_include_dirs: ["include"], + static_libs: [ + "libcutils", // does not expose a stable C API + ], cflags: [ "-Wall", "-Werror", - "-DLIBLOG_LOG_TAG=1006", - "-DWRITE_TO_STATSD=1", - "-DWRITE_TO_LOGD=0", ], - export_include_dirs: ["include"], - shared_libs: [ - "libcutils", - "liblog", +} + +cc_library { + name: "libstatssocket", + defaults: [ + "libstatssocket_defaults", ], + host_supported: true, + target: { + // On android, libstatssocket should only be linked as a shared lib + android: { + static: { + enabled: false, + }, + }, + host: { + shared: { + enabled: false, + }, + }, + }, + stl: "libc++_static", // enumerate stable entry points for APEX use stubs: { symbol_file: "libstatssocket.map.txt", versions: [ - "1", + "30", ], - } + }, + apex_available: [ + "com.android.os.statsd", + "test_com.android.os.statsd", + ], +} + +//TODO (b/149842105): Figure out if there is a better solution for this. +cc_test_library { + name: "libstatssocket_private", + defaults: [ + "libstatssocket_defaults", + ], + visibility: [ + "//frameworks/base/apex/statsd/tests/libstatspull", + "//frameworks/base/cmds/statsd", + ], } cc_library_headers { @@ -58,41 +89,36 @@ cc_library_headers { min_sdk_version: "29", } -cc_benchmark { - name: "libstatssocket_benchmark", - srcs: [ - "benchmark/main.cpp", - "benchmark/stats_event_benchmark.cpp", - ], - cflags: [ - "-Wall", - "-Werror", - ], - static_libs: [ - "libstatssocket", - ], - shared_libs: [ - "libcutils", - "liblog", - "libgtest_prod", - ], -} - cc_test { name: "libstatssocket_test", - srcs: ["tests/stats_event_test.cpp"], + srcs: [ + "tests/stats_event_test.cpp", + "tests/stats_writer_test.cpp", + ], cflags: [ "-Wall", "-Werror", ], static_libs: [ "libgmock", - "libstatssocket", + "libstatssocket_private", ], shared_libs: [ "libcutils", - "liblog", "libutils", ], - test_suites: ["device_tests"], + test_suites: ["device-tests", "mts"], + test_config: "libstatssocket_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", + }, + }, + require_root: true, } diff --git a/libstats/socket/TEST_MAPPING b/libstats/socket/TEST_MAPPING new file mode 100644 index 000000000..0224998f5 --- /dev/null +++ b/libstats/socket/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit" : [ + { + "name" : "libstatssocket_test" + } + ] +}
\ No newline at end of file diff --git a/libstats/socket/benchmark/stats_event_benchmark.cpp b/libstats/socket/benchmark/stats_event_benchmark.cpp deleted file mode 100644 index 9488168b5..000000000 --- a/libstats/socket/benchmark/stats_event_benchmark.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - */ - -#include "benchmark/benchmark.h" -#include "stats_event.h" - -static struct stats_event* constructStatsEvent() { - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, 100); - - // randomly sample atom size - int numElements = rand() % 800; - for (int i = 0; i < numElements; i++) { - stats_event_write_int32(event, i); - } - - return event; -} - -static void BM_stats_event_truncate_buffer(benchmark::State& state) { - while (state.KeepRunning()) { - struct stats_event* event = constructStatsEvent(); - stats_event_build(event); - stats_event_write(event); - stats_event_release(event); - } -} - -BENCHMARK(BM_stats_event_truncate_buffer); - -static void BM_stats_event_full_buffer(benchmark::State& state) { - while (state.KeepRunning()) { - struct stats_event* event = constructStatsEvent(); - stats_event_truncate_buffer(event, false); - stats_event_build(event); - stats_event_write(event); - stats_event_release(event); - } -} - -BENCHMARK(BM_stats_event_full_buffer); diff --git a/libstats/socket/include/stats_buffer_writer.h b/libstats/socket/include/stats_buffer_writer.h index de4a5e21d..5b41f0e04 100644 --- a/libstats/socket/include/stats_buffer_writer.h +++ b/libstats/socket/include/stats_buffer_writer.h @@ -23,6 +23,7 @@ extern "C" { #endif // __CPLUSPLUS void stats_log_close(); +int stats_log_is_closed(); int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId); #ifdef __cplusplus } diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h index 080e957b2..3d3baf9cf 100644 --- a/libstats/socket/include/stats_event.h +++ b/libstats/socket/include/stats_event.h @@ -26,136 +26,136 @@ * This code defines and encapsulates the socket protocol. * * Usage: - * struct stats_event* event = stats_event_obtain(); + * AStatsEvent* event = AStatsEvent_obtain(); * - * stats_event_set_atom_id(event, atomId); - * stats_event_write_int32(event, 24); - * stats_event_add_bool_annotation(event, 1, true); // annotations apply to the previous field - * stats_event_add_int32_annotation(event, 2, 128); - * stats_event_write_float(event, 2.0); + * AStatsEvent_setAtomId(event, atomId); + * AStatsEvent_addBoolAnnotation(event, 5, false); // atom-level annotation + * AStatsEvent_writeInt32(event, 24); + * AStatsEvent_addBoolAnnotation(event, 1, true); // annotation for preceding atom field + * AStatsEvent_addInt32Annotation(event, 2, 128); + * AStatsEvent_writeFloat(event, 2.0); * - * stats_event_build(event); - * stats_event_write(event); - * stats_event_release(event); + * AStatsEvent_write(event); + * AStatsEvent_release(event); * - * Notes: - * (a) write_<type>() and add_<type>_annotation() should be called in the order that fields - * and annotations are defined in the atom. - * (b) set_atom_id() can be called anytime before stats_event_write(). - * (c) add_<type>_annotation() calls apply to the previous field. - * (d) If errors occur, stats_event_write() will write a bitmask of the errors to the socket. - * (e) All strings should be encoded using UTF8. + * Note that calls to add atom fields and annotations should be made in the + * order that they are defined in the atom. */ -/* ERRORS */ -#define ERROR_NO_TIMESTAMP 0x1 -#define ERROR_NO_ATOM_ID 0x2 -#define ERROR_OVERFLOW 0x4 -#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8 -#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10 -#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20 -#define ERROR_INVALID_ANNOTATION_ID 0x40 -#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80 -#define ERROR_TOO_MANY_ANNOTATIONS 0x100 -#define ERROR_TOO_MANY_FIELDS 0x200 -#define ERROR_INVALID_VALUE_TYPE 0x400 -#define ERROR_STRING_NOT_NULL_TERMINATED 0x800 - -/* TYPE IDS */ -#define INT32_TYPE 0x00 -#define INT64_TYPE 0x01 -#define STRING_TYPE 0x02 -#define LIST_TYPE 0x03 -#define FLOAT_TYPE 0x04 -#define BOOL_TYPE 0x05 -#define BYTE_ARRAY_TYPE 0x06 -#define OBJECT_TYPE 0x07 -#define KEY_VALUE_PAIRS_TYPE 0x08 -#define ATTRIBUTION_CHAIN_TYPE 0x09 -#define ERROR_TYPE 0x0F - #ifdef __cplusplus extern "C" { #endif // __CPLUSPLUS -struct stats_event; - -/* SYSTEM API */ -struct stats_event* stats_event_obtain(); -// The build function can be called multiple times without error. If the event -// has been built before, this function is a no-op. -void stats_event_build(struct stats_event* event); -int stats_event_write(struct stats_event* event); -void stats_event_release(struct stats_event* event); +/** + * Opaque struct use to represent a StatsEvent. It builds and stores the data that is sent to + * statsd. + */ +struct AStatsEvent; +typedef struct AStatsEvent AStatsEvent; -void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId); +/** + * Returns a new AStatsEvent. If you call this function, you must call AStatsEvent_release to free + * the allocated memory. + */ +AStatsEvent* AStatsEvent_obtain(); -void stats_event_write_int32(struct stats_event* event, int32_t value); -void stats_event_write_int64(struct stats_event* event, int64_t value); -void stats_event_write_float(struct stats_event* event, float value); -void stats_event_write_bool(struct stats_event* event, bool value); +/** + * Builds and finalizes the AStatsEvent for a pulled event. + * This should only be called for pulled AStatsEvents. + * + * After this function, the StatsEvent must not be modified in any way other than calling release or + * write. + * + * Build can be called multiple times without error. + * If the event has been built before, this function is a no-op. + */ +void AStatsEvent_build(AStatsEvent* event); -void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes); +/** + * Writes the StatsEvent to the stats log. + * + * After calling this, AStatsEvent_release must be called, + * and is the only function that can be safely called. + */ +int AStatsEvent_write(AStatsEvent* event); -// Buf must be null-terminated. -void stats_event_write_string8(struct stats_event* event, const char* value); +/** + * Frees the memory held by this StatsEvent. + * + * After calling this, the StatsEvent must not be used or modified in any way. + */ +void AStatsEvent_release(AStatsEvent* event); -// Tags must be null-terminated. -void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids, - const char* const* tags, uint8_t numNodes); +/** + * Sets the atom id for this StatsEvent. + * + * This function should be called immediately after AStatsEvent_obtain. It may + * be called additional times as well, but subsequent calls will have no effect. + **/ +void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId); + +/** + * Writes an int32_t field to this StatsEvent. + **/ +void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value); + +/** + * Writes an int64_t field to this StatsEvent. + **/ +void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value); + +/** + * Writes a float field to this StatsEvent. + **/ +void AStatsEvent_writeFloat(AStatsEvent* event, float value); + +/** + * Write a bool field to this StatsEvent. + **/ +void AStatsEvent_writeBool(AStatsEvent* event, bool value); + +/** + * Write a byte array field to this StatsEvent. + **/ +void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes); + +/** + * Write a string field to this StatsEvent. + * + * The string must be null-terminated. + **/ +void AStatsEvent_writeString(AStatsEvent* event, const char* value); -/* key_value_pair struct can be constructed as follows: - * struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE, - * .stringValue = buf}; - */ -struct key_value_pair { - int32_t key; - uint8_t valueType; // expected to be INT32_TYPE, INT64_TYPE, FLOAT_TYPE, or STRING_TYPE - union { - int32_t int32Value; - int64_t int64Value; - float floatValue; - const char* stringValue; // must be null terminated - }; -}; - -void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs, - uint8_t numPairs); - -void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value); -void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId, - int32_t value); - -uint32_t stats_event_get_atom_id(struct stats_event* event); +/** + * Write an attribution chain field to this StatsEvent. + * + * The sizes of uids and tags must be equal. The AttributionNode at position i is + * made up of uids[i] and tags[i]. + * + * \param uids array of uids in the attribution chain. + * \param tags array of tags in the attribution chain. Each tag must be null-terminated. + * \param numNodes the number of AttributionNodes in the attribution chain. This is the length of + * the uids and the tags. + **/ +void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids, + const char* const* tags, uint8_t numNodes); + +/** + * Write a bool annotation for the previous field written. + **/ +void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value); + +/** + * Write an integer annotation for the previous field written. + **/ +void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value); + +// Internal/test APIs. Should not be exposed outside of the APEX. +void AStatsEvent_overwriteTimestamp(AStatsEvent* event, uint64_t timestampNs); +uint32_t AStatsEvent_getAtomId(AStatsEvent* event); // Size is an output parameter. -uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size); -uint32_t stats_event_get_errors(struct stats_event* event); - -// This table is used by StatsEventCompat to access the stats_event API. -struct stats_event_api_table { - struct stats_event* (*obtain)(void); - void (*build)(struct stats_event*); - int (*write)(struct stats_event*); - void (*release)(struct stats_event*); - void (*set_atom_id)(struct stats_event*, uint32_t); - void (*write_int32)(struct stats_event*, int32_t); - void (*write_int64)(struct stats_event*, int64_t); - void (*write_float)(struct stats_event*, float); - void (*write_bool)(struct stats_event*, bool); - void (*write_byte_array)(struct stats_event*, const uint8_t*, size_t); - void (*write_string8)(struct stats_event*, const char*); - void (*write_attribution_chain)(struct stats_event*, const uint32_t*, const char* const*, - uint8_t); - void (*write_key_value_pairs)(struct stats_event*, struct key_value_pair*, uint8_t); - void (*add_bool_annotation)(struct stats_event*, uint8_t, bool); - void (*add_int32_annotation)(struct stats_event*, uint8_t, int32_t); - uint32_t (*get_atom_id)(struct stats_event*); - uint8_t* (*get_buffer)(struct stats_event*, size_t*); - uint32_t (*get_errors)(struct stats_event*); -}; - -// exposed for benchmarking only -void stats_event_truncate_buffer(struct stats_event* event, bool truncate); +uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size); +uint32_t AStatsEvent_getErrors(AStatsEvent* event); #ifdef __cplusplus } diff --git a/libstats/socket/include/stats_event_list.h b/libstats/socket/include/stats_event_list.h deleted file mode 100644 index 7a26536d8..000000000 --- a/libstats/socket/include/stats_event_list.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2018, 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 <log/log_event_list.h> -#include <sys/uio.h> - -#ifdef __cplusplus -extern "C" { -#endif -void reset_log_context(android_log_context ctx); -int write_to_logger(android_log_context context, log_id_t id); -void note_log_drop(int error, int atomId); -void stats_log_close(); -int android_log_write_char_array(android_log_context ctx, const char* value, size_t len); -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -/** - * A copy of android_log_event_list class. - * - * android_log_event_list is going to be deprecated soon, so copy it here to - * avoid creating dependency on upstream code. TODO(b/78304629): Rewrite this - * code. - */ -class stats_event_list { - private: - android_log_context ctx; - int ret; - - stats_event_list(const stats_event_list&) = delete; - void operator=(const stats_event_list&) = delete; - - public: - explicit stats_event_list(int tag) : ret(0) { - ctx = create_android_logger(static_cast<uint32_t>(tag)); - } - ~stats_event_list() { android_log_destroy(&ctx); } - - int close() { - int retval = android_log_destroy(&ctx); - if (retval < 0) { - ret = retval; - } - return retval; - } - - /* To allow above C calls to use this class as parameter */ - operator android_log_context() const { return ctx; } - - /* return errors or transmit status */ - int status() const { return ret; } - - int begin() { - int retval = android_log_write_list_begin(ctx); - if (retval < 0) { - ret = retval; - } - return ret; - } - int end() { - int retval = android_log_write_list_end(ctx); - if (retval < 0) { - ret = retval; - } - return ret; - } - - stats_event_list& operator<<(int32_t value) { - int retval = android_log_write_int32(ctx, value); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(uint32_t value) { - int retval = android_log_write_int32(ctx, static_cast<int32_t>(value)); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(bool value) { - int retval = android_log_write_int32(ctx, value ? 1 : 0); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(int64_t value) { - int retval = android_log_write_int64(ctx, value); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(uint64_t value) { - int retval = android_log_write_int64(ctx, static_cast<int64_t>(value)); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(const char* value) { - int retval = android_log_write_string8(ctx, value); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(const std::string& value) { - int retval = android_log_write_string8_len(ctx, value.data(), value.length()); - if (retval < 0) { - ret = retval; - } - return *this; - } - - stats_event_list& operator<<(float value) { - int retval = android_log_write_float32(ctx, value); - if (retval < 0) { - ret = retval; - } - return *this; - } - - int write(log_id_t id = LOG_ID_EVENTS) { - /* facilitate -EBUSY retry */ - if ((ret == -EBUSY) || (ret > 0)) { - ret = 0; - } - int retval = write_to_logger(ctx, id); - /* existing errors trump transmission errors */ - if (!ret) { - ret = retval; - } - return ret; - } - - /* - * Append<Type> methods removes any integer promotion - * confusion, and adds access to string with length. - * Append methods are also added for all types for - * convenience. - */ - - bool AppendInt(int32_t value) { - int retval = android_log_write_int32(ctx, value); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - bool AppendLong(int64_t value) { - int retval = android_log_write_int64(ctx, value); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - bool AppendString(const char* value) { - int retval = android_log_write_string8(ctx, value); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - bool AppendString(const char* value, size_t len) { - int retval = android_log_write_string8_len(ctx, value, len); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - bool AppendString(const std::string& value) { - int retval = android_log_write_string8_len(ctx, value.data(), value.length()); - if (retval < 0) { - ret = retval; - } - return ret; - } - - bool Append(const std::string& value) { - int retval = android_log_write_string8_len(ctx, value.data(), value.length()); - if (retval < 0) { - ret = retval; - } - return ret; - } - - bool AppendFloat(float value) { - int retval = android_log_write_float32(ctx, value); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - template <typename Tvalue> - bool Append(Tvalue value) { - *this << value; - return ret >= 0; - } - - bool Append(const char* value, size_t len) { - int retval = android_log_write_string8_len(ctx, value, len); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } - - bool AppendCharArray(const char* value, size_t len) { - int retval = android_log_write_char_array(ctx, value, len); - if (retval < 0) { - ret = retval; - } - return ret >= 0; - } -}; - -#endif diff --git a/libstats/socket/include/stats_socket.h b/libstats/socket/include/stats_socket.h new file mode 100644 index 000000000..5a75fc021 --- /dev/null +++ b/libstats/socket/include/stats_socket.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#pragma once + +/** + * Helpers to manage the statsd socket. + **/ + +#ifdef __cplusplus +extern "C" { +#endif // __CPLUSPLUS + +/** + * Closes the statsd socket file descriptor. + **/ +void AStatsSocket_close(); +#ifdef __cplusplus +} +#endif // __CPLUSPLUS diff --git a/libstats/socket/libstatssocket.map.txt b/libstats/socket/libstatssocket.map.txt index 55bfbda66..5c1390419 100644 --- a/libstats/socket/libstatssocket.map.txt +++ b/libstats/socket/libstatssocket.map.txt @@ -1,23 +1,20 @@ LIBSTATSSOCKET { global: - stats_event_obtain; # apex # introduced=1 - stats_event_build; # apex # introduced=1 - stats_event_write; # apex # introduced=1 - stats_event_release; # apex # introduced=1 - stats_event_set_atom_id; # apex # introduced=1 - stats_event_write_int32; # apex # introduced=1 - stats_event_write_int64; # apex # introduced=1 - stats_event_write_float; # apex # introduced=1 - stats_event_write_bool; # apex # introduced=1 - stats_event_write_byte_array; # apex # introduced=1 - stats_event_write_string8; # apex # introduced=1 - stats_event_write_attribution_chain; # apex # introduced=1 - stats_event_write_key_value_pairs; # apex # introduced=1 - stats_event_add_bool_annotation; # apex # introduced=1 - stats_event_add_int32_annotation; # apex # introduced=1 - stats_event_get_atom_id; # apex # introduced=1 - stats_event_get_buffer; # apex # introduced=1 - stats_event_get_errors; # apex # introduced=1 + AStatsEvent_obtain; # apex # introduced=30 + AStatsEvent_build; # apex # introduced=30 + AStatsEvent_write; # apex # introduced=30 + AStatsEvent_release; # apex # introduced=30 + AStatsEvent_setAtomId; # apex # introduced=30 + AStatsEvent_writeInt32; # apex # introduced=30 + AStatsEvent_writeInt64; # apex # introduced=30 + AStatsEvent_writeFloat; # apex # introduced=30 + AStatsEvent_writeBool; # apex # introduced=30 + AStatsEvent_writeByteArray; # apex # introduced=30 + AStatsEvent_writeString; # apex # introduced=30 + AStatsEvent_writeAttributionChain; # apex # introduced=30 + AStatsEvent_addBoolAnnotation; # apex # introduced=30 + AStatsEvent_addInt32Annotation; # apex # introduced=30 + AStatsSocket_close; # apex # introduced=30 local: *; }; diff --git a/libstats/socket/libstatssocket_test.xml b/libstats/socket/libstatssocket_test.xml new file mode 100644 index 000000000..d2694d1dd --- /dev/null +++ b/libstats/socket/libstatssocket_test.xml @@ -0,0 +1,38 @@ +<?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. +--> +<configuration description="Runs libstatssocket_test."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-native" /> + <option name="test-suite-tag" value="mts" /> + + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="cleanup" value="true" /> + <option name="push" value="libstatssocket_test->/data/local/tmp/libstatssocket_test" /> + <option name="append-bitness" value="true" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="module-name" value="libstatssocket_test" /> + </test> + + <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> + <option name="mainline-module-package-name" value="com.google.android.os.statsd" /> + </object> +</configuration> + diff --git a/libstats/socket/stats_buffer_writer.c b/libstats/socket/stats_buffer_writer.c index c5c591d78..549acdc8e 100644 --- a/libstats/socket/stats_buffer_writer.c +++ b/libstats/socket/stats_buffer_writer.c @@ -43,27 +43,23 @@ void stats_log_close() { statsd_writer_init_unlock(); } +int stats_log_is_closed() { + return statsdLoggerWrite.isClosed && (*statsdLoggerWrite.isClosed)(); +} + int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) { int ret = 1; -#ifdef __ANDROID__ - bool statsdEnabled = property_get_bool("ro.statsd.enable", true); -#else - bool statsdEnabled = false; -#endif - - if (statsdEnabled) { - struct iovec vecs[2]; - vecs[0].iov_base = (void*)&kStatsEventTag; - vecs[0].iov_len = sizeof(kStatsEventTag); - vecs[1].iov_base = buffer; - vecs[1].iov_len = size; + struct iovec vecs[2]; + vecs[0].iov_base = (void*)&kStatsEventTag; + vecs[0].iov_len = sizeof(kStatsEventTag); + vecs[1].iov_base = buffer; + vecs[1].iov_len = size; - ret = __write_to_statsd(vecs, 2); + ret = __write_to_statsd(vecs, 2); - if (ret < 0) { - note_log_drop(ret, atomId); - } + if (ret < 0) { + note_log_drop(ret, atomId); } return ret; diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c index 15039c63d..f3e808756 100644 --- a/libstats/socket/stats_event.c +++ b/libstats/socket/stats_event.c @@ -23,29 +23,61 @@ #define LOGGER_ENTRY_MAX_PAYLOAD 4068 // Max payload size is 4 bytes less as 4 bytes are reserved for stats_eventTag. // See android_util_Stats_Log.cpp -#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - 4) +#define MAX_PUSH_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - 4) + +#define MAX_PULL_EVENT_PAYLOAD (50 * 1024) // 50 KB /* POSITIONS */ #define POS_NUM_ELEMENTS 1 #define POS_TIMESTAMP (POS_NUM_ELEMENTS + sizeof(uint8_t)) #define POS_ATOM_ID (POS_TIMESTAMP + sizeof(uint8_t) + sizeof(uint64_t)) -#define POS_FIRST_FIELD (POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t)) /* LIMITS */ #define MAX_ANNOTATION_COUNT 15 #define MAX_BYTE_VALUE 127 // parsing side requires that lengths fit in 7 bits -// The stats_event struct holds the serialized encoding of an event +/* ERRORS */ +#define ERROR_NO_TIMESTAMP 0x1 +#define ERROR_NO_ATOM_ID 0x2 +#define ERROR_OVERFLOW 0x4 +#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8 +#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10 +#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20 +#define ERROR_INVALID_ANNOTATION_ID 0x40 +#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80 +#define ERROR_TOO_MANY_ANNOTATIONS 0x100 +#define ERROR_TOO_MANY_FIELDS 0x200 +#define ERROR_INVALID_VALUE_TYPE 0x400 +#define ERROR_STRING_NOT_NULL_TERMINATED 0x800 +#define ERROR_ATOM_ID_INVALID_POSITION 0x2000 + +/* TYPE IDS */ +#define INT32_TYPE 0x00 +#define INT64_TYPE 0x01 +#define STRING_TYPE 0x02 +#define LIST_TYPE 0x03 +#define FLOAT_TYPE 0x04 +#define BOOL_TYPE 0x05 +#define BYTE_ARRAY_TYPE 0x06 +#define OBJECT_TYPE 0x07 +#define KEY_VALUE_PAIRS_TYPE 0x08 +#define ATTRIBUTION_CHAIN_TYPE 0x09 +#define ERROR_TYPE 0x0F + +// The AStatsEvent struct holds the serialized encoding of an event // within a buf. Also includes other required fields. -struct stats_event { +struct AStatsEvent { uint8_t* buf; - size_t lastFieldPos; // location of last field within the buf - size_t size; // number of valid bytes within buffer + // Location of last field within the buf. Here, field denotes either a + // metadata field (e.g. timestamp) or an atom field. + size_t lastFieldPos; + // Number of valid bytes within the buffer. + size_t numBytesWritten; uint32_t numElements; uint32_t atomId; uint32_t errors; - bool truncate; bool built; + size_t bufSize; }; static int64_t get_elapsed_realtime_ns() { @@ -55,93 +87,115 @@ static int64_t get_elapsed_realtime_ns() { return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec; } -struct stats_event* stats_event_obtain() { - struct stats_event* event = malloc(sizeof(struct stats_event)); - event->buf = (uint8_t*)calloc(MAX_EVENT_PAYLOAD, 1); - event->buf[0] = OBJECT_TYPE; +AStatsEvent* AStatsEvent_obtain() { + AStatsEvent* event = malloc(sizeof(AStatsEvent)); + event->lastFieldPos = 0; + event->numBytesWritten = 2; // reserve first 2 bytes for root event type and number of elements + event->numElements = 0; event->atomId = 0; event->errors = 0; - event->truncate = true; // truncate for both pulled and pushed atoms event->built = false; + event->bufSize = MAX_PUSH_EVENT_PAYLOAD; + event->buf = (uint8_t*)calloc(event->bufSize, 1); - // place the timestamp - uint64_t timestampNs = get_elapsed_realtime_ns(); - event->buf[POS_TIMESTAMP] = INT64_TYPE; - memcpy(&event->buf[POS_TIMESTAMP + sizeof(uint8_t)], ×tampNs, sizeof(timestampNs)); - - event->numElements = 1; - event->lastFieldPos = 0; // 0 since we haven't written a field yet - event->size = POS_FIRST_FIELD; + event->buf[0] = OBJECT_TYPE; + AStatsEvent_writeInt64(event, get_elapsed_realtime_ns()); // write the timestamp return event; } -void stats_event_release(struct stats_event* event) { +void AStatsEvent_release(AStatsEvent* event) { free(event->buf); free(event); } -void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId) { +void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId) { + if (event->atomId != 0) return; + if (event->numElements != 1) { + event->errors |= ERROR_ATOM_ID_INVALID_POSITION; + return; + } + event->atomId = atomId; - event->buf[POS_ATOM_ID] = INT32_TYPE; - memcpy(&event->buf[POS_ATOM_ID + sizeof(uint8_t)], &atomId, sizeof(atomId)); - event->numElements++; + AStatsEvent_writeInt32(event, atomId); +} + +// Overwrites the timestamp populated in AStatsEvent_obtain with a custom +// timestamp. Should only be called from test code. +void AStatsEvent_overwriteTimestamp(AStatsEvent* event, uint64_t timestampNs) { + memcpy(&event->buf[POS_TIMESTAMP + sizeof(uint8_t)], ×tampNs, sizeof(timestampNs)); + // Do not increment numElements because we already accounted for the timestamp + // within AStatsEvent_obtain. } // Side-effect: modifies event->errors if the buffer would overflow -static bool overflows(struct stats_event* event, size_t size) { - if (event->size + size > MAX_EVENT_PAYLOAD) { +static bool overflows(AStatsEvent* event, size_t size) { + const size_t totalBytesNeeded = event->numBytesWritten + size; + if (totalBytesNeeded > MAX_PULL_EVENT_PAYLOAD) { event->errors |= ERROR_OVERFLOW; return true; } + + // Expand buffer if needed. + if (event->bufSize < MAX_PULL_EVENT_PAYLOAD && totalBytesNeeded > event->bufSize) { + do { + event->bufSize *= 2; + } while (event->bufSize <= totalBytesNeeded); + + if (event->bufSize > MAX_PULL_EVENT_PAYLOAD) { + event->bufSize = MAX_PULL_EVENT_PAYLOAD; + } + + event->buf = (uint8_t*)realloc(event->buf, event->bufSize); + } return false; } -// Side-effect: all append functions increment event->size if there is +// Side-effect: all append functions increment event->numBytesWritten if there is // sufficient space within the buffer to place the value -static void append_byte(struct stats_event* event, uint8_t value) { +static void append_byte(AStatsEvent* event, uint8_t value) { if (!overflows(event, sizeof(value))) { - event->buf[event->size] = value; - event->size += sizeof(value); + event->buf[event->numBytesWritten] = value; + event->numBytesWritten += sizeof(value); } } -static void append_bool(struct stats_event* event, bool value) { +static void append_bool(AStatsEvent* event, bool value) { append_byte(event, (uint8_t)value); } -static void append_int32(struct stats_event* event, int32_t value) { +static void append_int32(AStatsEvent* event, int32_t value) { if (!overflows(event, sizeof(value))) { - memcpy(&event->buf[event->size], &value, sizeof(value)); - event->size += sizeof(value); + memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value)); + event->numBytesWritten += sizeof(value); } } -static void append_int64(struct stats_event* event, int64_t value) { +static void append_int64(AStatsEvent* event, int64_t value) { if (!overflows(event, sizeof(value))) { - memcpy(&event->buf[event->size], &value, sizeof(value)); - event->size += sizeof(value); + memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value)); + event->numBytesWritten += sizeof(value); } } -static void append_float(struct stats_event* event, float value) { +static void append_float(AStatsEvent* event, float value) { if (!overflows(event, sizeof(value))) { - memcpy(&event->buf[event->size], &value, sizeof(value)); - event->size += sizeof(float); + memcpy(&event->buf[event->numBytesWritten], &value, sizeof(value)); + event->numBytesWritten += sizeof(float); } } -static void append_byte_array(struct stats_event* event, const uint8_t* buf, size_t size) { +static void append_byte_array(AStatsEvent* event, const uint8_t* buf, size_t size) { if (!overflows(event, size)) { - memcpy(&event->buf[event->size], buf, size); - event->size += size; + memcpy(&event->buf[event->numBytesWritten], buf, size); + event->numBytesWritten += size; } } // Side-effect: modifies event->errors if buf is not properly null-terminated -static void append_string(struct stats_event* event, const char* buf) { - size_t size = strnlen(buf, MAX_EVENT_PAYLOAD); - if (size == MAX_EVENT_PAYLOAD) { +static void append_string(AStatsEvent* event, const char* buf) { + size_t size = strnlen(buf, MAX_PULL_EVENT_PAYLOAD); + if (size == MAX_PULL_EVENT_PAYLOAD) { event->errors |= ERROR_STRING_NOT_NULL_TERMINATED; return; } @@ -150,61 +204,51 @@ static void append_string(struct stats_event* event, const char* buf) { append_byte_array(event, (uint8_t*)buf, size); } -static void start_field(struct stats_event* event, uint8_t typeId) { - event->lastFieldPos = event->size; +static void start_field(AStatsEvent* event, uint8_t typeId) { + event->lastFieldPos = event->numBytesWritten; append_byte(event, typeId); event->numElements++; } -void stats_event_write_int32(struct stats_event* event, int32_t value) { - if (event->errors) return; - +void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value) { start_field(event, INT32_TYPE); append_int32(event, value); } -void stats_event_write_int64(struct stats_event* event, int64_t value) { - if (event->errors) return; - +void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value) { start_field(event, INT64_TYPE); append_int64(event, value); } -void stats_event_write_float(struct stats_event* event, float value) { - if (event->errors) return; - +void AStatsEvent_writeFloat(AStatsEvent* event, float value) { start_field(event, FLOAT_TYPE); append_float(event, value); } -void stats_event_write_bool(struct stats_event* event, bool value) { - if (event->errors) return; - +void AStatsEvent_writeBool(AStatsEvent* event, bool value) { start_field(event, BOOL_TYPE); append_bool(event, value); } -void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes) { - if (event->errors) return; - +void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes) { start_field(event, BYTE_ARRAY_TYPE); append_int32(event, numBytes); append_byte_array(event, buf, numBytes); } // Value is assumed to be encoded using UTF8 -void stats_event_write_string8(struct stats_event* event, const char* value) { - if (event->errors) return; - +void AStatsEvent_writeString(AStatsEvent* event, const char* value) { start_field(event, STRING_TYPE); append_string(event, value); } // Tags are assumed to be encoded using UTF8 -void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids, - const char* const* tags, uint8_t numNodes) { - if (numNodes > MAX_BYTE_VALUE) event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; - if (event->errors) return; +void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids, + const char* const* tags, uint8_t numNodes) { + if (numNodes > MAX_BYTE_VALUE) { + event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; + return; + } start_field(event, ATTRIBUTION_CHAIN_TYPE); append_byte(event, numNodes); @@ -215,39 +259,8 @@ void stats_event_write_attribution_chain(struct stats_event* event, const uint32 } } -void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs, - uint8_t numPairs) { - if (numPairs > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_KEY_VALUE_PAIRS; - if (event->errors) return; - - start_field(event, KEY_VALUE_PAIRS_TYPE); - append_byte(event, numPairs); - - for (uint8_t i = 0; i < numPairs; i++) { - append_int32(event, pairs[i].key); - append_byte(event, pairs[i].valueType); - switch (pairs[i].valueType) { - case INT32_TYPE: - append_int32(event, pairs[i].int32Value); - break; - case INT64_TYPE: - append_int64(event, pairs[i].int64Value); - break; - case FLOAT_TYPE: - append_float(event, pairs[i].floatValue); - break; - case STRING_TYPE: - append_string(event, pairs[i].stringValue); - break; - default: - event->errors |= ERROR_INVALID_VALUE_TYPE; - return; - } - } -} - // Side-effect: modifies event->errors if field has too many annotations -static void increment_annotation_count(struct stats_event* event) { +static void increment_annotation_count(AStatsEvent* event) { uint8_t fieldType = event->buf[event->lastFieldPos] & 0x0F; uint32_t oldAnnotationCount = (event->buf[event->lastFieldPos] & 0xF0) >> 4; uint32_t newAnnotationCount = oldAnnotationCount + 1; @@ -260,10 +273,14 @@ static void increment_annotation_count(struct stats_event* event) { event->buf[event->lastFieldPos] = (((uint8_t)newAnnotationCount << 4) & 0xF0) | fieldType; } -void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value) { - if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE; - if (event->errors) return; +void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value) { + if (event->numElements < 2) { + event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; + return; + } else if (annotationId > MAX_BYTE_VALUE) { + event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE; + return; + } append_byte(event, annotationId); append_byte(event, BOOL_TYPE); @@ -271,11 +288,14 @@ void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotati increment_annotation_count(event); } -void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId, - int32_t value) { - if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE; - if (event->errors) return; +void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value) { + if (event->numElements < 2) { + event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; + return; + } else if (annotationId > MAX_BYTE_VALUE) { + event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE; + return; + } append_byte(event, annotationId); append_byte(event, INT32_TYPE); @@ -283,72 +303,49 @@ void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotat increment_annotation_count(event); } -uint32_t stats_event_get_atom_id(struct stats_event* event) { +uint32_t AStatsEvent_getAtomId(AStatsEvent* event) { return event->atomId; } -uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size) { - if (size) *size = event->size; +uint8_t* AStatsEvent_getBuffer(AStatsEvent* event, size_t* size) { + if (size) *size = event->numBytesWritten; return event->buf; } -uint32_t stats_event_get_errors(struct stats_event* event) { +uint32_t AStatsEvent_getErrors(AStatsEvent* event) { return event->errors; } -void stats_event_truncate_buffer(struct stats_event* event, bool truncate) { - event->truncate = truncate; -} - -void stats_event_build(struct stats_event* event) { - if (event->built) return; - - if (event->atomId == 0) event->errors |= ERROR_NO_ATOM_ID; - - if (event->numElements > MAX_BYTE_VALUE) { - event->errors |= ERROR_TOO_MANY_FIELDS; - } else { - event->buf[POS_NUM_ELEMENTS] = event->numElements; - } +static void build_internal(AStatsEvent* event, const bool push) { + if (event->numElements > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_FIELDS; + if (0 == event->atomId) event->errors |= ERROR_NO_ATOM_ID; + if (push && event->numBytesWritten > MAX_PUSH_EVENT_PAYLOAD) event->errors |= ERROR_OVERFLOW; // If there are errors, rewrite buffer. if (event->errors) { - event->buf[POS_NUM_ELEMENTS] = 3; - event->buf[POS_FIRST_FIELD] = ERROR_TYPE; - memcpy(&event->buf[POS_FIRST_FIELD + sizeof(uint8_t)], &event->errors, - sizeof(event->errors)); - event->size = POS_FIRST_FIELD + sizeof(uint8_t) + sizeof(uint32_t); + // Discard everything after the atom id (including atom-level + // annotations). This leaves only two elements (timestamp and atom id). + event->numElements = 2; + // Reset number of atom-level annotations to 0. + event->buf[POS_ATOM_ID] = INT32_TYPE; + // Now, write errors to the buffer immediately after the atom id. + event->numBytesWritten = POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t); + start_field(event, ERROR_TYPE); + append_int32(event, event->errors); } - // Truncate the buffer to the appropriate length in order to limit our - // memory usage. - if (event->truncate) event->buf = (uint8_t*)realloc(event->buf, event->size); + event->buf[POS_NUM_ELEMENTS] = event->numElements; +} + +void AStatsEvent_build(AStatsEvent* event) { + if (event->built) return; + + build_internal(event, false /* push */); event->built = true; } -int stats_event_write(struct stats_event* event) { - stats_event_build(event); - return write_buffer_to_statsd(&event->buf, event->size, event->atomId); +int AStatsEvent_write(AStatsEvent* event) { + build_internal(event, true /* push */); + return write_buffer_to_statsd(event->buf, event->numBytesWritten, event->atomId); } - -struct stats_event_api_table table = { - stats_event_obtain, - stats_event_build, - stats_event_write, - stats_event_release, - stats_event_set_atom_id, - stats_event_write_int32, - stats_event_write_int64, - stats_event_write_float, - stats_event_write_bool, - stats_event_write_byte_array, - stats_event_write_string8, - stats_event_write_attribution_chain, - stats_event_write_key_value_pairs, - stats_event_add_bool_annotation, - stats_event_add_int32_annotation, - stats_event_get_atom_id, - stats_event_get_buffer, - stats_event_get_errors, -}; diff --git a/libstats/socket/stats_event_list.c b/libstats/socket/stats_event_list.c deleted file mode 100644 index 661a2237f..000000000 --- a/libstats/socket/stats_event_list.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2018, 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 "include/stats_event_list.h" - -#include <string.h> -#include <sys/time.h> -#include "stats_buffer_writer.h" - -#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t)) - -typedef struct { - uint32_t tag; - unsigned pos; /* Read/write position into buffer */ - unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */ - unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */ - unsigned list_nest_depth; - unsigned len; /* Length or raw buffer. */ - bool overflow; - bool list_stop; /* next call decrement list_nest_depth and issue a stop */ - enum { - kAndroidLoggerRead = 1, - kAndroidLoggerWrite = 2, - } read_write_flag; - uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD]; -} android_log_context_internal; - -// Similar to create_android_logger(), but instead of allocation a new buffer, -// this function resets the buffer for resuse. -void reset_log_context(android_log_context ctx) { - if (!ctx) { - return; - } - android_log_context_internal* context = (android_log_context_internal*)(ctx); - uint32_t tag = context->tag; - memset(context, 0, sizeof(android_log_context_internal)); - - context->tag = tag; - context->read_write_flag = kAndroidLoggerWrite; - size_t needed = sizeof(uint8_t) + sizeof(uint8_t); - if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { - context->overflow = true; - } - /* Everything is a list */ - context->storage[context->pos + 0] = EVENT_TYPE_LIST; - context->list[0] = context->pos + 1; - context->pos += needed; -} - -int stats_write_list(android_log_context ctx) { - android_log_context_internal* context; - const char* msg; - ssize_t len; - - context = (android_log_context_internal*)(ctx); - if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { - return -EBADF; - } - - if (context->list_nest_depth) { - return -EIO; - } - - /* NB: if there was overflow, then log is truncated. Nothing reported */ - context->storage[1] = context->count[0]; - len = context->len = context->pos; - msg = (const char*)context->storage; - /* it's not a list */ - if (context->count[0] <= 1) { - len -= sizeof(uint8_t) + sizeof(uint8_t); - if (len < 0) { - len = 0; - } - msg += sizeof(uint8_t) + sizeof(uint8_t); - } - - return write_buffer_to_statsd((void*)msg, len, 0); -} - -int write_to_logger(android_log_context ctx, log_id_t id) { - int retValue = 0; - - if (WRITE_TO_LOGD) { - retValue = android_log_write_list(ctx, id); - } - - if (WRITE_TO_STATSD) { - // log_event_list's cast operator is overloaded. - int ret = stats_write_list(ctx); - // In debugging phase, we may write to both logd and statsd. Prefer to - // return statsd socket write error code here. - if (ret < 0) { - retValue = ret; - } - } - - return retValue; -} - -static inline void copy4LE(uint8_t* buf, uint32_t val) { - buf[0] = val & 0xFF; - buf[1] = (val >> 8) & 0xFF; - buf[2] = (val >> 16) & 0xFF; - buf[3] = (val >> 24) & 0xFF; -} - -// Note: this function differs from android_log_write_string8_len in that the length passed in -// should be treated as actual length and not max length. -int android_log_write_char_array(android_log_context ctx, const char* value, size_t actual_len) { - size_t needed; - ssize_t len = actual_len; - android_log_context_internal* context; - - context = (android_log_context_internal*)ctx; - if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { - return -EBADF; - } - if (context->overflow) { - return -EIO; - } - if (!value) { - value = ""; - len = 0; - } - needed = sizeof(uint8_t) + sizeof(int32_t) + len; - if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { - /* Truncate string for delivery */ - len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t); - if (len <= 0) { - context->overflow = true; - return -EIO; - } - } - context->count[context->list_nest_depth]++; - context->storage[context->pos + 0] = EVENT_TYPE_STRING; - copy4LE(&context->storage[context->pos + 1], len); - if (len) { - memcpy(&context->storage[context->pos + 5], value, len); - } - context->pos += needed; - return len; -} diff --git a/libstats/socket/benchmark/main.cpp b/libstats/socket/stats_socket.c index 5ebdf6e9a..09f8967b0 100644 --- a/libstats/socket/benchmark/main.cpp +++ b/libstats/socket/stats_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * 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. @@ -14,6 +14,9 @@ * limitations under the License. */ -#include <benchmark/benchmark.h> +#include "include/stats_socket.h" +#include "stats_buffer_writer.h" -BENCHMARK_MAIN(); +void AStatsSocket_close() { + stats_log_close(); +} diff --git a/libstats/socket/statsd_writer.c b/libstats/socket/statsd_writer.c index 04d3b4644..73b7a7e71 100644 --- a/libstats/socket/statsd_writer.c +++ b/libstats/socket/statsd_writer.c @@ -62,6 +62,7 @@ static int statsdOpen(); static void statsdClose(); static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr); static void statsdNoteDrop(); +static int statsdIsClosed(); struct android_log_transport_write statsdLoggerWrite = { .name = "statsd", @@ -71,6 +72,7 @@ struct android_log_transport_write statsdLoggerWrite = { .close = statsdClose, .write = statsdWrite, .noteDrop = statsdNoteDrop, + .isClosed = statsdIsClosed, }; /* log_init_lock assumed */ @@ -153,6 +155,13 @@ static void statsdNoteDrop(int error, int tag) { atomic_exchange_explicit(&atom_tag, tag, memory_order_relaxed); } +static int statsdIsClosed() { + if (atomic_load(&statsdLoggerWrite.sock) < 0) { + return 1; + } + return 0; +} + static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr) { ssize_t ret; int sock; diff --git a/libstats/socket/statsd_writer.h b/libstats/socket/statsd_writer.h index fe2d37cbc..562bda5df 100644 --- a/libstats/socket/statsd_writer.h +++ b/libstats/socket/statsd_writer.h @@ -40,6 +40,8 @@ struct android_log_transport_write { int (*write)(struct timespec* ts, struct iovec* vec, size_t nr); /* note one log drop */ void (*noteDrop)(int error, int tag); + /* checks if the socket is closed */ + int (*isClosed)(); }; #endif // ANDROID_STATS_LOG_STATS_WRITER_H diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp index cf0592c3a..9a1fac89f 100644 --- a/libstats/socket/tests/stats_event_test.cpp +++ b/libstats/socket/tests/stats_event_test.cpp @@ -18,13 +18,47 @@ #include <gtest/gtest.h> #include <utils/SystemClock.h> +// Keep in sync with stats_event.c. Consider moving to separate header file to avoid duplication. +/* ERRORS */ +#define ERROR_NO_TIMESTAMP 0x1 +#define ERROR_NO_ATOM_ID 0x2 +#define ERROR_OVERFLOW 0x4 +#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8 +#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10 +#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20 +#define ERROR_INVALID_ANNOTATION_ID 0x40 +#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80 +#define ERROR_TOO_MANY_ANNOTATIONS 0x100 +#define ERROR_TOO_MANY_FIELDS 0x200 +#define ERROR_INVALID_VALUE_TYPE 0x400 +#define ERROR_STRING_NOT_NULL_TERMINATED 0x800 +#define ERROR_ATOM_ID_INVALID_POSITION 0x2000 + +/* TYPE IDS */ +#define INT32_TYPE 0x00 +#define INT64_TYPE 0x01 +#define STRING_TYPE 0x02 +#define LIST_TYPE 0x03 +#define FLOAT_TYPE 0x04 +#define BOOL_TYPE 0x05 +#define BYTE_ARRAY_TYPE 0x06 +#define OBJECT_TYPE 0x07 +#define KEY_VALUE_PAIRS_TYPE 0x08 +#define ATTRIBUTION_CHAIN_TYPE 0x09 +#define ERROR_TYPE 0x0F + using std::string; using std::vector; // Side-effect: this function moves the start of the buffer past the read value template <class T> T readNext(uint8_t** buffer) { - T value = *(T*)(*buffer); + T value; + if ((reinterpret_cast<uintptr_t>(*buffer) % alignof(T)) == 0) { + value = *(T*)(*buffer); + } else { + memcpy(&value, *buffer, sizeof(T)); + } *buffer += sizeof(T); return value; } @@ -61,7 +95,7 @@ void checkAnnotation(uint8_t** buffer, uint8_t annotationId, uint8_t typeId, T a } void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int64_t endTime, - uint32_t atomId) { + uint32_t atomId, uint8_t numAtomLevelAnnotations = 0) { // All events start with OBJECT_TYPE id. checkTypeHeader(buffer, OBJECT_TYPE); @@ -76,7 +110,7 @@ void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int EXPECT_LE(timestamp, endTime); // Check atom id - checkTypeHeader(buffer, INT32_TYPE); + checkTypeHeader(buffer, INT32_TYPE, numAtomLevelAnnotations); checkScalar(buffer, atomId); } @@ -88,17 +122,17 @@ TEST(StatsEventTest, TestScalars) { bool boolValue = false; int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, atomId); - stats_event_write_int32(event, int32Value); - stats_event_write_int64(event, int64Value); - stats_event_write_float(event, floatValue); - stats_event_write_bool(event, boolValue); - stats_event_build(event); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_writeInt32(event, int32Value); + AStatsEvent_writeInt64(event, int64Value); + AStatsEvent_writeFloat(event, floatValue); + AStatsEvent_writeBool(event, boolValue); + AStatsEvent_build(event); int64_t endTime = android::elapsedRealtimeNano(); size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); uint8_t* bufferEnd = buffer + bufferSize; checkMetadata(&buffer, /*numElements=*/4, startTime, endTime, atomId); @@ -120,8 +154,8 @@ TEST(StatsEventTest, TestScalars) { checkScalar(&buffer, boolValue); EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } TEST(StatsEventTest, TestStrings) { @@ -129,14 +163,14 @@ TEST(StatsEventTest, TestStrings) { string str = "test_string"; int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, atomId); - stats_event_write_string8(event, str.c_str()); - stats_event_build(event); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_writeString(event, str.c_str()); + AStatsEvent_build(event); int64_t endTime = android::elapsedRealtimeNano(); size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); uint8_t* bufferEnd = buffer + bufferSize; checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId); @@ -145,8 +179,8 @@ TEST(StatsEventTest, TestStrings) { checkString(&buffer, str); EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } TEST(StatsEventTest, TestByteArrays) { @@ -154,14 +188,14 @@ TEST(StatsEventTest, TestByteArrays) { vector<uint8_t> message = {'b', 'y', 't', '\0', 'e', 's'}; int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, atomId); - stats_event_write_byte_array(event, message.data(), message.size()); - stats_event_build(event); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_writeByteArray(event, message.data(), message.size()); + AStatsEvent_build(event); int64_t endTime = android::elapsedRealtimeNano(); size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); uint8_t* bufferEnd = buffer + bufferSize; checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId); @@ -170,8 +204,8 @@ TEST(StatsEventTest, TestByteArrays) { checkByteArray(&buffer, message); EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } TEST(StatsEventTest, TestAttributionChains) { @@ -188,14 +222,14 @@ TEST(StatsEventTest, TestAttributionChains) { } int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, atomId); - stats_event_write_attribution_chain(event, uids, cTags, numNodes); - stats_event_build(event); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes); + AStatsEvent_build(event); int64_t endTime = android::elapsedRealtimeNano(); size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); uint8_t* bufferEnd = buffer + bufferSize; checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId); @@ -208,63 +242,11 @@ TEST(StatsEventTest, TestAttributionChains) { } EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); -} - -TEST(StatsEventTest, TestKeyValuePairs) { - uint32_t atomId = 100; - - uint8_t numPairs = 4; - struct key_value_pair pairs[numPairs]; - pairs[0] = {.key = 0, .valueType = INT32_TYPE, .int32Value = -1}; - pairs[1] = {.key = 1, .valueType = INT64_TYPE, .int64Value = 0x123456789}; - pairs[2] = {.key = 2, .valueType = FLOAT_TYPE, .floatValue = 5.5}; - string str = "test_key_value_pair_string"; - pairs[3] = {.key = 3, .valueType = STRING_TYPE, .stringValue = str.c_str()}; - - int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, atomId); - stats_event_write_key_value_pairs(event, pairs, numPairs); - stats_event_build(event); - int64_t endTime = android::elapsedRealtimeNano(); - - size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); - uint8_t* bufferEnd = buffer + bufferSize; - - checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId); - - checkTypeHeader(&buffer, KEY_VALUE_PAIRS_TYPE); - checkScalar(&buffer, numPairs); - - // first pair - checkScalar(&buffer, pairs[0].key); - checkTypeHeader(&buffer, pairs[0].valueType); - checkScalar(&buffer, pairs[0].int32Value); - - // second pair - checkScalar(&buffer, pairs[1].key); - checkTypeHeader(&buffer, pairs[1].valueType); - checkScalar(&buffer, pairs[1].int64Value); - - // third pair - checkScalar(&buffer, pairs[2].key); - checkTypeHeader(&buffer, pairs[2].valueType); - checkScalar(&buffer, pairs[2].floatValue); - - // fourth pair - checkScalar(&buffer, pairs[3].key); - checkTypeHeader(&buffer, pairs[3].valueType); - checkString(&buffer, str); - - EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } -TEST(StatsEventTest, TestAnnotations) { +TEST(StatsEventTest, TestFieldAnnotations) { uint32_t atomId = 100; // first element information @@ -282,19 +264,19 @@ TEST(StatsEventTest, TestAnnotations) { bool floatAnnotation2Value = false; int64_t startTime = android::elapsedRealtimeNano(); - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, 100); - stats_event_write_bool(event, boolValue); - stats_event_add_bool_annotation(event, boolAnnotation1Id, boolAnnotation1Value); - stats_event_add_int32_annotation(event, boolAnnotation2Id, boolAnnotation2Value); - stats_event_write_float(event, floatValue); - stats_event_add_int32_annotation(event, floatAnnotation1Id, floatAnnotation1Value); - stats_event_add_bool_annotation(event, floatAnnotation2Id, floatAnnotation2Value); - stats_event_build(event); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_writeBool(event, boolValue); + AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value); + AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value); + AStatsEvent_writeFloat(event, floatValue); + AStatsEvent_addInt32Annotation(event, floatAnnotation1Id, floatAnnotation1Value); + AStatsEvent_addBoolAnnotation(event, floatAnnotation2Id, floatAnnotation2Value); + AStatsEvent_build(event); int64_t endTime = android::elapsedRealtimeNano(); size_t bufferSize; - uint8_t* buffer = stats_event_get_buffer(event, &bufferSize); + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); uint8_t* bufferEnd = buffer + bufferSize; checkMetadata(&buffer, /*numElements=*/2, startTime, endTime, atomId); @@ -312,33 +294,167 @@ TEST(StatsEventTest, TestAnnotations) { checkAnnotation(&buffer, floatAnnotation2Id, BOOL_TYPE, floatAnnotation2Value); EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer - EXPECT_EQ(stats_event_get_errors(event), 0); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); +} + +TEST(StatsEventTest, TestAtomLevelAnnotations) { + uint32_t atomId = 100; + // atom-level annotation information + uint8_t boolAnnotationId = 1; + uint8_t int32AnnotationId = 2; + bool boolAnnotationValue = false; + int32_t int32AnnotationValue = 5; + + float fieldValue = -3.5; + + int64_t startTime = android::elapsedRealtimeNano(); + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue); + AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue); + AStatsEvent_writeFloat(event, fieldValue); + AStatsEvent_build(event); + int64_t endTime = android::elapsedRealtimeNano(); + + size_t bufferSize; + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); + uint8_t* bufferEnd = buffer + bufferSize; + + checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId, + /*numAtomLevelAnnotations=*/2); + + // check atom-level annotations + checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue); + checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue); + + // check first element + checkTypeHeader(&buffer, FLOAT_TYPE); + checkScalar(&buffer, fieldValue); + + EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } TEST(StatsEventTest, TestNoAtomIdError) { - struct stats_event* event = stats_event_obtain(); + AStatsEvent* event = AStatsEvent_obtain(); // Don't set the atom id in order to trigger the error. - stats_event_build(event); + AStatsEvent_build(event); - uint32_t errors = stats_event_get_errors(event); - EXPECT_NE(errors | ERROR_NO_ATOM_ID, 0); + uint32_t errors = AStatsEvent_getErrors(event); + EXPECT_EQ(errors & ERROR_NO_ATOM_ID, ERROR_NO_ATOM_ID); - stats_event_release(event); + AStatsEvent_release(event); } -TEST(StatsEventTest, TestOverflowError) { - struct stats_event* event = stats_event_obtain(); - stats_event_set_atom_id(event, 100); - // Add 1000 int32s to the event. Each int32 takes 5 bytes so this will +TEST(StatsEventTest, TestPushOverflowError) { + const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + const int writeCount = 120; // Number of times to write str in the event. + + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, 100); + + // Add str to the event 120 times. Each str takes >35 bytes so this will // overflow the 4068 byte buffer. - for (int i = 0; i < 1000; i++) { - stats_event_write_int32(event, 0); + // We want to keep writeCount less than 127 to avoid hitting + // ERROR_TOO_MANY_FIELDS. + for (int i = 0; i < writeCount; i++) { + AStatsEvent_writeString(event, str); + } + AStatsEvent_write(event); + + uint32_t errors = AStatsEvent_getErrors(event); + EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW); + + AStatsEvent_release(event); +} + +TEST(StatsEventTest, TestPullOverflowError) { + const uint32_t atomId = 10100; + const vector<uint8_t> bytes(430 /* number of elements */, 1 /* value of each element */); + const int writeCount = 120; // Number of times to write bytes in the event. + + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + + // Add bytes to the event 120 times. Size of bytes is 430 so this will + // overflow the 50 KB pulled event buffer. + // We want to keep writeCount less than 127 to avoid hitting + // ERROR_TOO_MANY_FIELDS. + for (int i = 0; i < writeCount; i++) { + AStatsEvent_writeByteArray(event, bytes.data(), bytes.size()); } - stats_event_build(event); + AStatsEvent_build(event); + + uint32_t errors = AStatsEvent_getErrors(event); + EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW); + + AStatsEvent_release(event); +} + +TEST(StatsEventTest, TestLargePull) { + const uint32_t atomId = 100; + const string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + const int writeCount = 120; // Number of times to write str in the event. + const int64_t startTime = android::elapsedRealtimeNano(); + + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + + // Add str to the event 120 times. + // We want to keep writeCount less than 127 to avoid hitting + // ERROR_TOO_MANY_FIELDS. + for (int i = 0; i < writeCount; i++) { + AStatsEvent_writeString(event, str.c_str()); + } + AStatsEvent_build(event); + int64_t endTime = android::elapsedRealtimeNano(); + + size_t bufferSize; + uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize); + uint8_t* bufferEnd = buffer + bufferSize; + + checkMetadata(&buffer, writeCount, startTime, endTime, atomId); + + // Check all instances of str have been written. + for (int i = 0; i < writeCount; i++) { + checkTypeHeader(&buffer, STRING_TYPE); + checkString(&buffer, str); + } + + EXPECT_EQ(buffer, bufferEnd); // Ensure that we have read the entire buffer. + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); +} + +TEST(StatsEventTest, TestAtomIdInvalidPositionError) { + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_writeInt32(event, 0); + AStatsEvent_setAtomId(event, 100); + AStatsEvent_writeBool(event, true); + AStatsEvent_build(event); + + uint32_t errors = AStatsEvent_getErrors(event); + EXPECT_EQ(errors & ERROR_ATOM_ID_INVALID_POSITION, ERROR_ATOM_ID_INVALID_POSITION); + + AStatsEvent_release(event); +} + +TEST(StatsEventTest, TestOverwriteTimestamp) { + uint32_t atomId = 100; + int64_t expectedTimestamp = 0x123456789; + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, atomId); + AStatsEvent_overwriteTimestamp(event, expectedTimestamp); + AStatsEvent_build(event); + + uint8_t* buffer = AStatsEvent_getBuffer(event, NULL); - uint32_t errors = stats_event_get_errors(event); - EXPECT_NE(errors | ERROR_OVERFLOW, 0); + // Make sure that the timestamp is being overwritten. + checkMetadata(&buffer, /*numElements=*/0, /*startTime=*/expectedTimestamp, + /*endTime=*/expectedTimestamp, atomId); - stats_event_release(event); + EXPECT_EQ(AStatsEvent_getErrors(event), 0); + AStatsEvent_release(event); } diff --git a/libstats/socket/tests/stats_writer_test.cpp b/libstats/socket/tests/stats_writer_test.cpp new file mode 100644 index 000000000..749599ff3 --- /dev/null +++ b/libstats/socket/tests/stats_writer_test.cpp @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#include <gtest/gtest.h> +#include "stats_buffer_writer.h" +#include "stats_event.h" +#include "stats_socket.h" + +TEST(StatsWriterTest, TestSocketClose) { + AStatsEvent* event = AStatsEvent_obtain(); + AStatsEvent_setAtomId(event, 100); + AStatsEvent_writeInt32(event, 5); + int successResult = AStatsEvent_write(event); + AStatsEvent_release(event); + + // In the case of a successful write, we return the number of bytes written. + EXPECT_GT(successResult, 0); + EXPECT_FALSE(stats_log_is_closed()); + + AStatsSocket_close(); + + EXPECT_TRUE(stats_log_is_closed()); +} diff --git a/libutils/String16.cpp b/libutils/String16.cpp index d514f29fb..70bf5a0fb 100644 --- a/libutils/String16.cpp +++ b/libutils/String16.cpp @@ -441,7 +441,7 @@ status_t String16::remove(size_t len, size_t begin) mString = getEmptyString(); return OK; } - if ((begin+len) > N) len = N-begin; + if (len > N || len > N - begin) len = N - begin; if (begin == 0 && len == N) { return OK; } diff --git a/rootdir/init.rc b/rootdir/init.rc index 44c8f27b1..9d8100f79 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -182,6 +182,9 @@ on init mount binder binder /dev/binderfs stats=global chmod 0755 /dev/binderfs + # Mount fusectl + mount fusectl none /sys/fs/fuse/connections + symlink /dev/binderfs/binder /dev/binder symlink /dev/binderfs/hwbinder /dev/hwbinder symlink /dev/binderfs/vndbinder /dev/vndbinder @@ -521,6 +524,7 @@ on post-fs # no-op. restorecon_recursive /metadata/apex + mkdir /metadata/staged-install 0770 root system on late-fs # Ensure that tracefs has the correct permissions. # This does not work correctly if it is called in post-fs. @@ -789,13 +793,13 @@ on post-fs-data # IOCTLs on ashmem fds any more. setprop sys.use_memfd false - # Explicitly disable FUSE - setprop persist.sys.fuse false - # Set fscklog permission chown root system /dev/fscklogs/log chmod 0770 /dev/fscklogs/log + # Enable FUSE by default + setprop persist.sys.fuse true + # Switch between sdcardfs and FUSE depending on persist property # TODO: Move this to ro property before launch because FDE devices # interact with persistent properties differently during boot @@ -817,6 +821,7 @@ on zygote-start && property:persist.sys.fuse="" on zygote-start && property:ro.crypto.state=unencrypted # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted + start statsd start netd start zygote start zygote_secondary @@ -824,6 +829,7 @@ on zygote-start && property:ro.crypto.state=unencrypted on zygote-start && property:ro.crypto.state=unsupported # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted + start statsd start netd start zygote start zygote_secondary @@ -831,6 +837,7 @@ on zygote-start && property:ro.crypto.state=unsupported on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted + start statsd start netd start zygote start zygote_secondary diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc index 9adbcba2e..e827cf557 100644 --- a/rootdir/init.zygote32.rc +++ b/rootdir/init.zygote32.rc @@ -5,6 +5,7 @@ service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-sys group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary stream 660 root system + onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc index 0e69b1695..adc703102 100644 --- a/rootdir/init.zygote64.rc +++ b/rootdir/init.zygote64.rc @@ -5,6 +5,7 @@ service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-s group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary stream 660 root system + onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc index 3e8016867..fb9e99b69 100644 --- a/rootdir/init.zygote64_32.rc +++ b/rootdir/init.zygote64_32.rc @@ -5,13 +5,14 @@ service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-s group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary stream 660 root system + onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond - writepid /dev/cpuset/foreground/tasks + task_profiles ProcessCapacityHigh MaxPerformance service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload class main @@ -21,4 +22,4 @@ service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote socket zygote_secondary stream 660 root system socket usap_pool_secondary stream 660 root system onrestart restart zygote - writepid /dev/cpuset/foreground/tasks + task_profiles ProcessCapacityHigh MaxPerformance diff --git a/toolbox/start.cpp b/toolbox/start.cpp index 46314cfcf..cffb89cc5 100644 --- a/toolbox/start.cpp +++ b/toolbox/start.cpp @@ -37,6 +37,7 @@ static void ControlService(bool start, const std::string& service) { static void ControlDefaultServices(bool start) { std::vector<std::string> services = { + "iorapd", "netd", "surfaceflinger", "audioserver", @@ -91,4 +92,4 @@ extern "C" int start_main(int argc, char** argv) { extern "C" int stop_main(int argc, char** argv) { return StartStop(argc, argv, false); -} +}
\ No newline at end of file |