Remove MIPS support from JNI/trampoline compiler.
Also remove MIPS assembler/disassembler support.
Test: aosp_taimen-userdebug boots.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 147346243
Change-Id: Id736074b97cd04987a7902741828b119508df1c0
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 2b95003..c7a6ec2 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -121,20 +121,6 @@
"utils/arm64/managed_register_arm64.cc",
],
},
- mips: {
- srcs: [
- "jni/quick/mips/calling_convention_mips.cc",
- "utils/mips/assembler_mips.cc",
- "utils/mips/managed_register_mips.cc",
- ],
- },
- mips64: {
- srcs: [
- "jni/quick/mips64/calling_convention_mips64.cc",
- "utils/mips64/assembler_mips64.cc",
- "utils/mips64/managed_register_mips64.cc",
- ],
- },
x86: {
srcs: [
"jni/quick/x86/calling_convention_x86.cc",
@@ -194,8 +180,6 @@
"optimizing/optimizing_compiler_stats.h",
"utils/arm/constants_arm.h",
- "utils/mips/assembler_mips.h",
- "utils/mips64/assembler_mips64.h",
],
output_extension: "operator_out.cc",
}
@@ -418,15 +402,6 @@
"utils/arm64/managed_register_arm64_test.cc",
],
},
- mips: {
- srcs: [
- ],
- },
- mips64: {
- srcs: [
- "utils/mips64/managed_register_mips64_test.cc",
- ],
- },
x86: {
srcs: [
"utils/x86/managed_register_x86_test.cc",
@@ -486,18 +461,6 @@
"utils/assembler_thumb_test.cc",
],
},
- mips: {
- srcs: [
- "utils/mips/assembler_mips_test.cc",
- "utils/mips/assembler_mips32r5_test.cc",
- "utils/mips/assembler_mips32r6_test.cc",
- ],
- },
- mips64: {
- srcs: [
- "utils/mips64/assembler_mips64_test.cc",
- ],
- },
x86: {
srcs: [
"utils/x86/assembler_x86_test.cc",
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc
index 58f7e4f..03b87ef 100644
--- a/compiler/compiled_method.cc
+++ b/compiler/compiled_method.cc
@@ -62,8 +62,6 @@
switch (instruction_set) {
case InstructionSet::kArm:
case InstructionSet::kArm64:
- case InstructionSet::kMips:
- case InstructionSet::kMips64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
return 0;
@@ -81,8 +79,6 @@
switch (instruction_set) {
case InstructionSet::kArm:
case InstructionSet::kArm64:
- case InstructionSet::kMips:
- case InstructionSet::kMips64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
return code_pointer;
diff --git a/compiler/jni/jni_cfi_test.cc b/compiler/jni/jni_cfi_test.cc
index b19a2b8..cec94c9 100644
--- a/compiler/jni/jni_cfi_test.cc
+++ b/compiler/jni/jni_cfi_test.cc
@@ -142,14 +142,6 @@
TEST_ISA(kX86_64)
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
-TEST_ISA(kMips)
-#endif
-
-#ifdef ART_ENABLE_CODEGEN_mips64
-TEST_ISA(kMips64)
-#endif
-
#endif // ART_TARGET_ANDROID
} // namespace art
diff --git a/compiler/jni/jni_cfi_test_expected.inc b/compiler/jni/jni_cfi_test_expected.inc
index d641fe4..489ae00 100644
--- a/compiler/jni/jni_cfi_test_expected.inc
+++ b/compiler/jni/jni_cfi_test_expected.inc
@@ -328,146 +328,3 @@
// 0x0000007f: .cfi_restore_state
// 0x0000007f: .cfi_def_cfa_offset: 128
-static constexpr uint8_t expected_asm_kMips[] = {
- 0xC0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xBE, 0xAF,
- 0x34, 0x00, 0xB7, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
- 0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
- 0x00, 0x00, 0xA4, 0xAF, 0x44, 0x00, 0xA5, 0xAF, 0x48, 0x00, 0xA8, 0xE7,
- 0x4C, 0x00, 0xA6, 0xAF, 0x50, 0x00, 0xA7, 0xAF, 0xE0, 0xFF, 0xBD, 0x27,
- 0x20, 0x00, 0xBD, 0x27, 0x20, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
- 0x28, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
- 0x34, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xBE, 0x8F, 0x3C, 0x00, 0xBF, 0x8F,
- 0x09, 0x00, 0xE0, 0x03, 0x40, 0x00, 0xBD, 0x27,
-};
-static constexpr uint8_t expected_cfi_kMips[] = {
- 0x44, 0x0E, 0x40, 0x44, 0x9F, 0x01, 0x44, 0x9E, 0x02, 0x44, 0x97, 0x03,
- 0x44, 0x96, 0x04, 0x44, 0x95, 0x05, 0x44, 0x94, 0x06, 0x44, 0x93, 0x07,
- 0x44, 0x92, 0x08, 0x58, 0x0E, 0x60, 0x44, 0x0E, 0x40, 0x0A, 0x44, 0xD2,
- 0x44, 0xD3, 0x44, 0xD4, 0x44, 0xD5, 0x44, 0xD6, 0x44, 0xD7, 0x44, 0xDE,
- 0x44, 0xDF, 0x48, 0x0E, 0x00, 0x0B, 0x0E, 0x40,
-};
-// 0x00000000: addiu r29, r29, -64
-// 0x00000004: .cfi_def_cfa_offset: 64
-// 0x00000004: sw r31, +60(r29)
-// 0x00000008: .cfi_offset: r31 at cfa-4
-// 0x00000008: sw r30, +56(r29)
-// 0x0000000c: .cfi_offset: r30 at cfa-8
-// 0x0000000c: sw r23, +52(r29)
-// 0x00000010: .cfi_offset: r23 at cfa-12
-// 0x00000010: sw r22, +48(r29)
-// 0x00000014: .cfi_offset: r22 at cfa-16
-// 0x00000014: sw r21, +44(r29)
-// 0x00000018: .cfi_offset: r21 at cfa-20
-// 0x00000018: sw r20, +40(r29)
-// 0x0000001c: .cfi_offset: r20 at cfa-24
-// 0x0000001c: sw r19, +36(r29)
-// 0x00000020: .cfi_offset: r19 at cfa-28
-// 0x00000020: sw r18, +32(r29)
-// 0x00000024: .cfi_offset: r18 at cfa-32
-// 0x00000024: sw r4, +0(r29)
-// 0x00000028: sw r5, +68(r29)
-// 0x0000002c: swc1 f8, +72(r29)
-// 0x00000030: sw r6, +76(r29)
-// 0x00000034: sw r7, +80(r29)
-// 0x00000038: addiu r29, r29, -32
-// 0x0000003c: .cfi_def_cfa_offset: 96
-// 0x0000003c: addiu r29, r29, 32
-// 0x00000040: .cfi_def_cfa_offset: 64
-// 0x00000040: .cfi_remember_state
-// 0x00000040: lw r18, +32(r29)
-// 0x00000044: .cfi_restore: r18
-// 0x00000044: lw r19, +36(r29)
-// 0x00000048: .cfi_restore: r19
-// 0x00000048: lw r20, +40(r29)
-// 0x0000004c: .cfi_restore: r20
-// 0x0000004c: lw r21, +44(r29)
-// 0x00000050: .cfi_restore: r21
-// 0x00000050: lw r22, +48(r29)
-// 0x00000054: .cfi_restore: r22
-// 0x00000054: lw r23, +52(r29)
-// 0x00000058: .cfi_restore: r23
-// 0x00000058: lw r30, +56(r29)
-// 0x0000005c: .cfi_restore: r30
-// 0x0000005c: lw r31, +60(r29)
-// 0x00000060: .cfi_restore: r31
-// 0x00000060: jr r31
-// 0x00000064: addiu r29, r29, 64
-// 0x00000068: .cfi_def_cfa_offset: 0
-// 0x00000068: .cfi_restore_state
-// 0x00000068: .cfi_def_cfa_offset: 64
-
-static constexpr uint8_t expected_asm_kMips64[] = {
- 0x90, 0xFF, 0xBD, 0x67, 0x68, 0x00, 0xBF, 0xFF, 0x60, 0x00, 0xBE, 0xFF,
- 0x58, 0x00, 0xBC, 0xFF, 0x50, 0x00, 0xB7, 0xFF, 0x48, 0x00, 0xB6, 0xFF,
- 0x40, 0x00, 0xB5, 0xFF, 0x38, 0x00, 0xB4, 0xFF, 0x30, 0x00, 0xB3, 0xFF,
- 0x28, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0xA4, 0xFF, 0x78, 0x00, 0xA5, 0xAF,
- 0x7C, 0x00, 0xAE, 0xE7, 0x80, 0x00, 0xA7, 0xAF, 0x84, 0x00, 0xA8, 0xAF,
- 0xE0, 0xFF, 0xBD, 0x67, 0x20, 0x00, 0xBD, 0x67, 0x28, 0x00, 0xB2, 0xDF,
- 0x30, 0x00, 0xB3, 0xDF, 0x38, 0x00, 0xB4, 0xDF, 0x40, 0x00, 0xB5, 0xDF,
- 0x48, 0x00, 0xB6, 0xDF, 0x50, 0x00, 0xB7, 0xDF, 0x58, 0x00, 0xBC, 0xDF,
- 0x60, 0x00, 0xBE, 0xDF, 0x68, 0x00, 0xBF, 0xDF, 0x70, 0x00, 0xBD, 0x67,
- 0x09, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-};
-static constexpr uint8_t expected_cfi_kMips64[] = {
- 0x44, 0x0E, 0x70, 0x44, 0x9F, 0x02, 0x44, 0x9E, 0x04, 0x44, 0x9C, 0x06,
- 0x44, 0x97, 0x08, 0x44, 0x96, 0x0A, 0x44, 0x95, 0x0C, 0x44, 0x94, 0x0E,
- 0x44, 0x93, 0x10, 0x44, 0x92, 0x12, 0x58, 0x0E, 0x90, 0x01, 0x44, 0x0E,
- 0x70, 0x0A, 0x44, 0xD2, 0x44, 0xD3, 0x44, 0xD4, 0x44, 0xD5, 0x44, 0xD6,
- 0x44, 0xD7, 0x44, 0xDC, 0x44, 0xDE, 0x44, 0xDF, 0x44, 0x0E, 0x00, 0x48,
- 0x0B, 0x0E, 0x70,
-};
-// 0x00000000: daddiu r29, r29, -112
-// 0x00000004: .cfi_def_cfa_offset: 112
-// 0x00000004: sd r31, +104(r29)
-// 0x00000008: .cfi_offset: r31 at cfa-8
-// 0x00000008: sd r30, +96(r29)
-// 0x0000000c: .cfi_offset: r30 at cfa-16
-// 0x0000000c: sd r28, +88(r29)
-// 0x00000010: .cfi_offset: r28 at cfa-24
-// 0x00000010: sd r23, +80(r29)
-// 0x00000014: .cfi_offset: r23 at cfa-32
-// 0x00000014: sd r22, +72(r29)
-// 0x00000018: .cfi_offset: r22 at cfa-40
-// 0x00000018: sd r21, +64(r29)
-// 0x0000001c: .cfi_offset: r21 at cfa-48
-// 0x0000001c: sd r20, +56(r29)
-// 0x00000020: .cfi_offset: r20 at cfa-56
-// 0x00000020: sd r19, +48(r29)
-// 0x00000024: .cfi_offset: r19 at cfa-64
-// 0x00000024: sd r18, +40(r29)
-// 0x00000028: .cfi_offset: r18 at cfa-72
-// 0x00000028: sd r4, +0(r29)
-// 0x0000002c: sw r5, +120(r29)
-// 0x00000030: swc1 f14, +124(r29)
-// 0x00000034: sw r7, +128(r29)
-// 0x00000038: sw r8, +132(r29)
-// 0x0000003c: daddiu r29, r29, -32
-// 0x00000040: .cfi_def_cfa_offset: 144
-// 0x00000040: daddiu r29, r29, 32
-// 0x00000044: .cfi_def_cfa_offset: 112
-// 0x00000044: .cfi_remember_state
-// 0x00000044: ld r18, +40(r29)
-// 0x00000048: .cfi_restore: r18
-// 0x00000048: ld r19, +48(r29)
-// 0x0000004c: .cfi_restore: r19
-// 0x0000004c: ld r20, +56(r29)
-// 0x00000050: .cfi_restore: r20
-// 0x00000050: ld r21, +64(r29)
-// 0x00000054: .cfi_restore: r21
-// 0x00000054: ld r22, +72(r29)
-// 0x00000058: .cfi_restore: r22
-// 0x00000058: ld r23, +80(r29)
-// 0x0000005c: .cfi_restore: r23
-// 0x0000005c: ld r28, +88(r29)
-// 0x00000060: .cfi_restore: r28
-// 0x00000060: ld r30, +96(r29)
-// 0x00000064: .cfi_restore: r30
-// 0x00000064: ld r31, +104(r29)
-// 0x00000068: .cfi_restore: r31
-// 0x00000068: daddiu r29, r29, 112
-// 0x0000006c: .cfi_def_cfa_offset: 0
-// 0x0000006c: jr r31
-// 0x00000070: nop
-// 0x00000074: .cfi_restore_state
-// 0x00000074: .cfi_def_cfa_offset: 112
-
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 0e8602e..fb9704a 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -355,9 +355,6 @@
void StackArgsIntsFirstImpl();
void StackArgsFloatsFirstImpl();
void StackArgsMixedImpl();
-#if defined(__mips__) && defined(__LP64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
- void StackArgsSignExtendedMips64Impl();
-#endif
void NormalNativeImpl();
void FastNativeImpl();
@@ -2136,44 +2133,6 @@
JNI_TEST_CRITICAL(StackArgsMixed)
-#if defined(__mips__) && defined(__LP64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-// Function will fetch the last argument passed from caller that is now on top of the stack and
-// return it as a 8B long. That way we can test if the caller has properly sign-extended the
-// value when placing it on the stack.
-__attribute__((naked))
-jlong Java_MyClassNatives_getStackArgSignExtendedMips64(
- JNIEnv*, jclass, // Arguments passed from caller
- jint, jint, jint, jint, jint, jint, // through regs a0 to a7.
- jint) { // The last argument will be passed on the stack.
- __asm__(
- ".set noreorder\n\t" // Just return and store 8 bytes from the top of the stack
- "jr $ra\n\t" // in v0 (in branch delay slot). This should be the last
- "ld $v0, 0($sp)\n\t"); // argument. It is a 32-bit int, but it should be sign
- // extended and it occupies 64-bit location.
-}
-
-void JniCompilerTest::StackArgsSignExtendedMips64Impl() {
- uint64_t ret;
- SetUpForTest(true,
- "getStackArgSignExtendedMips64",
- "(IIIIIII)J",
- // Don't use wrapper because this is raw assembly function.
- reinterpret_cast<void*>(&Java_MyClassNatives_getStackArgSignExtendedMips64));
-
- // Mips64 ABI requires that arguments passed through stack be sign-extended 8B slots.
- // First 8 arguments are passed through registers.
- // Final argument's value is 7. When sign-extended, higher stack bits should be 0.
- ret = env_->CallStaticLongMethod(jklass_, jmethod_, 1, 2, 3, 4, 5, 6, 7);
- EXPECT_EQ(High32Bits(ret), static_cast<uint32_t>(0));
-
- // Final argument's value is -8. When sign-extended, higher stack bits should be 0xffffffff.
- ret = env_->CallStaticLongMethod(jklass_, jmethod_, 1, 2, 3, 4, 5, 6, -8);
- EXPECT_EQ(High32Bits(ret), static_cast<uint32_t>(0xffffffff));
-}
-
-JNI_TEST(StackArgsSignExtendedMips64)
-#endif
-
void Java_MyClassNatives_normalNative(JNIEnv*, jclass) {
// Intentionally left empty.
}
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 15af248..1943756 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -28,14 +28,6 @@
#include "jni/quick/arm64/calling_convention_arm64.h"
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
-#include "jni/quick/mips/calling_convention_mips.h"
-#endif
-
-#ifdef ART_ENABLE_CODEGEN_mips64
-#include "jni/quick/mips64/calling_convention_mips64.h"
-#endif
-
#ifdef ART_ENABLE_CODEGEN_x86
#include "jni/quick/x86/calling_convention_x86.h"
#endif
@@ -68,18 +60,6 @@
new (allocator) arm64::Arm64ManagedRuntimeCallingConvention(
is_static, is_synchronized, shorty));
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
- case InstructionSet::kMips:
- return std::unique_ptr<ManagedRuntimeCallingConvention>(
- new (allocator) mips::MipsManagedRuntimeCallingConvention(
- is_static, is_synchronized, shorty));
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
- case InstructionSet::kMips64:
- return std::unique_ptr<ManagedRuntimeCallingConvention>(
- new (allocator) mips64::Mips64ManagedRuntimeCallingConvention(
- is_static, is_synchronized, shorty));
-#endif
#ifdef ART_ENABLE_CODEGEN_x86
case InstructionSet::kX86:
return std::unique_ptr<ManagedRuntimeCallingConvention>(
@@ -170,18 +150,6 @@
new (allocator) arm64::Arm64JniCallingConvention(
is_static, is_synchronized, is_critical_native, shorty));
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
- case InstructionSet::kMips:
- return std::unique_ptr<JniCallingConvention>(
- new (allocator) mips::MipsJniCallingConvention(
- is_static, is_synchronized, is_critical_native, shorty));
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
- case InstructionSet::kMips64:
- return std::unique_ptr<JniCallingConvention>(
- new (allocator) mips64::Mips64JniCallingConvention(
- is_static, is_synchronized, is_critical_native, shorty));
-#endif
#ifdef ART_ENABLE_CODEGEN_x86
case InstructionSet::kX86:
return std::unique_ptr<JniCallingConvention>(
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 363e646..c2db73a 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -43,8 +43,6 @@
#include "utils/assembler.h"
#include "utils/jni_macro_assembler.h"
#include "utils/managed_register.h"
-#include "utils/mips/managed_register_mips.h"
-#include "utils/mips64/managed_register_mips64.h"
#include "utils/x86/managed_register_x86.h"
#define __ jni_asm->
@@ -324,8 +322,7 @@
// Skip this for @CriticalNative because we didn't build a HandleScope to begin with.
// Note that we always have outgoing param space available for at least two params.
if (kUseReadBarrier && is_static && !is_critical_native) {
- const bool kReadBarrierFastPath =
- (instruction_set != InstructionSet::kMips) && (instruction_set != InstructionSet::kMips64);
+ const bool kReadBarrierFastPath = true; // Always true after Mips codegen was removed.
std::unique_ptr<JNIMacroLabel> skip_cold_path_label;
if (kReadBarrierFastPath) {
skip_cold_path_label = __ CreateLabel();
@@ -548,16 +545,6 @@
if (LIKELY(!is_critical_native)) {
// For normal JNI, store the return value on the stack because the call to
// JniMethodEnd will clobber the return value. It will be restored in (13).
- if ((instruction_set == InstructionSet::kMips ||
- instruction_set == InstructionSet::kMips64) &&
- main_jni_conv->GetReturnType() == Primitive::kPrimDouble &&
- return_save_location.Uint32Value() % 8 != 0) {
- // Ensure doubles are 8-byte aligned for MIPS
- return_save_location = FrameOffset(return_save_location.Uint32Value()
- + static_cast<size_t>(kMipsPointerSize));
- // TODO: refactor this into the JniCallingConvention code
- // as a return value alignment requirement.
- }
CHECK_LT(return_save_location.Uint32Value(), current_frame_size);
__ Store(return_save_location,
main_jni_conv->ReturnRegister(),
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
deleted file mode 100644
index cbb692e..0000000
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include "calling_convention_mips.h"
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-#include "handle_scope-inl.h"
-#include "utils/mips/managed_register_mips.h"
-
-namespace art {
-namespace mips {
-
-//
-// JNI calling convention constants.
-//
-
-// Up to how many float-like (float, double) args can be enregistered in floating-point registers.
-// The rest of the args must go in integer registers or on the stack.
-constexpr size_t kMaxFloatOrDoubleRegisterArguments = 2u;
-// Up to how many integer-like (pointers, objects, longs, int, short, bool, etc) args can be
-// enregistered. The rest of the args must go on the stack.
-constexpr size_t kMaxIntLikeRegisterArguments = 4u;
-
-static const Register kJniCoreArgumentRegisters[] = { A0, A1, A2, A3 };
-static const FRegister kJniFArgumentRegisters[] = { F12, F14 };
-static const DRegister kJniDArgumentRegisters[] = { D6, D7 };
-
-//
-// Managed calling convention constants.
-//
-
-static const Register kManagedCoreArgumentRegisters[] = { A0, A1, A2, A3, T0, T1 };
-static const FRegister kManagedFArgumentRegisters[] = { F8, F10, F12, F14, F16, F18 };
-static const DRegister kManagedDArgumentRegisters[] = { D4, D5, D6, D7, D8, D9 };
-
-static constexpr ManagedRegister kCalleeSaveRegisters[] = {
- // Core registers.
- MipsManagedRegister::FromCoreRegister(S2),
- MipsManagedRegister::FromCoreRegister(S3),
- MipsManagedRegister::FromCoreRegister(S4),
- MipsManagedRegister::FromCoreRegister(S5),
- MipsManagedRegister::FromCoreRegister(S6),
- MipsManagedRegister::FromCoreRegister(S7),
- MipsManagedRegister::FromCoreRegister(FP),
- // No hard float callee saves.
-};
-
-static constexpr uint32_t CalculateCoreCalleeSpillMask() {
- // RA is a special callee save which is not reported by CalleeSaveRegisters().
- uint32_t result = 1 << RA;
- for (auto&& r : kCalleeSaveRegisters) {
- if (r.AsMips().IsCoreRegister()) {
- result |= (1 << r.AsMips().AsCoreRegister());
- }
- }
- return result;
-}
-
-static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
-static constexpr uint32_t kFpCalleeSpillMask = 0u;
-
-// Calling convention
-ManagedRegister MipsManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
- return MipsManagedRegister::FromCoreRegister(T9);
-}
-
-ManagedRegister MipsJniCallingConvention::InterproceduralScratchRegister() const {
- return MipsManagedRegister::FromCoreRegister(T9);
-}
-
-static ManagedRegister ReturnRegisterForShorty(const char* shorty) {
- if (shorty[0] == 'F') {
- return MipsManagedRegister::FromFRegister(F0);
- } else if (shorty[0] == 'D') {
- return MipsManagedRegister::FromDRegister(D0);
- } else if (shorty[0] == 'J') {
- return MipsManagedRegister::FromRegisterPair(V0_V1);
- } else if (shorty[0] == 'V') {
- return MipsManagedRegister::NoRegister();
- } else {
- return MipsManagedRegister::FromCoreRegister(V0);
- }
-}
-
-ManagedRegister MipsManagedRuntimeCallingConvention::ReturnRegister() {
- return ReturnRegisterForShorty(GetShorty());
-}
-
-ManagedRegister MipsJniCallingConvention::ReturnRegister() {
- return ReturnRegisterForShorty(GetShorty());
-}
-
-ManagedRegister MipsJniCallingConvention::IntReturnRegister() {
- return MipsManagedRegister::FromCoreRegister(V0);
-}
-
-// Managed runtime calling convention
-
-ManagedRegister MipsManagedRuntimeCallingConvention::MethodRegister() {
- return MipsManagedRegister::FromCoreRegister(A0);
-}
-
-bool MipsManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
- return false; // Everything moved to stack on entry.
-}
-
-bool MipsManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
- return true;
-}
-
-ManagedRegister MipsManagedRuntimeCallingConvention::CurrentParamRegister() {
- LOG(FATAL) << "Should not reach here";
- UNREACHABLE();
-}
-
-FrameOffset MipsManagedRuntimeCallingConvention::CurrentParamStackOffset() {
- CHECK(IsCurrentParamOnStack());
- FrameOffset result =
- FrameOffset(displacement_.Int32Value() + // displacement
- kFramePointerSize + // Method*
- (itr_slots_ * kFramePointerSize)); // offset into in args
- return result;
-}
-
-const ManagedRegisterEntrySpills& MipsManagedRuntimeCallingConvention::EntrySpills() {
- // We spill the argument registers on MIPS to free them up for scratch use, we then assume
- // all arguments are on the stack.
- if ((entry_spills_.size() == 0) && (NumArgs() > 0)) {
- uint32_t gpr_index = 1; // Skip A0, it is used for ArtMethod*.
- uint32_t fpr_index = 0;
-
- for (ResetIterator(FrameOffset(0)); HasNext(); Next()) {
- if (IsCurrentParamAFloatOrDouble()) {
- if (IsCurrentParamADouble()) {
- if (fpr_index < arraysize(kManagedDArgumentRegisters)) {
- entry_spills_.push_back(
- MipsManagedRegister::FromDRegister(kManagedDArgumentRegisters[fpr_index++]));
- } else {
- entry_spills_.push_back(ManagedRegister::NoRegister(), 8);
- }
- } else {
- if (fpr_index < arraysize(kManagedFArgumentRegisters)) {
- entry_spills_.push_back(
- MipsManagedRegister::FromFRegister(kManagedFArgumentRegisters[fpr_index++]));
- } else {
- entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
- }
- }
- } else {
- if (IsCurrentParamALong() && !IsCurrentParamAReference()) {
- if (gpr_index == 1 || gpr_index == 3) {
- // Don't use A1-A2(A3-T0) as a register pair, move to A2-A3(T0-T1) instead.
- gpr_index++;
- }
- if (gpr_index < arraysize(kManagedCoreArgumentRegisters) - 1) {
- entry_spills_.push_back(
- MipsManagedRegister::FromCoreRegister(kManagedCoreArgumentRegisters[gpr_index++]));
- } else if (gpr_index == arraysize(kManagedCoreArgumentRegisters) - 1) {
- gpr_index++;
- entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
- } else {
- entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
- }
- }
-
- if (gpr_index < arraysize(kManagedCoreArgumentRegisters)) {
- entry_spills_.push_back(
- MipsManagedRegister::FromCoreRegister(kManagedCoreArgumentRegisters[gpr_index++]));
- } else {
- entry_spills_.push_back(ManagedRegister::NoRegister(), 4);
- }
- }
- }
- }
- return entry_spills_;
-}
-
-// JNI calling convention
-
-MipsJniCallingConvention::MipsJniCallingConvention(bool is_static,
- bool is_synchronized,
- bool is_critical_native,
- const char* shorty)
- : JniCallingConvention(is_static,
- is_synchronized,
- is_critical_native,
- shorty,
- kMipsPointerSize) {
- // SYSTEM V - Application Binary Interface (MIPS RISC Processor):
- // Data Representation - Fundamental Types (3-4) specifies fundamental alignments for each type.
- // "Each member is assigned to the lowest available offset with the appropriate alignment. This
- // may require internal padding, depending on the previous member."
- //
- // All of our stack arguments are usually 4-byte aligned, however longs and doubles must be 8
- // bytes aligned. Add padding to maintain 8-byte alignment invariant.
- //
- // Compute padding to ensure longs and doubles are not split in o32.
- size_t padding = 0;
- size_t cur_arg, cur_reg;
- if (LIKELY(HasExtraArgumentsForJni())) {
- // Ignore the 'this' jobject or jclass for static methods and the JNIEnv.
- // We start at the aligned register A2.
- //
- // Ignore the first 2 parameters because they are guaranteed to be aligned.
- cur_arg = NumImplicitArgs(); // Skip the "this" argument.
- cur_reg = 2; // Skip {A0=JNIEnv, A1=jobject} / {A0=JNIEnv, A1=jclass} parameters (start at A2).
- } else {
- // Check every parameter.
- cur_arg = 0;
- cur_reg = 0;
- }
-
- // Shift across a logical register mapping that looks like:
- //
- // | A0 | A1 | A2 | A3 | SP+16 | SP+20 | SP+24 | ... | SP+n | SP+n+4 |
- //
- // or some of variants with floating-point registers (F12 and F14), for example
- //
- // | F12 | F14 | A3 | SP+16 | SP+20 | SP+24 | ... | SP+n | SP+n+4 |
- //
- // (where SP is the stack pointer at the start of called function).
- //
- // Any time there would normally be a long/double in an odd logical register,
- // we have to push out the rest of the mappings by 4 bytes to maintain an 8-byte alignment.
- //
- // This works for both physical register pairs {A0, A1}, {A2, A3},
- // floating-point registers F12, F14 and for when the value is on the stack.
- //
- // For example:
- // (a) long would normally go into A1, but we shift it into A2
- // | INT | (PAD) | LONG |
- // | A0 | A1 | A2 | A3 |
- //
- // (b) long would normally go into A3, but we shift it into SP
- // | INT | INT | INT | (PAD) | LONG |
- // | A0 | A1 | A2 | A3 | SP+16 SP+20 |
- //
- // where INT is any <=4 byte arg, and LONG is any 8-byte arg.
- for (; cur_arg < NumArgs(); cur_arg++) {
- if (IsParamALongOrDouble(cur_arg)) {
- if ((cur_reg & 1) != 0) {
- padding += 4;
- cur_reg++; // Additional bump to ensure alignment.
- }
- cur_reg += 2; // Bump the iterator twice for every long argument.
- } else {
- cur_reg++; // Bump the iterator for every argument.
- }
- }
- if (cur_reg < kMaxIntLikeRegisterArguments) {
- // As a special case when, as a result of shifting (or not) there are no arguments on the stack,
- // we actually have 0 stack padding.
- //
- // For example with @CriticalNative and:
- // (int, long) -> shifts the long but doesn't need to pad the stack
- //
- // shift
- // \/
- // | INT | (PAD) | LONG | (EMPTY) ...
- // | r0 | r1 | r2 | r3 | SP ...
- // /\
- // no stack padding
- padding_ = 0;
- } else {
- padding_ = padding;
- }
-
- // Argument Passing (3-17):
- // "When the first argument is integral, the remaining arguments are passed in the integer
- // registers."
- //
- // "The rules that determine which arguments go into registers and which ones must be passed on
- // the stack are most easily explained by considering the list of arguments as a structure,
- // aligned according to normal structure rules. Mapping of this structure into the combination of
- // stack and registers is as follows: up to two leading floating-point arguments can be passed in
- // $f12 and $f14; everything else with a structure offset greater than or equal to 16 is passed on
- // the stack. The remainder of the arguments are passed in $4..$7 based on their structure offset.
- // Holes left in the structure for alignment are unused, whether in registers or in the stack."
- //
- // For example with @CriticalNative and:
- // (a) first argument is not floating-point, so all go into integer registers
- // | INT | FLOAT | DOUBLE |
- // | A0 | A1 | A2 | A3 |
- // (b) first argument is floating-point, but 2nd is integer
- // | FLOAT | INT | DOUBLE |
- // | F12 | A1 | A2 | A3 |
- // (c) first two arguments are floating-point (float, double)
- // | FLOAT | (PAD) | DOUBLE | INT |
- // | F12 | | F14 | SP+16 |
- // (d) first two arguments are floating-point (double, float)
- // | DOUBLE | FLOAT | INT |
- // | F12 | F14 | A3 |
- // (e) first three arguments are floating-point, but just first two will go into fp registers
- // | DOUBLE | FLOAT | FLOAT |
- // | F12 | F14 | A3 |
- //
- // Find out if the first argument is a floating-point. In that case, floating-point registers will
- // be used for up to two leading floating-point arguments. Otherwise, all arguments will be passed
- // using integer registers.
- use_fp_arg_registers_ = false;
- if (is_critical_native) {
- if (NumArgs() > 0) {
- if (IsParamAFloatOrDouble(0)) {
- use_fp_arg_registers_ = true;
- }
- }
- }
-}
-
-uint32_t MipsJniCallingConvention::CoreSpillMask() const {
- return kCoreCalleeSpillMask;
-}
-
-uint32_t MipsJniCallingConvention::FpSpillMask() const {
- return kFpCalleeSpillMask;
-}
-
-ManagedRegister MipsJniCallingConvention::ReturnScratchRegister() const {
- return MipsManagedRegister::FromCoreRegister(AT);
-}
-
-size_t MipsJniCallingConvention::FrameSize() const {
- // ArtMethod*, RA and callee save area size, local reference segment state.
- const size_t method_ptr_size = static_cast<size_t>(kMipsPointerSize);
- const size_t ra_return_addr_size = kFramePointerSize;
- const size_t callee_save_area_size = CalleeSaveRegisters().size() * kFramePointerSize;
-
- size_t frame_data_size = method_ptr_size + ra_return_addr_size + callee_save_area_size;
-
- if (LIKELY(HasLocalReferenceSegmentState())) {
- // Local reference segment state.
- frame_data_size += kFramePointerSize;
- }
-
- // References plus 2 words for HandleScope header.
- const size_t handle_scope_size = HandleScope::SizeOf(kMipsPointerSize, ReferenceCount());
-
- size_t total_size = frame_data_size;
- if (LIKELY(HasHandleScope())) {
- // HandleScope is sometimes excluded.
- total_size += handle_scope_size; // Handle scope size.
- }
-
- // Plus return value spill area size.
- total_size += SizeOfReturnValue();
-
- return RoundUp(total_size, kStackAlignment);
-}
-
-size_t MipsJniCallingConvention::OutArgSize() const {
- // Argument Passing (3-17):
- // "Despite the fact that some or all of the arguments to a function are passed in registers,
- // always allocate space on the stack for all arguments. This stack space should be a structure
- // large enough to contain all the arguments, aligned according to normal structure rules (after
- // promotion and structure return pointer insertion). The locations within the stack frame used
- // for arguments are called the home locations."
- //
- // Allocate 16 bytes for home locations + space needed for stack arguments.
-
- size_t static_args = HasSelfClass() ? 1 : 0; // Count jclass.
- // Regular argument parameters and this.
- size_t param_args = NumArgs() + NumLongOrDoubleArgs(); // Twice count 8-byte args.
- // Count JNIEnv* less arguments in registers.
- size_t internal_args = (HasJniEnv() ? 1 : 0);
- size_t total_args = static_args + param_args + internal_args;
-
- size_t stack_args =
- total_args - std::min(kMaxIntLikeRegisterArguments, static_cast<size_t>(total_args));
-
- return RoundUp(
- (kMaxIntLikeRegisterArguments + stack_args) * kFramePointerSize + padding_,
- kStackAlignment);
-}
-
-ArrayRef<const ManagedRegister> MipsJniCallingConvention::CalleeSaveRegisters() const {
- return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
-}
-
-// JniCallingConvention ABI follows o32 where longs and doubles must occur
-// in even register numbers and stack slots.
-void MipsJniCallingConvention::Next() {
- JniCallingConvention::Next();
-
- if (LIKELY(HasNext())) { // Avoid CHECK failure for IsCurrentParam
- // Ensure slot is 8-byte aligned for longs/doubles (o32).
- if (IsCurrentParamALongOrDouble() && ((itr_slots_ & 0x1u) != 0)) {
- // itr_slots_ needs to be an even number, according to o32.
- itr_slots_++;
- }
- }
-}
-
-bool MipsJniCallingConvention::IsCurrentParamInRegister() {
- // Argument Passing (3-17):
- // "The rules that determine which arguments go into registers and which ones must be passed on
- // the stack are most easily explained by considering the list of arguments as a structure,
- // aligned according to normal structure rules. Mapping of this structure into the combination of
- // stack and registers is as follows: up to two leading floating-point arguments can be passed in
- // $f12 and $f14; everything else with a structure offset greater than or equal to 16 is passed on
- // the stack. The remainder of the arguments are passed in $4..$7 based on their structure offset.
- // Holes left in the structure for alignment are unused, whether in registers or in the stack."
- //
- // Even when floating-point registers are used, there can be up to 4 arguments passed in
- // registers.
- return itr_slots_ < kMaxIntLikeRegisterArguments;
-}
-
-bool MipsJniCallingConvention::IsCurrentParamOnStack() {
- return !IsCurrentParamInRegister();
-}
-
-ManagedRegister MipsJniCallingConvention::CurrentParamRegister() {
- CHECK_LT(itr_slots_, kMaxIntLikeRegisterArguments);
- // Up to two leading floating-point arguments can be passed in floating-point registers.
- if (use_fp_arg_registers_ && (itr_args_ < kMaxFloatOrDoubleRegisterArguments)) {
- if (IsCurrentParamAFloatOrDouble()) {
- if (IsCurrentParamADouble()) {
- return MipsManagedRegister::FromDRegister(kJniDArgumentRegisters[itr_args_]);
- } else {
- return MipsManagedRegister::FromFRegister(kJniFArgumentRegisters[itr_args_]);
- }
- }
- }
- // All other arguments (including other floating-point arguments) will be passed in integer
- // registers.
- if (IsCurrentParamALongOrDouble()) {
- if (itr_slots_ == 0u) {
- return MipsManagedRegister::FromRegisterPair(A0_A1);
- } else {
- CHECK_EQ(itr_slots_, 2u);
- return MipsManagedRegister::FromRegisterPair(A2_A3);
- }
- } else {
- return MipsManagedRegister::FromCoreRegister(kJniCoreArgumentRegisters[itr_slots_]);
- }
-}
-
-FrameOffset MipsJniCallingConvention::CurrentParamStackOffset() {
- CHECK_GE(itr_slots_, kMaxIntLikeRegisterArguments);
- size_t offset = displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize);
- CHECK_LT(offset, OutArgSize());
- return FrameOffset(offset);
-}
-
-ManagedRegister MipsJniCallingConvention::HiddenArgumentRegister() const {
- UNIMPLEMENTED(FATAL);
- UNREACHABLE();
-}
-
-bool MipsJniCallingConvention::UseTailCall() const {
- UNIMPLEMENTED(FATAL);
- UNREACHABLE();
-}
-
-} // namespace mips
-} // namespace art
diff --git a/compiler/jni/quick/mips/calling_convention_mips.h b/compiler/jni/quick/mips/calling_convention_mips.h
deleted file mode 100644
index af27dc8..0000000
--- a/compiler/jni/quick/mips/calling_convention_mips.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ART_COMPILER_JNI_QUICK_MIPS_CALLING_CONVENTION_MIPS_H_
-#define ART_COMPILER_JNI_QUICK_MIPS_CALLING_CONVENTION_MIPS_H_
-
-#include "base/enums.h"
-#include "jni/quick/calling_convention.h"
-
-namespace art {
-namespace mips {
-
-constexpr size_t kFramePointerSize = 4;
-static_assert(kFramePointerSize == static_cast<size_t>(PointerSize::k32),
- "Invalid frame pointer size");
-
-class MipsManagedRuntimeCallingConvention final : public ManagedRuntimeCallingConvention {
- public:
- MipsManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
- : ManagedRuntimeCallingConvention(is_static,
- is_synchronized,
- shorty,
- PointerSize::k32) {}
- ~MipsManagedRuntimeCallingConvention() override {}
- // Calling convention
- ManagedRegister ReturnRegister() override;
- ManagedRegister InterproceduralScratchRegister() const override;
- // Managed runtime calling convention
- ManagedRegister MethodRegister() override;
- bool IsCurrentParamInRegister() override;
- bool IsCurrentParamOnStack() override;
- ManagedRegister CurrentParamRegister() override;
- FrameOffset CurrentParamStackOffset() override;
- const ManagedRegisterEntrySpills& EntrySpills() override;
-
- private:
- ManagedRegisterEntrySpills entry_spills_;
-
- DISALLOW_COPY_AND_ASSIGN(MipsManagedRuntimeCallingConvention);
-};
-
-class MipsJniCallingConvention final : public JniCallingConvention {
- public:
- MipsJniCallingConvention(bool is_static,
- bool is_synchronized,
- bool is_critical_native,
- const char* shorty);
- ~MipsJniCallingConvention() override {}
- // Calling convention
- ManagedRegister ReturnRegister() override;
- ManagedRegister IntReturnRegister() override;
- ManagedRegister InterproceduralScratchRegister() const override;
- // JNI calling convention
- void Next() override; // Override default behavior for o32.
- size_t FrameSize() const override;
- size_t OutArgSize() const override;
- ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
- ManagedRegister ReturnScratchRegister() const override;
- uint32_t CoreSpillMask() const override;
- uint32_t FpSpillMask() const override;
- bool IsCurrentParamInRegister() override;
- bool IsCurrentParamOnStack() override;
- ManagedRegister CurrentParamRegister() override;
- FrameOffset CurrentParamStackOffset() override;
-
- // Mips does not need to extend small return types.
- bool RequiresSmallResultTypeExtension() const override {
- return false;
- }
-
- // Hidden argument register, used to pass the method pointer for @CriticalNative call.
- ManagedRegister HiddenArgumentRegister() const override;
-
- // Whether to use tail call (used only for @CriticalNative).
- bool UseTailCall() const override;
-
- private:
- // Padding to ensure longs and doubles are not split in o32.
- size_t padding_;
- bool use_fp_arg_registers_;
-
- DISALLOW_COPY_AND_ASSIGN(MipsJniCallingConvention);
-};
-
-} // namespace mips
-} // namespace art
-
-#endif // ART_COMPILER_JNI_QUICK_MIPS_CALLING_CONVENTION_MIPS_H_
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.cc b/compiler/jni/quick/mips64/calling_convention_mips64.cc
deleted file mode 100644
index e65ad83..0000000
--- a/compiler/jni/quick/mips64/calling_convention_mips64.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "calling_convention_mips64.h"
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-#include "handle_scope-inl.h"
-#include "utils/mips64/managed_register_mips64.h"
-
-namespace art {
-namespace mips64 {
-
-// Up to kow many args can be enregistered. The rest of the args must go on the stack.
-constexpr size_t kMaxRegisterArguments = 8u;
-
-static const GpuRegister kGpuArgumentRegisters[] = {
- A0, A1, A2, A3, A4, A5, A6, A7
-};
-
-static const FpuRegister kFpuArgumentRegisters[] = {
- F12, F13, F14, F15, F16, F17, F18, F19
-};
-
-static constexpr ManagedRegister kCalleeSaveRegisters[] = {
- // Core registers.
- Mips64ManagedRegister::FromGpuRegister(S2),
- Mips64ManagedRegister::FromGpuRegister(S3),
- Mips64ManagedRegister::FromGpuRegister(S4),
- Mips64ManagedRegister::FromGpuRegister(S5),
- Mips64ManagedRegister::FromGpuRegister(S6),
- Mips64ManagedRegister::FromGpuRegister(S7),
- Mips64ManagedRegister::FromGpuRegister(GP),
- Mips64ManagedRegister::FromGpuRegister(S8),
- // No hard float callee saves.
-};
-
-static constexpr uint32_t CalculateCoreCalleeSpillMask() {
- // RA is a special callee save which is not reported by CalleeSaveRegisters().
- uint32_t result = 1 << RA;
- for (auto&& r : kCalleeSaveRegisters) {
- if (r.AsMips64().IsGpuRegister()) {
- result |= (1 << r.AsMips64().AsGpuRegister());
- }
- }
- return result;
-}
-
-static constexpr uint32_t kCoreCalleeSpillMask = CalculateCoreCalleeSpillMask();
-static constexpr uint32_t kFpCalleeSpillMask = 0u;
-
-// Calling convention
-ManagedRegister Mips64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() const {
- return Mips64ManagedRegister::FromGpuRegister(T9);
-}
-
-ManagedRegister Mips64JniCallingConvention::InterproceduralScratchRegister() const {
- return Mips64ManagedRegister::FromGpuRegister(T9);
-}
-
-static ManagedRegister ReturnRegisterForShorty(const char* shorty) {
- if (shorty[0] == 'F' || shorty[0] == 'D') {
- return Mips64ManagedRegister::FromFpuRegister(F0);
- } else if (shorty[0] == 'V') {
- return Mips64ManagedRegister::NoRegister();
- } else {
- return Mips64ManagedRegister::FromGpuRegister(V0);
- }
-}
-
-ManagedRegister Mips64ManagedRuntimeCallingConvention::ReturnRegister() {
- return ReturnRegisterForShorty(GetShorty());
-}
-
-ManagedRegister Mips64JniCallingConvention::ReturnRegister() {
- return ReturnRegisterForShorty(GetShorty());
-}
-
-ManagedRegister Mips64JniCallingConvention::IntReturnRegister() {
- return Mips64ManagedRegister::FromGpuRegister(V0);
-}
-
-// Managed runtime calling convention
-
-ManagedRegister Mips64ManagedRuntimeCallingConvention::MethodRegister() {
- return Mips64ManagedRegister::FromGpuRegister(A0);
-}
-
-bool Mips64ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
- return false; // Everything moved to stack on entry.
-}
-
-bool Mips64ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
- return true;
-}
-
-ManagedRegister Mips64ManagedRuntimeCallingConvention::CurrentParamRegister() {
- LOG(FATAL) << "Should not reach here";
- UNREACHABLE();
-}
-
-FrameOffset Mips64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
- CHECK(IsCurrentParamOnStack());
- FrameOffset result =
- FrameOffset(displacement_.Int32Value() + // displacement
- kFramePointerSize + // Method ref
- (itr_slots_ * sizeof(uint32_t))); // offset into in args
- return result;
-}
-
-const ManagedRegisterEntrySpills& Mips64ManagedRuntimeCallingConvention::EntrySpills() {
- // We spill the argument registers on MIPS64 to free them up for scratch use,
- // we then assume all arguments are on the stack.
- if ((entry_spills_.size() == 0) && (NumArgs() > 0)) {
- int reg_index = 1; // we start from A1, A0 holds ArtMethod*.
-
- // We need to choose the correct register size since the managed
- // stack uses 32bit stack slots.
- ResetIterator(FrameOffset(0));
- while (HasNext()) {
- if (reg_index < 8) {
- if (IsCurrentParamAFloatOrDouble()) { // FP regs.
- FpuRegister arg = kFpuArgumentRegisters[reg_index];
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromFpuRegister(arg);
- entry_spills_.push_back(reg, IsCurrentParamADouble() ? 8 : 4);
- } else { // GP regs.
- GpuRegister arg = kGpuArgumentRegisters[reg_index];
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromGpuRegister(arg);
- entry_spills_.push_back(reg,
- (IsCurrentParamALong() && (!IsCurrentParamAReference())) ? 8 : 4);
- }
- // e.g. A1, A2, F3, A4, F5, F6, A7
- reg_index++;
- }
-
- Next();
- }
- }
- return entry_spills_;
-}
-
-// JNI calling convention
-
-Mips64JniCallingConvention::Mips64JniCallingConvention(bool is_static,
- bool is_synchronized,
- bool is_critical_native,
- const char* shorty)
- : JniCallingConvention(is_static,
- is_synchronized,
- is_critical_native,
- shorty,
- kMips64PointerSize) {
-}
-
-uint32_t Mips64JniCallingConvention::CoreSpillMask() const {
- return kCoreCalleeSpillMask;
-}
-
-uint32_t Mips64JniCallingConvention::FpSpillMask() const {
- return kFpCalleeSpillMask;
-}
-
-ManagedRegister Mips64JniCallingConvention::ReturnScratchRegister() const {
- return Mips64ManagedRegister::FromGpuRegister(AT);
-}
-
-size_t Mips64JniCallingConvention::FrameSize() const {
- // ArtMethod*, RA and callee save area size, local reference segment state.
- size_t method_ptr_size = static_cast<size_t>(kFramePointerSize);
- size_t ra_and_callee_save_area_size = (CalleeSaveRegisters().size() + 1) * kFramePointerSize;
-
- size_t frame_data_size = method_ptr_size + ra_and_callee_save_area_size;
- if (LIKELY(HasLocalReferenceSegmentState())) { // Local ref. segment state.
- // Local reference segment state is sometimes excluded.
- frame_data_size += sizeof(uint32_t);
- }
- // References plus 2 words for HandleScope header.
- size_t handle_scope_size = HandleScope::SizeOf(kMips64PointerSize, ReferenceCount());
-
- size_t total_size = frame_data_size;
- if (LIKELY(HasHandleScope())) {
- // HandleScope is sometimes excluded.
- total_size += handle_scope_size; // Handle scope size.
- }
-
- // Plus return value spill area size.
- total_size += SizeOfReturnValue();
-
- return RoundUp(total_size, kStackAlignment);
-}
-
-size_t Mips64JniCallingConvention::OutArgSize() const {
- // all arguments including JNI args
- size_t all_args = NumArgs() + NumberOfExtraArgumentsForJni();
-
- // Nothing on the stack unless there are more than 8 arguments
- size_t stack_args = (all_args > kMaxRegisterArguments) ? all_args - kMaxRegisterArguments : 0;
-
- return RoundUp(stack_args * kFramePointerSize, kStackAlignment);
-}
-
-ArrayRef<const ManagedRegister> Mips64JniCallingConvention::CalleeSaveRegisters() const {
- return ArrayRef<const ManagedRegister>(kCalleeSaveRegisters);
-}
-
-bool Mips64JniCallingConvention::IsCurrentParamInRegister() {
- return itr_args_ < kMaxRegisterArguments;
-}
-
-bool Mips64JniCallingConvention::IsCurrentParamOnStack() {
- return !IsCurrentParamInRegister();
-}
-
-ManagedRegister Mips64JniCallingConvention::CurrentParamRegister() {
- CHECK(IsCurrentParamInRegister());
- if (IsCurrentParamAFloatOrDouble()) {
- return Mips64ManagedRegister::FromFpuRegister(kFpuArgumentRegisters[itr_args_]);
- } else {
- return Mips64ManagedRegister::FromGpuRegister(kGpuArgumentRegisters[itr_args_]);
- }
-}
-
-FrameOffset Mips64JniCallingConvention::CurrentParamStackOffset() {
- CHECK(IsCurrentParamOnStack());
- size_t args_on_stack = itr_args_ - kMaxRegisterArguments;
- size_t offset = displacement_.Int32Value() - OutArgSize() + (args_on_stack * kFramePointerSize);
- CHECK_LT(offset, OutArgSize());
- return FrameOffset(offset);
-}
-
-ManagedRegister Mips64JniCallingConvention::HiddenArgumentRegister() const {
- UNIMPLEMENTED(FATAL);
- UNREACHABLE();
-}
-
-bool Mips64JniCallingConvention::UseTailCall() const {
- UNIMPLEMENTED(FATAL);
- UNREACHABLE();
-}
-
-} // namespace mips64
-} // namespace art
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.h b/compiler/jni/quick/mips64/calling_convention_mips64.h
deleted file mode 100644
index e9a42a4..0000000
--- a/compiler/jni/quick/mips64/calling_convention_mips64.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_JNI_QUICK_MIPS64_CALLING_CONVENTION_MIPS64_H_
-#define ART_COMPILER_JNI_QUICK_MIPS64_CALLING_CONVENTION_MIPS64_H_
-
-#include "base/enums.h"
-#include "jni/quick/calling_convention.h"
-
-namespace art {
-namespace mips64 {
-
-constexpr size_t kFramePointerSize = 8;
-static_assert(kFramePointerSize == static_cast<size_t>(PointerSize::k64),
- "Invalid frame pointer size");
-
-class Mips64ManagedRuntimeCallingConvention final : public ManagedRuntimeCallingConvention {
- public:
- Mips64ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
- : ManagedRuntimeCallingConvention(is_static,
- is_synchronized,
- shorty,
- PointerSize::k64) {}
- ~Mips64ManagedRuntimeCallingConvention() override {}
- // Calling convention
- ManagedRegister ReturnRegister() override;
- ManagedRegister InterproceduralScratchRegister() const override;
- // Managed runtime calling convention
- ManagedRegister MethodRegister() override;
- bool IsCurrentParamInRegister() override;
- bool IsCurrentParamOnStack() override;
- ManagedRegister CurrentParamRegister() override;
- FrameOffset CurrentParamStackOffset() override;
- const ManagedRegisterEntrySpills& EntrySpills() override;
-
- private:
- ManagedRegisterEntrySpills entry_spills_;
-
- DISALLOW_COPY_AND_ASSIGN(Mips64ManagedRuntimeCallingConvention);
-};
-
-class Mips64JniCallingConvention final : public JniCallingConvention {
- public:
- Mips64JniCallingConvention(bool is_static,
- bool is_synchronized,
- bool is_critical_native,
- const char* shorty);
- ~Mips64JniCallingConvention() override {}
- // Calling convention
- ManagedRegister ReturnRegister() override;
- ManagedRegister IntReturnRegister() override;
- ManagedRegister InterproceduralScratchRegister() const override;
- // JNI calling convention
- size_t FrameSize() const override;
- size_t OutArgSize() const override;
- ArrayRef<const ManagedRegister> CalleeSaveRegisters() const override;
- ManagedRegister ReturnScratchRegister() const override;
- uint32_t CoreSpillMask() const override;
- uint32_t FpSpillMask() const override;
- bool IsCurrentParamInRegister() override;
- bool IsCurrentParamOnStack() override;
- ManagedRegister CurrentParamRegister() override;
- FrameOffset CurrentParamStackOffset() override;
-
- // Mips64 does not need to extend small return types.
- bool RequiresSmallResultTypeExtension() const override {
- return false;
- }
-
- // Hidden argument register, used to pass the method pointer for @CriticalNative call.
- ManagedRegister HiddenArgumentRegister() const override;
-
- // Whether to use tail call (used only for @CriticalNative).
- bool UseTailCall() const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Mips64JniCallingConvention);
-};
-
-} // namespace mips64
-} // namespace art
-
-#endif // ART_COMPILER_JNI_QUICK_MIPS64_CALLING_CONVENTION_MIPS64_H_
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index aa21f86..0744aec2 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -33,7 +33,6 @@
#include "dwarf/debug_frame_opcode_writer.h"
#include "label.h"
#include "managed_register.h"
-#include "mips/constants_mips.h"
#include "offsets.h"
#include "x86/constants_x86.h"
#include "x86_64/constants_x86_64.h"
diff --git a/compiler/utils/jni_macro_assembler.cc b/compiler/utils/jni_macro_assembler.cc
index 5f405f3..d6d49f8 100644
--- a/compiler/utils/jni_macro_assembler.cc
+++ b/compiler/utils/jni_macro_assembler.cc
@@ -25,12 +25,6 @@
#ifdef ART_ENABLE_CODEGEN_arm64
#include "arm64/jni_macro_assembler_arm64.h"
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
-#include "mips/assembler_mips.h"
-#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
-#include "mips64/assembler_mips64.h"
-#endif
#ifdef ART_ENABLE_CODEGEN_x86
#include "x86/jni_macro_assembler_x86.h"
#endif
@@ -50,9 +44,8 @@
ArenaAllocator* allocator,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features) {
-#ifndef ART_ENABLE_CODEGEN_mips
+ // TODO: Remove the parameter from API (not needed after Mips target was removed).
UNUSED(instruction_set_features);
-#endif
switch (instruction_set) {
#ifdef ART_ENABLE_CODEGEN_arm
@@ -60,14 +53,6 @@
case InstructionSet::kThumb2:
return MacroAsm32UniquePtr(new (allocator) arm::ArmVIXLJNIMacroAssembler(allocator));
#endif
-#ifdef ART_ENABLE_CODEGEN_mips
- case InstructionSet::kMips:
- return MacroAsm32UniquePtr(new (allocator) mips::MipsAssembler(
- allocator,
- instruction_set_features != nullptr
- ? instruction_set_features->AsMipsInstructionSetFeatures()
- : nullptr));
-#endif
#ifdef ART_ENABLE_CODEGEN_x86
case InstructionSet::kX86:
return MacroAsm32UniquePtr(new (allocator) x86::X86JNIMacroAssembler(allocator));
@@ -85,23 +70,14 @@
ArenaAllocator* allocator,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features) {
-#ifndef ART_ENABLE_CODEGEN_mips64
+ // TODO: Remove the parameter from API (not needed after Mips64 target was removed).
UNUSED(instruction_set_features);
-#endif
switch (instruction_set) {
#ifdef ART_ENABLE_CODEGEN_arm64
case InstructionSet::kArm64:
return MacroAsm64UniquePtr(new (allocator) arm64::Arm64JNIMacroAssembler(allocator));
#endif
-#ifdef ART_ENABLE_CODEGEN_mips64
- case InstructionSet::kMips64:
- return MacroAsm64UniquePtr(new (allocator) mips64::Mips64Assembler(
- allocator,
- instruction_set_features != nullptr
- ? instruction_set_features->AsMips64InstructionSetFeatures()
- : nullptr));
-#endif
#ifdef ART_ENABLE_CODEGEN_x86_64
case InstructionSet::kX86_64:
return MacroAsm64UniquePtr(new (allocator) x86_64::X86_64JNIMacroAssembler(allocator));
diff --git a/compiler/utils/label.h b/compiler/utils/label.h
index 3c91b2f..9586a19 100644
--- a/compiler/utils/label.h
+++ b/compiler/utils/label.h
@@ -29,14 +29,6 @@
namespace arm64 {
class Arm64Assembler;
} // namespace arm64
-namespace mips {
-class MipsAssembler;
-class MipsLabel;
-} // namespace mips
-namespace mips64 {
-class Mips64Assembler;
-class Mips64Label;
-} // namespace mips64
namespace x86 {
class X86Assembler;
class NearLabel;
@@ -115,10 +107,6 @@
}
friend class arm64::Arm64Assembler;
- friend class mips::MipsAssembler;
- friend class mips::MipsLabel;
- friend class mips64::Mips64Assembler;
- friend class mips64::Mips64Label;
friend class x86::X86Assembler;
friend class x86::NearLabel;
friend class x86_64::X86_64Assembler;
diff --git a/compiler/utils/managed_register.h b/compiler/utils/managed_register.h
index fb41153..f20750b 100644
--- a/compiler/utils/managed_register.h
+++ b/compiler/utils/managed_register.h
@@ -30,12 +30,6 @@
namespace arm64 {
class Arm64ManagedRegister;
} // namespace arm64
-namespace mips {
-class MipsManagedRegister;
-} // namespace mips
-namespace mips64 {
-class Mips64ManagedRegister;
-} // namespace mips64
namespace x86 {
class X86ManagedRegister;
@@ -56,8 +50,6 @@
constexpr arm::ArmManagedRegister AsArm() const;
constexpr arm64::Arm64ManagedRegister AsArm64() const;
- constexpr mips::MipsManagedRegister AsMips() const;
- constexpr mips64::Mips64ManagedRegister AsMips64() const;
constexpr x86::X86ManagedRegister AsX86() const;
constexpr x86_64::X86_64ManagedRegister AsX86_64() const;
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
deleted file mode 100644
index 6b73695..0000000
--- a/compiler/utils/mips/assembler_mips.cc
+++ /dev/null
@@ -1,5271 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include "assembler_mips.h"
-
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/memory_region.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "entrypoints/quick/quick_entrypoints_enum.h"
-#include "thread.h"
-
-namespace art {
-namespace mips {
-
-static_assert(static_cast<size_t>(kMipsPointerSize) == kMipsWordSize,
- "Unexpected Mips pointer size.");
-static_assert(kMipsPointerSize == PointerSize::k32, "Unexpected Mips pointer size.");
-
-
-std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
- if (rhs >= D0 && rhs < kNumberOfDRegisters) {
- os << "d" << static_cast<int>(rhs);
- } else {
- os << "DRegister[" << static_cast<int>(rhs) << "]";
- }
- return os;
-}
-
-MipsAssembler::DelaySlot::DelaySlot()
- : instruction_(0),
- patcher_label_(nullptr) {}
-
-InOutRegMasks& MipsAssembler::DsFsmInstr(uint32_t instruction, MipsLabel* patcher_label) {
- if (!reordering_) {
- CHECK_EQ(ds_fsm_state_, kExpectingLabel);
- CHECK_EQ(delay_slot_.instruction_, 0u);
- return delay_slot_.masks_;
- }
- switch (ds_fsm_state_) {
- case kExpectingLabel:
- break;
- case kExpectingInstruction:
- CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size());
- // If the last instruction is not suitable for delay slots, drop
- // the PC of the label preceding it so that no unconditional branch
- // uses this instruction to fill its delay slot.
- if (instruction == 0) {
- DsFsmDropLabel(); // Sets ds_fsm_state_ = kExpectingLabel.
- } else {
- // Otherwise wait for another instruction or label before we can
- // commit the label PC. The label PC will be dropped if instead
- // of another instruction or label there's a call from the code
- // generator to CodePosition() to record the buffer size.
- // Instructions after which the buffer size is recorded cannot
- // be moved into delay slots or anywhere else because they may
- // trigger signals and the signal handlers expect these signals
- // to be coming from the instructions immediately preceding the
- // recorded buffer locations.
- ds_fsm_state_ = kExpectingCommit;
- }
- break;
- case kExpectingCommit:
- CHECK_EQ(ds_fsm_target_pc_ + 2 * sizeof(uint32_t), buffer_.Size());
- DsFsmCommitLabel(); // Sets ds_fsm_state_ = kExpectingLabel.
- break;
- }
- delay_slot_.instruction_ = instruction;
- delay_slot_.masks_ = InOutRegMasks();
- delay_slot_.patcher_label_ = patcher_label;
- return delay_slot_.masks_;
-}
-
-void MipsAssembler::DsFsmLabel() {
- if (!reordering_) {
- CHECK_EQ(ds_fsm_state_, kExpectingLabel);
- CHECK_EQ(delay_slot_.instruction_, 0u);
- return;
- }
- switch (ds_fsm_state_) {
- case kExpectingLabel:
- ds_fsm_target_pc_ = buffer_.Size();
- ds_fsm_state_ = kExpectingInstruction;
- break;
- case kExpectingInstruction:
- // Allow consecutive labels.
- CHECK_EQ(ds_fsm_target_pc_, buffer_.Size());
- break;
- case kExpectingCommit:
- CHECK_EQ(ds_fsm_target_pc_ + sizeof(uint32_t), buffer_.Size());
- DsFsmCommitLabel();
- ds_fsm_target_pc_ = buffer_.Size();
- ds_fsm_state_ = kExpectingInstruction;
- break;
- }
- // We cannot move instructions into delay slots across labels.
- delay_slot_.instruction_ = 0;
-}
-
-void MipsAssembler::DsFsmCommitLabel() {
- if (ds_fsm_state_ == kExpectingCommit) {
- ds_fsm_target_pcs_.emplace_back(ds_fsm_target_pc_);
- }
- ds_fsm_state_ = kExpectingLabel;
-}
-
-void MipsAssembler::DsFsmDropLabel() {
- ds_fsm_state_ = kExpectingLabel;
-}
-
-bool MipsAssembler::SetReorder(bool enable) {
- bool last_state = reordering_;
- if (last_state != enable) {
- DsFsmCommitLabel();
- DsFsmInstrNop(0);
- }
- reordering_ = enable;
- return last_state;
-}
-
-size_t MipsAssembler::CodePosition() {
- // The last instruction cannot be used in a delay slot, do not commit
- // the label before it (if any) and clear the delay slot.
- DsFsmDropLabel();
- DsFsmInstrNop(0);
- size_t size = buffer_.Size();
- // In theory we can get the following sequence:
- // label1:
- // instr
- // label2: # label1 gets committed when label2 is seen
- // CodePosition() call
- // and we need to uncommit label1.
- if (ds_fsm_target_pcs_.size() != 0 && ds_fsm_target_pcs_.back() + sizeof(uint32_t) == size) {
- ds_fsm_target_pcs_.pop_back();
- }
- return size;
-}
-
-void MipsAssembler::DsFsmInstrNop(uint32_t instruction ATTRIBUTE_UNUSED) {
- DsFsmInstr(0);
-}
-
-void MipsAssembler::FinalizeCode() {
- for (auto& exception_block : exception_blocks_) {
- EmitExceptionPoll(&exception_block);
- }
- // Commit the last branch target label (if any) and disable instruction reordering.
- DsFsmCommitLabel();
- SetReorder(false);
- EmitLiterals();
- ReserveJumpTableSpace();
- PromoteBranches();
-}
-
-void MipsAssembler::FinalizeInstructions(const MemoryRegion& region) {
- size_t number_of_delayed_adjust_pcs = cfi().NumberOfDelayedAdvancePCs();
- EmitBranches();
- EmitJumpTables();
- Assembler::FinalizeInstructions(region);
- PatchCFI(number_of_delayed_adjust_pcs);
-}
-
-void MipsAssembler::PatchCFI(size_t number_of_delayed_adjust_pcs) {
- if (cfi().NumberOfDelayedAdvancePCs() == 0u) {
- DCHECK_EQ(number_of_delayed_adjust_pcs, 0u);
- return;
- }
-
- using DelayedAdvancePC = DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC;
- const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
- const std::vector<uint8_t>& old_stream = data.first;
- const std::vector<DelayedAdvancePC>& advances = data.second;
-
- // PCs recorded before EmitBranches() need to be adjusted.
- // PCs recorded during EmitBranches() are already adjusted.
- // Both ranges are separately sorted but they may overlap.
- if (kIsDebugBuild) {
- auto cmp = [](const DelayedAdvancePC& lhs, const DelayedAdvancePC& rhs) {
- return lhs.pc < rhs.pc;
- };
- CHECK(std::is_sorted(advances.begin(), advances.begin() + number_of_delayed_adjust_pcs, cmp));
- CHECK(std::is_sorted(advances.begin() + number_of_delayed_adjust_pcs, advances.end(), cmp));
- }
-
- // Append initial CFI data if any.
- size_t size = advances.size();
- DCHECK_NE(size, 0u);
- cfi().AppendRawData(old_stream, 0u, advances[0].stream_pos);
- // Emit PC adjustments interleaved with the old CFI stream.
- size_t adjust_pos = 0u;
- size_t late_emit_pos = number_of_delayed_adjust_pcs;
- while (adjust_pos != number_of_delayed_adjust_pcs || late_emit_pos != size) {
- size_t adjusted_pc = (adjust_pos != number_of_delayed_adjust_pcs)
- ? GetAdjustedPosition(advances[adjust_pos].pc)
- : static_cast<size_t>(-1);
- size_t late_emit_pc = (late_emit_pos != size)
- ? advances[late_emit_pos].pc
- : static_cast<size_t>(-1);
- size_t advance_pc = std::min(adjusted_pc, late_emit_pc);
- DCHECK_NE(advance_pc, static_cast<size_t>(-1));
- size_t entry = (adjusted_pc <= late_emit_pc) ? adjust_pos : late_emit_pos;
- if (adjusted_pc <= late_emit_pc) {
- ++adjust_pos;
- } else {
- ++late_emit_pos;
- }
- cfi().AdvancePC(advance_pc);
- size_t end_pos = (entry + 1u == size) ? old_stream.size() : advances[entry + 1u].stream_pos;
- cfi().AppendRawData(old_stream, advances[entry].stream_pos, end_pos);
- }
-}
-
-void MipsAssembler::EmitBranches() {
- CHECK(!overwriting_);
- CHECK(!reordering_);
- // Now that everything has its final position in the buffer (the branches have
- // been promoted), adjust the target label PCs.
- for (size_t cnt = ds_fsm_target_pcs_.size(), i = 0; i < cnt; i++) {
- ds_fsm_target_pcs_[i] = GetAdjustedPosition(ds_fsm_target_pcs_[i]);
- }
- // Switch from appending instructions at the end of the buffer to overwriting
- // existing instructions (branch placeholders) in the buffer.
- overwriting_ = true;
- for (size_t id = 0; id < branches_.size(); id++) {
- EmitBranch(id);
- }
- overwriting_ = false;
-}
-
-void MipsAssembler::Emit(uint32_t value) {
- if (overwriting_) {
- // Branches to labels are emitted into their placeholders here.
- buffer_.Store<uint32_t>(overwrite_location_, value);
- overwrite_location_ += sizeof(uint32_t);
- } else {
- // Other instructions are simply appended at the end here.
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- buffer_.Emit<uint32_t>(value);
- }
-}
-
-uint32_t MipsAssembler::EmitR(int opcode,
- Register rs,
- Register rt,
- Register rd,
- int shamt,
- int funct) {
- CHECK_NE(rs, kNoRegister);
- CHECK_NE(rt, kNoRegister);
- CHECK_NE(rd, kNoRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- static_cast<uint32_t>(rt) << kRtShift |
- static_cast<uint32_t>(rd) << kRdShift |
- shamt << kShamtShift |
- funct;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitI(int opcode, Register rs, Register rt, uint16_t imm) {
- CHECK_NE(rs, kNoRegister);
- CHECK_NE(rt, kNoRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- static_cast<uint32_t>(rt) << kRtShift |
- imm;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitI21(int opcode, Register rs, uint32_t imm21) {
- CHECK_NE(rs, kNoRegister);
- CHECK(IsUint<21>(imm21)) << imm21;
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- imm21;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitI26(int opcode, uint32_t imm26) {
- CHECK(IsUint<26>(imm26)) << imm26;
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitFR(int opcode,
- int fmt,
- FRegister ft,
- FRegister fs,
- FRegister fd,
- int funct) {
- CHECK_NE(ft, kNoFRegister);
- CHECK_NE(fs, kNoFRegister);
- CHECK_NE(fd, kNoFRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- fmt << kFmtShift |
- static_cast<uint32_t>(ft) << kFtShift |
- static_cast<uint32_t>(fs) << kFsShift |
- static_cast<uint32_t>(fd) << kFdShift |
- funct;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitFI(int opcode, int fmt, FRegister ft, uint16_t imm) {
- CHECK_NE(ft, kNoFRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- fmt << kFmtShift |
- static_cast<uint32_t>(ft) << kFtShift |
- imm;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsa3R(int operation,
- int df,
- VectorRegister wt,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(wt, kNoVectorRegister);
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df << kDfShift |
- static_cast<uint32_t>(wt) << kWtShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsaBIT(int operation,
- int df_m,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df_m << kDfMShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsaELM(int operation,
- int df_n,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaELMOperationShift |
- df_n << kDfNShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsaMI10(int s10,
- Register rs,
- VectorRegister wd,
- int minor_opcode,
- int df) {
- CHECK_NE(rs, kNoRegister);
- CHECK_NE(wd, kNoVectorRegister);
- CHECK(IsUint<10>(s10)) << s10;
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- s10 << kS10Shift |
- static_cast<uint32_t>(rs) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode << kS10MinorShift |
- df;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsaI10(int operation,
- int df,
- int i10,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(wd, kNoVectorRegister);
- CHECK(IsUint<10>(i10)) << i10;
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df << kDfShift |
- i10 << kI10Shift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsa2R(int operation,
- int df,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsa2ROperationShift |
- df << kDf2RShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-uint32_t MipsAssembler::EmitMsa2RF(int operation,
- int df,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsa2RFOperationShift |
- df << kDf2RShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
- return encoding;
-}
-
-void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x21)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
- if (patcher_label != nullptr) {
- Bind(patcher_label);
- }
- DsFsmInstr(EmitI(0x9, rs, rt, imm16), patcher_label).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
- Addiu(rt, rs, imm16, /* patcher_label= */ nullptr);
-}
-
-void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x23)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::MultR2(Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18)).GprIns(rs, rt);
-}
-
-void MipsAssembler::MultuR2(Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19)).GprIns(rs, rt);
-}
-
-void MipsAssembler::DivR2(Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a)).GprIns(rs, rt);
-}
-
-void MipsAssembler::DivuR2(Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b)).GprIns(rs, rt);
-}
-
-void MipsAssembler::MulR2(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0x1c, rs, rt, rd, 0, 2)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::DivR2(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DivR2(rs, rt);
- Mflo(rd);
-}
-
-void MipsAssembler::ModR2(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DivR2(rs, rt);
- Mfhi(rd);
-}
-
-void MipsAssembler::DivuR2(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DivuR2(rs, rt);
- Mflo(rd);
-}
-
-void MipsAssembler::ModuR2(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DivuR2(rs, rt);
- Mfhi(rd);
-}
-
-void MipsAssembler::MulR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x18)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x18)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x19)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::DivR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x1a)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::ModR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x1a)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x1b)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x1b)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::And(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x24)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0xc, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Or(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x25)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0xd, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x26)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0xe, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x27)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Movz(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x0A)).GprInOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Movn(Register rd, Register rs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x0B)).GprInOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x35)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Selnez(Register rd, Register rs, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x37)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::ClzR6(Register rd, Register rs) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10)).GprOuts(rd).GprIns(rs);
-}
-
-void MipsAssembler::ClzR2(Register rd, Register rs) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0x1C, rs, rd, rd, 0, 0x20)).GprOuts(rd).GprIns(rs);
-}
-
-void MipsAssembler::CloR6(Register rd, Register rs) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11)).GprOuts(rd).GprIns(rs);
-}
-
-void MipsAssembler::CloR2(Register rd, Register rs) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0x1C, rs, rd, rd, 0, 0x21)).GprOuts(rd).GprIns(rs);
-}
-
-void MipsAssembler::Seb(Register rd, Register rt) {
- DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Seh(Register rd, Register rt) {
- DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Wsbh(Register rd, Register rt) {
- DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Bitswap(Register rd, Register rt) {
- CHECK(IsR6());
- DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Sll(Register rd, Register rt, int shamt) {
- CHECK(IsUint<5>(shamt)) << shamt;
- DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Srl(Register rd, Register rt, int shamt) {
- CHECK(IsUint<5>(shamt)) << shamt;
- DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Rotr(Register rd, Register rt, int shamt) {
- CHECK(IsUint<5>(shamt)) << shamt;
- DsFsmInstr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Sra(Register rd, Register rt, int shamt) {
- CHECK(IsUint<5>(shamt)) << shamt;
- DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03)).GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Sllv(Register rd, Register rt, Register rs) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x04)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Srlv(Register rd, Register rt, Register rs) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x06)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 1, 0x06)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Srav(Register rd, Register rt, Register rs) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x07)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(0 < size && size <= 32) << size;
- CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
- DsFsmInstr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00))
- .GprOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(0 < size && size <= 32) << size;
- CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
- DsFsmInstr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04))
- .GprInOuts(rd).GprIns(rt);
-}
-
-void MipsAssembler::Lsa(Register rd, Register rs, Register rt, int saPlusOne) {
- CHECK(IsR6() || HasMsa());
- CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
- int sa = saPlusOne - 1;
- DsFsmInstr(EmitR(0x0, rs, rt, rd, sa, 0x05)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::ShiftAndAdd(Register dst,
- Register src_idx,
- Register src_base,
- int shamt,
- Register tmp) {
- CHECK(0 <= shamt && shamt <= 4) << shamt;
- CHECK_NE(src_base, tmp);
- if (shamt == TIMES_1) {
- // Catch the special case where the shift amount is zero (0).
- Addu(dst, src_base, src_idx);
- } else if (IsR6() || HasMsa()) {
- Lsa(dst, src_idx, src_base, shamt);
- } else {
- Sll(tmp, src_idx, shamt);
- Addu(dst, src_base, tmp);
- }
-}
-
-void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x20, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x21, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
- if (patcher_label != nullptr) {
- Bind(patcher_label);
- }
- DsFsmInstr(EmitI(0x23, rs, rt, imm16), patcher_label).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
- Lw(rt, rs, imm16, /* patcher_label= */ nullptr);
-}
-
-void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x22, rs, rt, imm16)).GprInOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x26, rs, rt, imm16)).GprInOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x24, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x25, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Lwpc(Register rs, uint32_t imm19) {
- CHECK(IsR6());
- CHECK(IsUint<19>(imm19)) << imm19;
- DsFsmInstrNop(EmitI21(0x3B, rs, (0x01 << 19) | imm19));
-}
-
-void MipsAssembler::Lui(Register rt, uint16_t imm16) {
- DsFsmInstr(EmitI(0xf, static_cast<Register>(0), rt, imm16)).GprOuts(rt);
-}
-
-void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstr(EmitI(0xf, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::AddUpper(Register rt, Register rs, uint16_t imm16, Register tmp) {
- bool increment = (rs == rt);
- if (increment) {
- CHECK_NE(rs, tmp);
- }
- if (IsR6()) {
- Aui(rt, rs, imm16);
- } else if (increment) {
- Lui(tmp, imm16);
- Addu(rt, rs, tmp);
- } else {
- Lui(rt, imm16);
- Addu(rt, rs, rt);
- }
-}
-
-void MipsAssembler::Sync(uint32_t stype) {
- DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, stype & 0x1f, 0xf));
-}
-
-void MipsAssembler::Mfhi(Register rd) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, ZERO, ZERO, rd, 0, 0x10)).GprOuts(rd);
-}
-
-void MipsAssembler::Mflo(Register rd) {
- CHECK(!IsR6());
- DsFsmInstr(EmitR(0, ZERO, ZERO, rd, 0, 0x12)).GprOuts(rd);
-}
-
-void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x28, rs, rt, imm16)).GprIns(rt, rs);
-}
-
-void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x29, rs, rt, imm16)).GprIns(rt, rs);
-}
-
-void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
- if (patcher_label != nullptr) {
- Bind(patcher_label);
- }
- DsFsmInstr(EmitI(0x2b, rs, rt, imm16), patcher_label).GprIns(rt, rs);
-}
-
-void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
- Sw(rt, rs, imm16, /* patcher_label= */ nullptr);
-}
-
-void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x2a, rs, rt, imm16)).GprIns(rt, rs);
-}
-
-void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x2e, rs, rt, imm16)).GprIns(rt, rs);
-}
-
-void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x30, base, rt, imm16)).GprOuts(rt).GprIns(base);
-}
-
-void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) {
- CHECK(!IsR6());
- DsFsmInstr(EmitI(0x38, base, rt, imm16)).GprInOuts(rt).GprIns(base);
-}
-
-void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) {
- CHECK(IsR6());
- CHECK(IsInt<9>(imm9));
- DsFsmInstr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36)).GprOuts(rt).GprIns(base);
-}
-
-void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) {
- CHECK(IsR6());
- CHECK(IsInt<9>(imm9));
- DsFsmInstr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26)).GprInOuts(rt).GprIns(base);
-}
-
-void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x2a)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
- DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x2b)).GprOuts(rd).GprIns(rs, rt);
-}
-
-void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0xa, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0xb, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
-}
-
-void MipsAssembler::B(uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x4, static_cast<Register>(0), static_cast<Register>(0), imm16));
-}
-
-void MipsAssembler::Bal(uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x11), imm16));
-}
-
-void MipsAssembler::Beq(Register rs, Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x4, rs, rt, imm16));
-}
-
-void MipsAssembler::Bne(Register rs, Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x5, rs, rt, imm16));
-}
-
-void MipsAssembler::Beqz(Register rt, uint16_t imm16) {
- Beq(rt, ZERO, imm16);
-}
-
-void MipsAssembler::Bnez(Register rt, uint16_t imm16) {
- Bne(rt, ZERO, imm16);
-}
-
-void MipsAssembler::Bltz(Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0), imm16));
-}
-
-void MipsAssembler::Bgez(Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x1, rt, static_cast<Register>(0x1), imm16));
-}
-
-void MipsAssembler::Blez(Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x6, rt, static_cast<Register>(0), imm16));
-}
-
-void MipsAssembler::Bgtz(Register rt, uint16_t imm16) {
- DsFsmInstrNop(EmitI(0x7, rt, static_cast<Register>(0), imm16));
-}
-
-void MipsAssembler::Bc1f(uint16_t imm16) {
- Bc1f(0, imm16);
-}
-
-void MipsAssembler::Bc1f(int cc, uint16_t imm16) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstrNop(EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16));
-}
-
-void MipsAssembler::Bc1t(uint16_t imm16) {
- Bc1t(0, imm16);
-}
-
-void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstrNop(EmitI(0x11,
- static_cast<Register>(0x8),
- static_cast<Register>((cc << 2) | 1),
- imm16));
-}
-
-void MipsAssembler::J(uint32_t addr26) {
- DsFsmInstrNop(EmitI26(0x2, addr26));
-}
-
-void MipsAssembler::Jal(uint32_t addr26) {
- DsFsmInstrNop(EmitI26(0x3, addr26));
-}
-
-void MipsAssembler::Jalr(Register rd, Register rs) {
- uint32_t last_instruction = delay_slot_.instruction_;
- MipsLabel* patcher_label = delay_slot_.patcher_label_;
- bool exchange = (last_instruction != 0 &&
- (delay_slot_.masks_.gpr_outs_ & (1u << rs)) == 0 &&
- ((delay_slot_.masks_.gpr_ins_ | delay_slot_.masks_.gpr_outs_) & (1u << rd)) == 0);
- if (exchange) {
- // The last instruction cannot be used in a different delay slot,
- // do not commit the label before it (if any).
- DsFsmDropLabel();
- }
- DsFsmInstrNop(EmitR(0, rs, static_cast<Register>(0), rd, 0, 0x09));
- if (exchange) {
- // Exchange the last two instructions in the assembler buffer.
- size_t size = buffer_.Size();
- CHECK_GE(size, 2 * sizeof(uint32_t));
- size_t pos1 = size - 2 * sizeof(uint32_t);
- size_t pos2 = size - sizeof(uint32_t);
- uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
- uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
- CHECK_EQ(instr1, last_instruction);
- buffer_.Store<uint32_t>(pos1, instr2);
- buffer_.Store<uint32_t>(pos2, instr1);
- // Move the patcher label along with the patched instruction.
- if (patcher_label != nullptr) {
- patcher_label->AdjustBoundPosition(sizeof(uint32_t));
- }
- } else if (reordering_) {
- Nop();
- }
-}
-
-void MipsAssembler::Jalr(Register rs) {
- Jalr(RA, rs);
-}
-
-void MipsAssembler::Jr(Register rs) {
- Jalr(ZERO, rs);
-}
-
-void MipsAssembler::Nal() {
- DsFsmInstrNop(EmitI(0x1, static_cast<Register>(0), static_cast<Register>(0x10), 0));
-}
-
-void MipsAssembler::Auipc(Register rs, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitI(0x3B, rs, static_cast<Register>(0x1E), imm16));
-}
-
-void MipsAssembler::Addiupc(Register rs, uint32_t imm19) {
- CHECK(IsR6());
- CHECK(IsUint<19>(imm19)) << imm19;
- DsFsmInstrNop(EmitI21(0x3B, rs, imm19));
-}
-
-void MipsAssembler::Bc(uint32_t imm26) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitI26(0x32, imm26));
-}
-
-void MipsAssembler::Balc(uint32_t imm26) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitI26(0x3A, imm26));
-}
-
-void MipsAssembler::Jic(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitI(0x36, static_cast<Register>(0), rt, imm16));
-}
-
-void MipsAssembler::Jialc(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitI(0x3E, static_cast<Register>(0), rt, imm16));
-}
-
-void MipsAssembler::Bltc(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x17, rs, rt, imm16));
-}
-
-void MipsAssembler::Bltzc(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rt, ZERO);
- DsFsmInstrNop(EmitI(0x17, rt, rt, imm16));
-}
-
-void MipsAssembler::Bgtzc(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rt, ZERO);
- DsFsmInstrNop(EmitI(0x17, static_cast<Register>(0), rt, imm16));
-}
-
-void MipsAssembler::Bgec(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x16, rs, rt, imm16));
-}
-
-void MipsAssembler::Bgezc(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rt, ZERO);
- DsFsmInstrNop(EmitI(0x16, rt, rt, imm16));
-}
-
-void MipsAssembler::Blezc(Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rt, ZERO);
- DsFsmInstrNop(EmitI(0x16, static_cast<Register>(0), rt, imm16));
-}
-
-void MipsAssembler::Bltuc(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x7, rs, rt, imm16));
-}
-
-void MipsAssembler::Bgeuc(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x6, rs, rt, imm16));
-}
-
-void MipsAssembler::Beqc(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16));
-}
-
-void MipsAssembler::Bnec(Register rs, Register rt, uint16_t imm16) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- DsFsmInstrNop(EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16));
-}
-
-void MipsAssembler::Beqzc(Register rs, uint32_t imm21) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- DsFsmInstrNop(EmitI21(0x36, rs, imm21));
-}
-
-void MipsAssembler::Bnezc(Register rs, uint32_t imm21) {
- CHECK(IsR6());
- CHECK_NE(rs, ZERO);
- DsFsmInstrNop(EmitI21(0x3E, rs, imm21));
-}
-
-void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitFI(0x11, 0x9, ft, imm16));
-}
-
-void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) {
- CHECK(IsR6());
- DsFsmInstrNop(EmitFI(0x11, 0xD, ft, imm16));
-}
-
-void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) {
- switch (cond) {
- case kCondLTZ:
- CHECK_EQ(rt, ZERO);
- Bltz(rs, imm16);
- break;
- case kCondGEZ:
- CHECK_EQ(rt, ZERO);
- Bgez(rs, imm16);
- break;
- case kCondLEZ:
- CHECK_EQ(rt, ZERO);
- Blez(rs, imm16);
- break;
- case kCondGTZ:
- CHECK_EQ(rt, ZERO);
- Bgtz(rs, imm16);
- break;
- case kCondEQ:
- Beq(rs, rt, imm16);
- break;
- case kCondNE:
- Bne(rs, rt, imm16);
- break;
- case kCondEQZ:
- CHECK_EQ(rt, ZERO);
- Beqz(rs, imm16);
- break;
- case kCondNEZ:
- CHECK_EQ(rt, ZERO);
- Bnez(rs, imm16);
- break;
- case kCondF:
- CHECK_EQ(rt, ZERO);
- Bc1f(static_cast<int>(rs), imm16);
- break;
- case kCondT:
- CHECK_EQ(rt, ZERO);
- Bc1t(static_cast<int>(rs), imm16);
- break;
- case kCondLT:
- case kCondGE:
- case kCondLE:
- case kCondGT:
- case kCondLTU:
- case kCondGEU:
- case kUncond:
- // We don't support synthetic R2 branches (preceded with slt[u]) at this level
- // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
- LOG(FATAL) << "Unexpected branch condition " << cond;
- UNREACHABLE();
- }
-}
-
-void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) {
- switch (cond) {
- case kCondLT:
- Bltc(rs, rt, imm16_21);
- break;
- case kCondGE:
- Bgec(rs, rt, imm16_21);
- break;
- case kCondLE:
- Bgec(rt, rs, imm16_21);
- break;
- case kCondGT:
- Bltc(rt, rs, imm16_21);
- break;
- case kCondLTZ:
- CHECK_EQ(rt, ZERO);
- Bltzc(rs, imm16_21);
- break;
- case kCondGEZ:
- CHECK_EQ(rt, ZERO);
- Bgezc(rs, imm16_21);
- break;
- case kCondLEZ:
- CHECK_EQ(rt, ZERO);
- Blezc(rs, imm16_21);
- break;
- case kCondGTZ:
- CHECK_EQ(rt, ZERO);
- Bgtzc(rs, imm16_21);
- break;
- case kCondEQ:
- Beqc(rs, rt, imm16_21);
- break;
- case kCondNE:
- Bnec(rs, rt, imm16_21);
- break;
- case kCondEQZ:
- CHECK_EQ(rt, ZERO);
- Beqzc(rs, imm16_21);
- break;
- case kCondNEZ:
- CHECK_EQ(rt, ZERO);
- Bnezc(rs, imm16_21);
- break;
- case kCondLTU:
- Bltuc(rs, rt, imm16_21);
- break;
- case kCondGEU:
- Bgeuc(rs, rt, imm16_21);
- break;
- case kCondF:
- CHECK_EQ(rt, ZERO);
- Bc1eqz(static_cast<FRegister>(rs), imm16_21);
- break;
- case kCondT:
- CHECK_EQ(rt, ZERO);
- Bc1nez(static_cast<FRegister>(rs), imm16_21);
- break;
- case kUncond:
- LOG(FATAL) << "Unexpected branch condition " << cond;
- UNREACHABLE();
- }
-}
-
-void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x0)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x2)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x3)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x0)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x2)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x3)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::MovS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::MovD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::NegS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::NegD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::CunS(FRegister fs, FRegister ft) {
- CunS(0, fs, ft);
-}
-
-void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
- CeqS(0, fs, ft);
-}
-
-void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
- CueqS(0, fs, ft);
-}
-
-void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
- ColtS(0, fs, ft);
-}
-
-void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CultS(FRegister fs, FRegister ft) {
- CultS(0, fs, ft);
-}
-
-void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
- ColeS(0, fs, ft);
-}
-
-void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
- CuleS(0, fs, ft);
-}
-
-void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CunD(FRegister fs, FRegister ft) {
- CunD(0, fs, ft);
-}
-
-void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
- CeqD(0, fs, ft);
-}
-
-void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
- CueqD(0, fs, ft);
-}
-
-void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
- ColtD(0, fs, ft);
-}
-
-void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CultD(FRegister fs, FRegister ft) {
- CultD(0, fs, ft);
-}
-
-void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
- ColeD(0, fs, ft);
-}
-
-void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
- CuleD(0, fs, ft);
-}
-
-void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37))
- .CcOuts(cc).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x01)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x02)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x03)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x04)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x05)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x06)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x07)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x11)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x12)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x13)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x01)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x02)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x03)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x04)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x05)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x06)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x07)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x11)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x12)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x13)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::Movf(Register rd, Register rs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01))
- .GprInOuts(rd).GprIns(rs).CcIns(cc);
-}
-
-void MipsAssembler::Movt(Register rd, Register rs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01))
- .GprInOuts(rd).GprIns(rs).CcIns(cc);
-}
-
-void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11))
- .FprInOuts(fd).FprIns(fs).CcIns(cc);
-}
-
-void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11))
- .FprInOuts(fd).FprIns(fs).CcIns(cc);
-}
-
-void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11))
- .FprInOuts(fd).FprIns(fs).CcIns(cc);
-}
-
-void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
- CHECK(!IsR6());
- CHECK(IsUint<3>(cc)) << cc;
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11))
- .FprInOuts(fd).FprIns(fs).CcIns(cc);
-}
-
-void MipsAssembler::MovzS(FRegister fd, FRegister fs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12))
- .FprInOuts(fd).FprIns(fs).GprIns(rt);
-}
-
-void MipsAssembler::MovzD(FRegister fd, FRegister fs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12))
- .FprInOuts(fd).FprIns(fs).GprIns(rt);
-}
-
-void MipsAssembler::MovnS(FRegister fd, FRegister fs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13))
- .FprInOuts(fd).FprIns(fs).GprIns(rt);
-}
-
-void MipsAssembler::MovnD(FRegister fd, FRegister fs, Register rt) {
- CHECK(!IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13))
- .FprInOuts(fd).FprIns(fs).GprIns(rt);
-}
-
-void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x10)).FprInOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x10)).FprInOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SeleqzS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x14)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SeleqzD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x14)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SelnezS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x17)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::SelnezD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x17)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
- CHECK(IsR6());
- DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e)).FprOuts(fd).FprIns(fs, ft);
-}
-
-void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::TruncLD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::TruncWS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::TruncWD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtds(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf)).FprOuts(fd).FprIns(fs);
-}
-
-void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf)).FprOuts(fd).FprIns(fs);
-}
-
-FRegister MipsAssembler::GetFpuRegLow(FRegister reg) {
- // If FPRs are 32-bit (and get paired to hold 64-bit values), accesses to
- // odd-numbered FPRs are reattributed to even-numbered FPRs. This lets us
- // use only even-numbered FPRs irrespective of whether we're doing single-
- // or double-precision arithmetic. (We don't use odd-numbered 32-bit FPRs
- // to hold single-precision values).
- return Is32BitFPU() ? static_cast<FRegister>(reg & ~1u) : reg;
-}
-
-void MipsAssembler::Mfc1(Register rt, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
- .GprOuts(rt).FprIns(GetFpuRegLow(fs));
-}
-
-// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
-// when loading the value as 32-bit halves.
-void MipsAssembler::Mtc1(Register rt, FRegister fs) {
- uint32_t encoding =
- EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
- if (Is32BitFPU() && (fs % 2 != 0)) {
- // If mtc1 is used to simulate mthc1 by writing to the odd-numbered FPR in
- // a pair of 32-bit FPRs, the associated even-numbered FPR is an in/out.
- DsFsmInstr(encoding).FprInOuts(GetFpuRegLow(fs)).GprIns(rt);
- } else {
- // Otherwise (the FPR is 64-bit or even-numbered), the FPR is an out.
- DsFsmInstr(encoding).FprOuts(fs).GprIns(rt);
- }
-}
-
-void MipsAssembler::Mfhc1(Register rt, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
- .GprOuts(rt).FprIns(fs);
-}
-
-// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
-// when loading the value as 32-bit halves.
-void MipsAssembler::Mthc1(Register rt, FRegister fs) {
- DsFsmInstr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
- .FprInOuts(fs).GprIns(rt);
-}
-
-void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) {
- if (Is32BitFPU()) {
- CHECK_EQ(fs % 2, 0) << fs;
- Mfc1(rt, static_cast<FRegister>(fs + 1));
- } else {
- Mfhc1(rt, fs);
- }
-}
-
-void MipsAssembler::MoveToFpuHigh(Register rt, FRegister fs) {
- if (Is32BitFPU()) {
- CHECK_EQ(fs % 2, 0) << fs;
- Mtc1(rt, static_cast<FRegister>(fs + 1));
- } else {
- Mthc1(rt, fs);
- }
-}
-
-// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
-// when loading the value as 32-bit halves.
-void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
- uint32_t encoding = EmitI(0x31, rs, static_cast<Register>(ft), imm16);
- if (Is32BitFPU() && (ft % 2 != 0)) {
- // If lwc1 is used to load the odd-numbered FPR in a pair of 32-bit FPRs,
- // the associated even-numbered FPR is an in/out.
- DsFsmInstr(encoding).FprInOuts(GetFpuRegLow(ft)).GprIns(rs);
- } else {
- // Otherwise (the FPR is 64-bit or even-numbered), the FPR is an out.
- DsFsmInstr(encoding).FprOuts(ft).GprIns(rs);
- }
-}
-
-void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x35, rs, static_cast<Register>(ft), imm16)).FprOuts(ft).GprIns(rs);
-}
-
-void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x39, rs, static_cast<Register>(ft), imm16)).FprIns(GetFpuRegLow(ft)).GprIns(rs);
-}
-
-void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) {
- DsFsmInstr(EmitI(0x3d, rs, static_cast<Register>(ft), imm16)).FprIns(ft).GprIns(rs);
-}
-
-void MipsAssembler::Break() {
- DsFsmInstrNop(EmitR(0, ZERO, ZERO, ZERO, 0, 0xD));
-}
-
-void MipsAssembler::Nop() {
- DsFsmInstrNop(EmitR(0x0, ZERO, ZERO, ZERO, 0, 0x0));
-}
-
-void MipsAssembler::NopIfNoReordering() {
- if (!reordering_) {
- Nop();
- }
-}
-
-void MipsAssembler::Move(Register rd, Register rs) {
- Or(rd, rs, ZERO);
-}
-
-void MipsAssembler::Clear(Register rd) {
- Move(rd, ZERO);
-}
-
-void MipsAssembler::Not(Register rd, Register rs) {
- Nor(rd, rs, ZERO);
-}
-
-void MipsAssembler::Push(Register rs) {
- IncreaseFrameSize(kStackAlignment);
- Sw(rs, SP, 0);
-}
-
-void MipsAssembler::Pop(Register rd) {
- Lw(rd, SP, 0);
- DecreaseFrameSize(kStackAlignment);
-}
-
-void MipsAssembler::PopAndReturn(Register rd, Register rt) {
- bool reordering = SetReorder(false);
- Lw(rd, SP, 0);
- Jr(rt);
- DecreaseFrameSize(kStackAlignment); // Single instruction in delay slot.
- SetReorder(reordering);
-}
-
-void MipsAssembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- DsFsmInstr(EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- DsFsmInstr(EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- DsFsmInstr(EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- DsFsmInstr(EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- DsFsmInstr(EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- DsFsmInstr(EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- DsFsmInstr(EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- DsFsmInstr(EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- DsFsmInstr(EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- DsFsmInstr(EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- DsFsmInstr(EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- DsFsmInstr(EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::MoveV(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- DsFsmInstr(EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- DsFsmInstr(EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- DsFsmInstr(EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
- CHECK(HasMsa());
- CHECK(IsUint<1>(n1)) << n1;
- DsFsmInstr(EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::Copy_sB(Register rd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- DsFsmInstr(EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19))
- .GprOuts(rd).FprIns(ws);
-}
-
-void MipsAssembler::Copy_sH(Register rd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- DsFsmInstr(EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19))
- .GprOuts(rd).FprIns(ws);
-}
-
-void MipsAssembler::Copy_sW(Register rd, VectorRegister ws, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- DsFsmInstr(EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19))
- .GprOuts(rd).FprIns(ws);
-}
-
-void MipsAssembler::Copy_uB(Register rd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- DsFsmInstr(EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19))
- .GprOuts(rd).FprIns(ws);
-}
-
-void MipsAssembler::Copy_uH(Register rd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- DsFsmInstr(EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19))
- .GprOuts(rd).FprIns(ws);
-}
-
-void MipsAssembler::InsertB(VectorRegister wd, Register rs, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- DsFsmInstr(EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19))
- .FprInOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::InsertH(VectorRegister wd, Register rs, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- DsFsmInstr(EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19))
- .FprInOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::InsertW(VectorRegister wd, Register rs, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- DsFsmInstr(EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19))
- .FprInOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::FillB(VectorRegister wd, Register rs) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::FillH(VectorRegister wd, Register rs) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::FillW(VectorRegister wd, Register rs) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::LdiB(VectorRegister wd, int imm8) {
- CHECK(HasMsa());
- CHECK(IsInt<8>(imm8)) << imm8;
- DsFsmInstr(EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
-}
-
-void MipsAssembler::LdiH(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- DsFsmInstr(EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
-}
-
-void MipsAssembler::LdiW(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- DsFsmInstr(EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
-}
-
-void MipsAssembler::LdiD(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- DsFsmInstr(EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
-}
-
-void MipsAssembler::LdB(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(offset)) << offset;
- DsFsmInstr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0)).FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::LdH(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<11>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsHalfwordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::LdW(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<12>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsWordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::LdD(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<13>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsDoublewordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3))
- .FprOuts(wd).GprIns(rs);
-}
-
-void MipsAssembler::StB(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(offset)) << offset;
- DsFsmInstr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0)).FprIns(wd).GprIns(rs);
-}
-
-void MipsAssembler::StH(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<11>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsHalfwordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1))
- .FprIns(wd).GprIns(rs);
-}
-
-void MipsAssembler::StW(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<12>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsWordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2))
- .FprIns(wd).GprIns(rs);
-}
-
-void MipsAssembler::StD(VectorRegister wd, Register rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<13>(offset)) << offset;
- CHECK_ALIGNED(offset, kMipsDoublewordSize);
- DsFsmInstr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3))
- .FprIns(wd).GprIns(rs);
-}
-
-void MipsAssembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
-}
-
-void MipsAssembler::PcntB(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc1, 0x0, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::PcntH(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc1, 0x1, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::PcntW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc1, 0x2, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::PcntD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- DsFsmInstr(EmitMsa2R(0xc1, 0x3, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
-}
-
-void MipsAssembler::ReplicateFPToVectorRegister(VectorRegister dst,
- FRegister src,
- bool is_double) {
- // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
- if (is_double) {
- SplatiD(dst, static_cast<VectorRegister>(src), 0);
- } else {
- SplatiW(dst, static_cast<VectorRegister>(src), 0);
- }
-}
-
-void MipsAssembler::LoadConst32(Register rd, int32_t value) {
- if (IsUint<16>(value)) {
- // Use OR with (unsigned) immediate to encode 16b unsigned int.
- Ori(rd, ZERO, value);
- } else if (IsInt<16>(value)) {
- // Use ADD with (signed) immediate to encode 16b signed int.
- Addiu(rd, ZERO, value);
- } else {
- Lui(rd, High16Bits(value));
- if (value & 0xFFFF)
- Ori(rd, rd, Low16Bits(value));
- }
-}
-
-void MipsAssembler::LoadConst64(Register reg_hi, Register reg_lo, int64_t value) {
- uint32_t low = Low32Bits(value);
- uint32_t high = High32Bits(value);
- LoadConst32(reg_lo, low);
- if (high != low) {
- LoadConst32(reg_hi, high);
- } else {
- Move(reg_hi, reg_lo);
- }
-}
-
-void MipsAssembler::LoadSConst32(FRegister r, int32_t value, Register temp) {
- if (value == 0) {
- temp = ZERO;
- } else {
- LoadConst32(temp, value);
- }
- Mtc1(temp, r);
-}
-
-void MipsAssembler::LoadDConst64(FRegister rd, int64_t value, Register temp) {
- uint32_t low = Low32Bits(value);
- uint32_t high = High32Bits(value);
- if (low == 0) {
- Mtc1(ZERO, rd);
- } else {
- LoadConst32(temp, low);
- Mtc1(temp, rd);
- }
- if (high == 0) {
- MoveToFpuHigh(ZERO, rd);
- } else {
- LoadConst32(temp, high);
- MoveToFpuHigh(temp, rd);
- }
-}
-
-void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) {
- CHECK_NE(rs, temp); // Must not overwrite the register `rs` while loading `value`.
- if (IsInt<16>(value)) {
- Addiu(rt, rs, value);
- } else if (IsR6()) {
- int16_t high = High16Bits(value);
- int16_t low = Low16Bits(value);
- high += (low < 0) ? 1 : 0; // Account for sign extension in addiu.
- if (low != 0) {
- Aui(temp, rs, high);
- Addiu(rt, temp, low);
- } else {
- Aui(rt, rs, high);
- }
- } else {
- // Do not load the whole 32-bit `value` if it can be represented as
- // a sum of two 16-bit signed values. This can save an instruction.
- constexpr int32_t kMinValueForSimpleAdjustment = std::numeric_limits<int16_t>::min() * 2;
- constexpr int32_t kMaxValueForSimpleAdjustment = std::numeric_limits<int16_t>::max() * 2;
- if (0 <= value && value <= kMaxValueForSimpleAdjustment) {
- Addiu(temp, rs, kMaxValueForSimpleAdjustment / 2);
- Addiu(rt, temp, value - kMaxValueForSimpleAdjustment / 2);
- } else if (kMinValueForSimpleAdjustment <= value && value < 0) {
- Addiu(temp, rs, kMinValueForSimpleAdjustment / 2);
- Addiu(rt, temp, value - kMinValueForSimpleAdjustment / 2);
- } else {
- // Now that all shorter options have been exhausted, load the full 32-bit value.
- LoadConst32(temp, value);
- Addu(rt, rs, temp);
- }
- }
-}
-
-void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size,
- MipsAssembler::Branch::Type short_type,
- MipsAssembler::Branch::Type long_type) {
- type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
-}
-
-void MipsAssembler::Branch::InitializeType(Type initial_type, bool is_r6) {
- OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_);
- if (is_r6) {
- // R6
- switch (initial_type) {
- case kLabel:
- CHECK(!IsResolved());
- type_ = kR6Label;
- break;
- case kLiteral:
- CHECK(!IsResolved());
- type_ = kR6Literal;
- break;
- case kCall:
- InitShortOrLong(offset_size_needed, kR6Call, kR6LongCall);
- break;
- case kCondBranch:
- switch (condition_) {
- case kUncond:
- InitShortOrLong(offset_size_needed, kR6UncondBranch, kR6LongUncondBranch);
- break;
- case kCondEQZ:
- case kCondNEZ:
- // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
- type_ = (offset_size_needed <= kOffset23) ? kR6CondBranch : kR6LongCondBranch;
- break;
- default:
- InitShortOrLong(offset_size_needed, kR6CondBranch, kR6LongCondBranch);
- break;
- }
- break;
- case kBareCall:
- type_ = kR6BareCall;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- case kBareCondBranch:
- type_ = (condition_ == kUncond) ? kR6BareUncondBranch : kR6BareCondBranch;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- default:
- LOG(FATAL) << "Unexpected branch type " << initial_type;
- UNREACHABLE();
- }
- } else {
- // R2
- switch (initial_type) {
- case kLabel:
- CHECK(!IsResolved());
- type_ = kLabel;
- break;
- case kLiteral:
- CHECK(!IsResolved());
- type_ = kLiteral;
- break;
- case kCall:
- InitShortOrLong(offset_size_needed, kCall, kLongCall);
- break;
- case kCondBranch:
- switch (condition_) {
- case kUncond:
- InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch);
- break;
- default:
- InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch);
- break;
- }
- break;
- case kBareCall:
- type_ = kBareCall;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- case kBareCondBranch:
- type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- default:
- LOG(FATAL) << "Unexpected branch type " << initial_type;
- UNREACHABLE();
- }
- }
- old_type_ = type_;
-}
-
-bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) {
- switch (condition) {
- case kCondLT:
- case kCondGT:
- case kCondNE:
- case kCondLTU:
- return lhs == rhs;
- default:
- return false;
- }
-}
-
-bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) {
- switch (condition) {
- case kUncond:
- return true;
- case kCondGE:
- case kCondLE:
- case kCondEQ:
- case kCondGEU:
- return lhs == rhs;
- default:
- return false;
- }
-}
-
-MipsAssembler::Branch::Branch(bool is_r6,
- uint32_t location,
- uint32_t target,
- bool is_call,
- bool is_bare)
- : old_location_(location),
- location_(location),
- target_(target),
- lhs_reg_(0),
- rhs_reg_(0),
- condition_(kUncond),
- delayed_instruction_(kUnfilledDelaySlot),
- patcher_label_(nullptr) {
- InitializeType(
- (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)),
- is_r6);
-}
-
-MipsAssembler::Branch::Branch(bool is_r6,
- uint32_t location,
- uint32_t target,
- MipsAssembler::BranchCondition condition,
- Register lhs_reg,
- Register rhs_reg,
- bool is_bare)
- : old_location_(location),
- location_(location),
- target_(target),
- lhs_reg_(lhs_reg),
- rhs_reg_(rhs_reg),
- condition_(condition),
- delayed_instruction_(kUnfilledDelaySlot),
- patcher_label_(nullptr) {
- CHECK_NE(condition, kUncond);
- switch (condition) {
- case kCondLT:
- case kCondGE:
- case kCondLE:
- case kCondGT:
- case kCondLTU:
- case kCondGEU:
- // We don't support synthetic R2 branches (preceded with slt[u]) at this level
- // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
- // We leave this up to the caller.
- CHECK(is_r6);
- FALLTHROUGH_INTENDED;
- case kCondEQ:
- case kCondNE:
- // Require registers other than 0 not only for R6, but also for R2 to catch errors.
- // To compare with 0, use dedicated kCond*Z conditions.
- CHECK_NE(lhs_reg, ZERO);
- CHECK_NE(rhs_reg, ZERO);
- break;
- case kCondLTZ:
- case kCondGEZ:
- case kCondLEZ:
- case kCondGTZ:
- case kCondEQZ:
- case kCondNEZ:
- // Require registers other than 0 not only for R6, but also for R2 to catch errors.
- CHECK_NE(lhs_reg, ZERO);
- CHECK_EQ(rhs_reg, ZERO);
- break;
- case kCondF:
- case kCondT:
- CHECK_EQ(rhs_reg, ZERO);
- break;
- case kUncond:
- UNREACHABLE();
- }
- CHECK(!IsNop(condition, lhs_reg, rhs_reg));
- if (IsUncond(condition, lhs_reg, rhs_reg)) {
- // Branch condition is always true, make the branch unconditional.
- condition_ = kUncond;
- }
- InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6);
-}
-
-MipsAssembler::Branch::Branch(bool is_r6,
- uint32_t location,
- Register dest_reg,
- Register base_reg,
- Type label_or_literal_type)
- : old_location_(location),
- location_(location),
- target_(kUnresolved),
- lhs_reg_(dest_reg),
- rhs_reg_(base_reg),
- condition_(kUncond),
- delayed_instruction_(kUnfilledDelaySlot),
- patcher_label_(nullptr) {
- CHECK_NE(dest_reg, ZERO);
- if (is_r6) {
- CHECK_EQ(base_reg, ZERO);
- }
- InitializeType(label_or_literal_type, is_r6);
-}
-
-MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition(
- MipsAssembler::BranchCondition cond) {
- switch (cond) {
- case kCondLT:
- return kCondGE;
- case kCondGE:
- return kCondLT;
- case kCondLE:
- return kCondGT;
- case kCondGT:
- return kCondLE;
- case kCondLTZ:
- return kCondGEZ;
- case kCondGEZ:
- return kCondLTZ;
- case kCondLEZ:
- return kCondGTZ;
- case kCondGTZ:
- return kCondLEZ;
- case kCondEQ:
- return kCondNE;
- case kCondNE:
- return kCondEQ;
- case kCondEQZ:
- return kCondNEZ;
- case kCondNEZ:
- return kCondEQZ;
- case kCondLTU:
- return kCondGEU;
- case kCondGEU:
- return kCondLTU;
- case kCondF:
- return kCondT;
- case kCondT:
- return kCondF;
- case kUncond:
- LOG(FATAL) << "Unexpected branch condition " << cond;
- }
- UNREACHABLE();
-}
-
-MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const {
- return type_;
-}
-
-MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const {
- return condition_;
-}
-
-Register MipsAssembler::Branch::GetLeftRegister() const {
- return static_cast<Register>(lhs_reg_);
-}
-
-Register MipsAssembler::Branch::GetRightRegister() const {
- return static_cast<Register>(rhs_reg_);
-}
-
-uint32_t MipsAssembler::Branch::GetTarget() const {
- return target_;
-}
-
-uint32_t MipsAssembler::Branch::GetLocation() const {
- return location_;
-}
-
-uint32_t MipsAssembler::Branch::GetOldLocation() const {
- return old_location_;
-}
-
-uint32_t MipsAssembler::Branch::GetPrecedingInstructionLength(Type type) const {
- // Short branches with delay slots always consist of two instructions, the branch
- // and the delay slot, irrespective of whether the delay slot is filled with a
- // useful instruction or not.
- // Long composite branches may have a length longer by one instruction than
- // specified in branch_info_[].length. This happens when an instruction is taken
- // to fill the short branch delay slot, but the branch eventually becomes long
- // and formally has no delay slot to fill. This instruction is placed at the
- // beginning of the long composite branch and this needs to be accounted for in
- // the branch length and the location of the offset encoded in the branch.
- switch (type) {
- case kLongUncondBranch:
- case kLongCondBranch:
- case kLongCall:
- case kR6LongCondBranch:
- return (delayed_instruction_ != kUnfilledDelaySlot &&
- delayed_instruction_ != kUnfillableDelaySlot) ? 1 : 0;
- default:
- return 0;
- }
-}
-
-uint32_t MipsAssembler::Branch::GetPrecedingInstructionSize(Type type) const {
- return GetPrecedingInstructionLength(type) * sizeof(uint32_t);
-}
-
-uint32_t MipsAssembler::Branch::GetLength() const {
- return GetPrecedingInstructionLength(type_) + branch_info_[type_].length;
-}
-
-uint32_t MipsAssembler::Branch::GetOldLength() const {
- return GetPrecedingInstructionLength(old_type_) + branch_info_[old_type_].length;
-}
-
-uint32_t MipsAssembler::Branch::GetSize() const {
- return GetLength() * sizeof(uint32_t);
-}
-
-uint32_t MipsAssembler::Branch::GetOldSize() const {
- return GetOldLength() * sizeof(uint32_t);
-}
-
-uint32_t MipsAssembler::Branch::GetEndLocation() const {
- return GetLocation() + GetSize();
-}
-
-uint32_t MipsAssembler::Branch::GetOldEndLocation() const {
- return GetOldLocation() + GetOldSize();
-}
-
-bool MipsAssembler::Branch::IsBare() const {
- switch (type_) {
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- case kBareUncondBranch:
- case kBareCondBranch:
- case kBareCall:
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- case kR6BareUncondBranch:
- case kR6BareCondBranch:
- case kR6BareCall:
- return true;
- default:
- return false;
- }
-}
-
-bool MipsAssembler::Branch::IsLong() const {
- switch (type_) {
- // R2 short branches (can be promoted to long).
- case kUncondBranch:
- case kCondBranch:
- case kCall:
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- case kBareUncondBranch:
- case kBareCondBranch:
- case kBareCall:
- // R2 near label.
- case kLabel:
- // R2 near literal.
- case kLiteral:
- // R6 short branches (can be promoted to long).
- case kR6UncondBranch:
- case kR6CondBranch:
- case kR6Call:
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- case kR6BareUncondBranch:
- case kR6BareCondBranch:
- case kR6BareCall:
- // R6 near label.
- case kR6Label:
- // R6 near literal.
- case kR6Literal:
- return false;
- // R2 long branches.
- case kLongUncondBranch:
- case kLongCondBranch:
- case kLongCall:
- // R2 far label.
- case kFarLabel:
- // R2 far literal.
- case kFarLiteral:
- // R6 long branches.
- case kR6LongUncondBranch:
- case kR6LongCondBranch:
- case kR6LongCall:
- // R6 far label.
- case kR6FarLabel:
- // R6 far literal.
- case kR6FarLiteral:
- return true;
- }
- UNREACHABLE();
-}
-
-bool MipsAssembler::Branch::IsResolved() const {
- return target_ != kUnresolved;
-}
-
-MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const {
- bool r6_cond_branch = (type_ == kR6CondBranch || type_ == kR6BareCondBranch);
- OffsetBits offset_size =
- (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
- ? kOffset23
- : branch_info_[type_].offset_size;
- return offset_size;
-}
-
-MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location,
- uint32_t target) {
- // For unresolved targets assume the shortest encoding
- // (later it will be made longer if needed).
- if (target == kUnresolved)
- return kOffset16;
- int64_t distance = static_cast<int64_t>(target) - location;
- // To simplify calculations in composite branches consisting of multiple instructions
- // bump up the distance by a value larger than the max byte size of a composite branch.
- distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
- if (IsInt<kOffset16>(distance))
- return kOffset16;
- else if (IsInt<kOffset18>(distance))
- return kOffset18;
- else if (IsInt<kOffset21>(distance))
- return kOffset21;
- else if (IsInt<kOffset23>(distance))
- return kOffset23;
- else if (IsInt<kOffset28>(distance))
- return kOffset28;
- return kOffset32;
-}
-
-void MipsAssembler::Branch::Resolve(uint32_t target) {
- target_ = target;
-}
-
-void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
- if (location_ > expand_location) {
- location_ += delta;
- }
- if (!IsResolved()) {
- return; // Don't know the target yet.
- }
- if (target_ > expand_location) {
- target_ += delta;
- }
-}
-
-void MipsAssembler::Branch::PromoteToLong() {
- CHECK(!IsBare()); // Bare branches do not promote.
- switch (type_) {
- // R2 short branches (can be promoted to long).
- case kUncondBranch:
- type_ = kLongUncondBranch;
- break;
- case kCondBranch:
- type_ = kLongCondBranch;
- break;
- case kCall:
- type_ = kLongCall;
- break;
- // R2 near label.
- case kLabel:
- type_ = kFarLabel;
- break;
- // R2 near literal.
- case kLiteral:
- type_ = kFarLiteral;
- break;
- // R6 short branches (can be promoted to long).
- case kR6UncondBranch:
- type_ = kR6LongUncondBranch;
- break;
- case kR6CondBranch:
- type_ = kR6LongCondBranch;
- break;
- case kR6Call:
- type_ = kR6LongCall;
- break;
- // R6 near label.
- case kR6Label:
- type_ = kR6FarLabel;
- break;
- // R6 near literal.
- case kR6Literal:
- type_ = kR6FarLiteral;
- break;
- default:
- // Note: 'type_' is already long.
- break;
- }
- CHECK(IsLong());
-}
-
-uint32_t MipsAssembler::GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const {
- switch (branch->GetType()) {
- case Branch::kLabel:
- case Branch::kFarLabel:
- case Branch::kLiteral:
- case Branch::kFarLiteral:
- if (branch->GetRightRegister() != ZERO) {
- return GetLabelLocation(&pc_rel_base_label_);
- }
- // For those label/literal loads which come with their own NAL instruction
- // and don't depend on `pc_rel_base_label_` we can simply use the location
- // of the "branch" (the NAL precedes the "branch" immediately). The location
- // is close enough for the user of the returned location, PromoteIfNeeded(),
- // to not miss needed promotion to a far load.
- // (GetOffsetSizeNeeded() provides a little leeway by means of kMaxBranchSize,
- // which is larger than all composite branches and label/literal loads: it's
- // OK to promote a bit earlier than strictly necessary, it makes things
- // simpler.)
- FALLTHROUGH_INTENDED;
- default:
- return branch->GetLocation();
- }
-}
-
-uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t location, uint32_t max_short_distance) {
- // `location` comes from GetBranchLocationOrPcRelBase() and is either the location
- // of the PC-relative branch or (for some R2 label and literal loads) the location
- // of `pc_rel_base_label_`. The PC-relative offset of the branch/load is relative
- // to this location.
- // If the branch is still unresolved or already long, nothing to do.
- if (IsLong() || !IsResolved()) {
- return 0;
- }
- // Promote the short branch to long if the offset size is too small
- // to hold the distance between location and target_.
- if (GetOffsetSizeNeeded(location, target_) > GetOffsetSize()) {
- PromoteToLong();
- uint32_t old_size = GetOldSize();
- uint32_t new_size = GetSize();
- CHECK_GT(new_size, old_size);
- return new_size - old_size;
- }
- // The following logic is for debugging/testing purposes.
- // Promote some short branches to long when it's not really required.
- if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) {
- int64_t distance = static_cast<int64_t>(target_) - location;
- distance = (distance >= 0) ? distance : -distance;
- if (distance >= max_short_distance) {
- PromoteToLong();
- uint32_t old_size = GetOldSize();
- uint32_t new_size = GetSize();
- CHECK_GT(new_size, old_size);
- return new_size - old_size;
- }
- }
- return 0;
-}
-
-uint32_t MipsAssembler::Branch::GetOffsetLocation() const {
- return location_ + GetPrecedingInstructionSize(type_) +
- branch_info_[type_].instr_offset * sizeof(uint32_t);
-}
-
-uint32_t MipsAssembler::GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const {
- switch (branch->GetType()) {
- case Branch::kLabel:
- case Branch::kFarLabel:
- case Branch::kLiteral:
- case Branch::kFarLiteral:
- if (branch->GetRightRegister() == ZERO) {
- // These loads don't use `pc_rel_base_label_` and instead rely on their own
- // NAL instruction (it immediately precedes the "branch"). Therefore the
- // effective PC-relative base register is RA and it corresponds to the 2nd
- // instruction after the NAL.
- return branch->GetLocation() + sizeof(uint32_t);
- } else {
- return GetLabelLocation(&pc_rel_base_label_);
- }
- default:
- return branch->GetOffsetLocation() +
- Branch::branch_info_[branch->GetType()].pc_org * sizeof(uint32_t);
- }
-}
-
-uint32_t MipsAssembler::Branch::GetOffset(uint32_t location) const {
- // `location` comes from GetBranchOrPcRelBaseForEncoding() and is either a location
- // within/near the PC-relative branch or (for some R2 label and literal loads) the
- // location of `pc_rel_base_label_`. The PC-relative offset of the branch/load is
- // relative to this location.
- CHECK(IsResolved());
- uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
- // Calculate the byte distance between instructions and also account for
- // different PC-relative origins.
- uint32_t offset = target_ - location;
- // Prepare the offset for encoding into the instruction(s).
- offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
- return offset;
-}
-
-MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) {
- CHECK_LT(branch_id, branches_.size());
- return &branches_[branch_id];
-}
-
-const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const {
- CHECK_LT(branch_id, branches_.size());
- return &branches_[branch_id];
-}
-
-void MipsAssembler::BindRelativeToPrecedingBranch(MipsLabel* label,
- uint32_t prev_branch_id_plus_one,
- uint32_t position) {
- if (prev_branch_id_plus_one != 0) {
- const Branch* branch = GetBranch(prev_branch_id_plus_one - 1);
- position -= branch->GetEndLocation();
- }
- label->prev_branch_id_plus_one_ = prev_branch_id_plus_one;
- label->BindTo(position);
-}
-
-void MipsAssembler::Bind(MipsLabel* label) {
- CHECK(!label->IsBound());
- uint32_t bound_pc = buffer_.Size();
-
- // Make the delay slot FSM aware of the new label.
- DsFsmLabel();
-
- // Walk the list of branches referring to and preceding this label.
- // Store the previously unknown target addresses in them.
- while (label->IsLinked()) {
- uint32_t branch_id = label->Position();
- Branch* branch = GetBranch(branch_id);
- branch->Resolve(bound_pc);
-
- uint32_t branch_location = branch->GetLocation();
- // Extract the location of the previous branch in the list (walking the list backwards;
- // the previous branch ID was stored in the space reserved for this branch).
- uint32_t prev = buffer_.Load<uint32_t>(branch_location);
-
- // On to the previous branch in the list...
- label->position_ = prev;
- }
-
- // Now make the label object contain its own location (relative to the end of the preceding
- // branch, if any; it will be used by the branches referring to and following this label).
- BindRelativeToPrecedingBranch(label, branches_.size(), bound_pc);
-}
-
-uint32_t MipsAssembler::GetLabelLocation(const MipsLabel* label) const {
- CHECK(label->IsBound());
- uint32_t target = label->Position();
- if (label->prev_branch_id_plus_one_ != 0) {
- // Get label location based on the branch preceding it.
- const Branch* branch = GetBranch(label->prev_branch_id_plus_one_ - 1);
- target += branch->GetEndLocation();
- }
- return target;
-}
-
-uint32_t MipsAssembler::GetAdjustedPosition(uint32_t old_position) {
- // We can reconstruct the adjustment by going through all the branches from the beginning
- // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
- // with increasing old_position, we can use the data from last AdjustedPosition() to
- // continue where we left off and the whole loop should be O(m+n) where m is the number
- // of positions to adjust and n is the number of branches.
- if (old_position < last_old_position_) {
- last_position_adjustment_ = 0;
- last_old_position_ = 0;
- last_branch_id_ = 0;
- }
- while (last_branch_id_ != branches_.size()) {
- const Branch* branch = GetBranch(last_branch_id_);
- if (branch->GetLocation() >= old_position + last_position_adjustment_) {
- break;
- }
- last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
- ++last_branch_id_;
- }
- last_old_position_ = old_position;
- return old_position + last_position_adjustment_;
-}
-
-void MipsAssembler::BindPcRelBaseLabel() {
- Bind(&pc_rel_base_label_);
-}
-
-uint32_t MipsAssembler::GetPcRelBaseLabelLocation() const {
- return GetLabelLocation(&pc_rel_base_label_);
-}
-
-void MipsAssembler::FinalizeLabeledBranch(MipsLabel* label) {
- uint32_t length = branches_.back().GetLength();
- // Commit the last branch target label (if any).
- DsFsmCommitLabel();
- if (!label->IsBound()) {
- // Branch forward (to a following label), distance is unknown.
- // The first branch forward will contain 0, serving as the terminator of
- // the list of forward-reaching branches.
- Emit(label->position_);
- // Nothing for the delay slot (yet).
- DsFsmInstrNop(0);
- length--;
- // Now make the label object point to this branch
- // (this forms a linked list of branches preceding this label).
- uint32_t branch_id = branches_.size() - 1;
- label->LinkTo(branch_id);
- }
- // Reserve space for the branch.
- for (; length != 0u; --length) {
- Nop();
- }
-}
-
-bool MipsAssembler::Branch::CanHaveDelayedInstruction(const DelaySlot& delay_slot) const {
- if (delay_slot.instruction_ == 0) {
- // NOP or no instruction for the delay slot.
- return false;
- }
- switch (type_) {
- // R2 unconditional branches.
- case kUncondBranch:
- case kLongUncondBranch:
- // There are no register interdependencies.
- return true;
-
- // R2 calls.
- case kCall:
- case kLongCall:
- // Instructions depending on or modifying RA should not be moved into delay slots
- // of branches modifying RA.
- return ((delay_slot.masks_.gpr_ins_ | delay_slot.masks_.gpr_outs_) & (1u << RA)) == 0;
-
- // R2 conditional branches.
- case kCondBranch:
- case kLongCondBranch:
- switch (condition_) {
- // Branches with one GPR source.
- case kCondLTZ:
- case kCondGEZ:
- case kCondLEZ:
- case kCondGTZ:
- case kCondEQZ:
- case kCondNEZ:
- return (delay_slot.masks_.gpr_outs_ & (1u << lhs_reg_)) == 0;
-
- // Branches with two GPR sources.
- case kCondEQ:
- case kCondNE:
- return (delay_slot.masks_.gpr_outs_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0;
-
- // Branches with one FPU condition code source.
- case kCondF:
- case kCondT:
- return (delay_slot.masks_.cc_outs_ & (1u << lhs_reg_)) == 0;
-
- default:
- // We don't support synthetic R2 branches (preceded with slt[u]) at this level
- // (R2 doesn't have branches to compare 2 registers using <, <=, >=, >).
- LOG(FATAL) << "Unexpected branch condition " << condition_;
- UNREACHABLE();
- }
-
- // R6 unconditional branches.
- case kR6UncondBranch:
- case kR6LongUncondBranch:
- // R6 calls.
- case kR6Call:
- case kR6LongCall:
- // There are no delay slots.
- return false;
-
- // R6 conditional branches.
- case kR6CondBranch:
- case kR6LongCondBranch:
- switch (condition_) {
- // Branches with one FPU register source.
- case kCondF:
- case kCondT:
- return (delay_slot.masks_.fpr_outs_ & (1u << lhs_reg_)) == 0;
- // Others have a forbidden slot instead of a delay slot.
- default:
- return false;
- }
-
- // Literals.
- default:
- LOG(FATAL) << "Unexpected branch type " << type_;
- UNREACHABLE();
- }
-}
-
-uint32_t MipsAssembler::Branch::GetDelayedInstruction() const {
- return delayed_instruction_;
-}
-
-MipsLabel* MipsAssembler::Branch::GetPatcherLabel() const {
- return patcher_label_;
-}
-
-void MipsAssembler::Branch::SetDelayedInstruction(uint32_t instruction, MipsLabel* patcher_label) {
- CHECK_NE(instruction, kUnfilledDelaySlot);
- CHECK_EQ(delayed_instruction_, kUnfilledDelaySlot);
- delayed_instruction_ = instruction;
- patcher_label_ = patcher_label;
-}
-
-void MipsAssembler::Branch::DecrementLocations() {
- // We first create a branch object, which gets its type and locations initialized,
- // and then we check if the branch can actually have the preceding instruction moved
- // into its delay slot. If it can, the branch locations need to be decremented.
- //
- // We could make the check before creating the branch object and avoid the location
- // adjustment, but the check is cleaner when performed on an initialized branch
- // object.
- //
- // If the branch is backwards (to a previously bound label), reducing the locations
- // cannot cause a short branch to exceed its offset range because the offset reduces.
- // And this is not at all a problem for a long branch backwards.
- //
- // If the branch is forward (not linked to any label yet), reducing the locations
- // is harmless. The branch will be promoted to long if needed when the target is known.
- CHECK_EQ(location_, old_location_);
- CHECK_GE(old_location_, sizeof(uint32_t));
- old_location_ -= sizeof(uint32_t);
- location_ = old_location_;
-}
-
-void MipsAssembler::MoveInstructionToDelaySlot(Branch& branch) {
- if (branch.IsBare()) {
- // Delay slots are filled manually in bare branches.
- return;
- }
- if (branch.CanHaveDelayedInstruction(delay_slot_)) {
- // The last instruction cannot be used in a different delay slot,
- // do not commit the label before it (if any).
- DsFsmDropLabel();
- // Remove the last emitted instruction.
- size_t size = buffer_.Size();
- CHECK_GE(size, sizeof(uint32_t));
- size -= sizeof(uint32_t);
- CHECK_EQ(buffer_.Load<uint32_t>(size), delay_slot_.instruction_);
- buffer_.Resize(size);
- // Attach it to the branch and adjust the branch locations.
- branch.DecrementLocations();
- branch.SetDelayedInstruction(delay_slot_.instruction_, delay_slot_.patcher_label_);
- } else if (!reordering_ && branch.GetType() == Branch::kUncondBranch) {
- // If reordefing is disabled, prevent absorption of the target instruction.
- branch.SetDelayedInstruction(Branch::kUnfillableDelaySlot);
- }
-}
-
-void MipsAssembler::Buncond(MipsLabel* label, bool is_r6, bool is_bare) {
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(is_r6, buffer_.Size(), target, /* is_call= */ false, is_bare);
- MoveInstructionToDelaySlot(branches_.back());
- FinalizeLabeledBranch(label);
-}
-
-void MipsAssembler::Bcond(MipsLabel* label,
- bool is_r6,
- bool is_bare,
- BranchCondition condition,
- Register lhs,
- Register rhs) {
- // If lhs = rhs, this can be a NOP.
- if (Branch::IsNop(condition, lhs, rhs)) {
- return;
- }
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare);
- MoveInstructionToDelaySlot(branches_.back());
- FinalizeLabeledBranch(label);
-}
-
-void MipsAssembler::Call(MipsLabel* label, bool is_r6, bool is_bare) {
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(is_r6, buffer_.Size(), target, /* is_call= */ true, is_bare);
- MoveInstructionToDelaySlot(branches_.back());
- FinalizeLabeledBranch(label);
-}
-
-void MipsAssembler::LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label) {
- // Label address loads are treated as pseudo branches since they require very similar handling.
- DCHECK(!label->IsBound());
- // If `pc_rel_base_label_` isn't bound or none of registers contains its address, we
- // may generate an individual NAL instruction to simulate PC-relative addressing on R2
- // by specifying `base_reg` of `ZERO`. Check for it.
- if (base_reg == ZERO && !IsR6()) {
- Nal();
- }
- branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLabel);
- FinalizeLabeledBranch(label);
-}
-
-Literal* MipsAssembler::NewLiteral(size_t size, const uint8_t* data) {
- DCHECK(size == 4u || size == 8u) << size;
- literals_.emplace_back(size, data);
- return &literals_.back();
-}
-
-void MipsAssembler::LoadLiteral(Register dest_reg, Register base_reg, Literal* literal) {
- // Literal loads are treated as pseudo branches since they require very similar handling.
- DCHECK_EQ(literal->GetSize(), 4u);
- MipsLabel* label = literal->GetLabel();
- DCHECK(!label->IsBound());
- // If `pc_rel_base_label_` isn't bound or none of registers contains its address, we
- // may generate an individual NAL instruction to simulate PC-relative addressing on R2
- // by specifying `base_reg` of `ZERO`. Check for it.
- if (base_reg == ZERO && !IsR6()) {
- Nal();
- }
- branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLiteral);
- FinalizeLabeledBranch(label);
-}
-
-JumpTable* MipsAssembler::CreateJumpTable(std::vector<MipsLabel*>&& labels) {
- jump_tables_.emplace_back(std::move(labels));
- JumpTable* table = &jump_tables_.back();
- DCHECK(!table->GetLabel()->IsBound());
- return table;
-}
-
-void MipsAssembler::EmitLiterals() {
- if (!literals_.empty()) {
- // We don't support byte and half-word literals.
- // TODO: proper alignment for 64-bit literals when they're implemented.
- for (Literal& literal : literals_) {
- MipsLabel* label = literal.GetLabel();
- Bind(label);
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- DCHECK(literal.GetSize() == 4u || literal.GetSize() == 8u);
- for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
- buffer_.Emit<uint8_t>(literal.GetData()[i]);
- }
- }
- }
-}
-
-void MipsAssembler::ReserveJumpTableSpace() {
- if (!jump_tables_.empty()) {
- for (JumpTable& table : jump_tables_) {
- MipsLabel* label = table.GetLabel();
- Bind(label);
-
- // Bulk ensure capacity, as this may be large.
- size_t orig_size = buffer_.Size();
- size_t required_capacity = orig_size + table.GetSize();
- if (required_capacity > buffer_.Capacity()) {
- buffer_.ExtendCapacity(required_capacity);
- }
-#ifndef NDEBUG
- buffer_.has_ensured_capacity_ = true;
-#endif
-
- // Fill the space with dummy data as the data is not final
- // until the branches have been promoted. And we shouldn't
- // be moving uninitialized data during branch promotion.
- for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
- buffer_.Emit<uint32_t>(0x1abe1234u);
- }
-
-#ifndef NDEBUG
- buffer_.has_ensured_capacity_ = false;
-#endif
- }
- }
-}
-
-void MipsAssembler::EmitJumpTables() {
- if (!jump_tables_.empty()) {
- CHECK(!overwriting_);
- // Switch from appending instructions at the end of the buffer to overwriting
- // existing instructions (here, jump tables) in the buffer.
- overwriting_ = true;
-
- for (JumpTable& table : jump_tables_) {
- MipsLabel* table_label = table.GetLabel();
- uint32_t start = GetLabelLocation(table_label);
- overwrite_location_ = start;
-
- for (MipsLabel* target : table.GetData()) {
- CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
- // The table will contain target addresses relative to the table start.
- uint32_t offset = GetLabelLocation(target) - start;
- Emit(offset);
- }
- }
-
- overwriting_ = false;
- }
-}
-
-void MipsAssembler::PromoteBranches() {
- // Promote short branches to long as necessary.
- bool changed;
- do {
- changed = false;
- for (auto& branch : branches_) {
- CHECK(branch.IsResolved());
- uint32_t base = GetBranchLocationOrPcRelBase(&branch);
- uint32_t delta = branch.PromoteIfNeeded(base);
- // If this branch has been promoted and needs to expand in size,
- // relocate all branches by the expansion size.
- if (delta) {
- changed = true;
- uint32_t expand_location = branch.GetLocation();
- for (auto& branch2 : branches_) {
- branch2.Relocate(expand_location, delta);
- }
- }
- }
- } while (changed);
-
- // Account for branch expansion by resizing the code buffer
- // and moving the code in it to its final location.
- size_t branch_count = branches_.size();
- if (branch_count > 0) {
- // Resize.
- Branch& last_branch = branches_[branch_count - 1];
- uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
- uint32_t old_size = buffer_.Size();
- buffer_.Resize(old_size + size_delta);
- // Move the code residing between branch placeholders.
- uint32_t end = old_size;
- for (size_t i = branch_count; i > 0; ) {
- Branch& branch = branches_[--i];
- CHECK_GE(end, branch.GetOldEndLocation());
- uint32_t size = end - branch.GetOldEndLocation();
- buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
- end = branch.GetOldLocation();
- }
- }
-}
-
-// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
-const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = {
- // R2 short branches (can be promoted to long).
- { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kUncondBranch
- { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCondBranch
- { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCall
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- { 1, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kBareUncondBranch
- { 1, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kBareCondBranch
- { 1, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kBareCall
- // R2 near label.
- { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLabel
- // R2 near literal.
- { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLiteral
- // R2 long branches.
- { 9, 3, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongUncondBranch
- { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCondBranch
- { 6, 1, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCall
- // R2 far label.
- { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLabel
- // R2 far literal.
- { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLiteral
- // R6 short branches (can be promoted to long).
- { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6UncondBranch
- { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kR6CondBranch
- // Exception: kOffset23 for beqzc/bnezc.
- { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6Call
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6BareUncondBranch
- { 1, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kR6BareCondBranch
- // Exception: kOffset23 for beqzc/bnezc.
- { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6BareCall
- // R6 near label.
- { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Label
- // R6 near literal.
- { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Literal
- // R6 long branches.
- { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongUncondBranch
- { 3, 1, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCondBranch
- { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCall
- // R6 far label.
- { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLabel
- // R6 far literal.
- { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLiteral
-};
-
-static inline bool IsAbsorbableInstruction(uint32_t instruction) {
- // The relative patcher patches addiu, lw and sw with an immediate operand of 0x5678.
- // We want to make sure that these instructions do not get absorbed into delay slots
- // of unconditional branches on R2. Absorption would otherwise make copies of
- // unpatched instructions.
- if ((instruction & 0xFFFF) != 0x5678) {
- return true;
- }
- switch (instruction >> kOpcodeShift) {
- case 0x09: // Addiu.
- case 0x23: // Lw.
- case 0x2B: // Sw.
- return false;
- default:
- return true;
- }
-}
-
-static inline Register GetR2PcRelBaseRegister(Register reg) {
- // LoadLabelAddress() and LoadLiteral() generate individual NAL
- // instructions on R2 when the specified base register is ZERO
- // and so the effective PC-relative base register is RA, not ZERO.
- return (reg == ZERO) ? RA : reg;
-}
-
-// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
-void MipsAssembler::EmitBranch(uint32_t branch_id) {
- CHECK_EQ(overwriting_, true);
- Branch* branch = GetBranch(branch_id);
- overwrite_location_ = branch->GetLocation();
- uint32_t offset = branch->GetOffset(GetBranchOrPcRelBaseForEncoding(branch));
- BranchCondition condition = branch->GetCondition();
- Register lhs = branch->GetLeftRegister();
- Register rhs = branch->GetRightRegister();
- uint32_t delayed_instruction = branch->GetDelayedInstruction();
- MipsLabel* patcher_label = branch->GetPatcherLabel();
- if (patcher_label != nullptr) {
- // Update the patcher label location to account for branch promotion and
- // delay slot filling.
- CHECK(patcher_label->IsBound());
- uint32_t bound_pc = branch->GetLocation();
- if (!branch->IsLong()) {
- // Short branches precede delay slots.
- // Long branches follow "delay slots".
- bound_pc += sizeof(uint32_t);
- }
- // Rebind the label.
- patcher_label->Reinitialize();
- BindRelativeToPrecedingBranch(patcher_label, branch_id, bound_pc);
- }
- switch (branch->GetType()) {
- // R2 short branches.
- case Branch::kUncondBranch:
- if (delayed_instruction == Branch::kUnfillableDelaySlot) {
- // The branch was created when reordering was disabled, do not absorb the target
- // instruction.
- delayed_instruction = 0; // NOP.
- } else if (delayed_instruction == Branch::kUnfilledDelaySlot) {
- // Try to absorb the target instruction into the delay slot.
- delayed_instruction = 0; // NOP.
- // Incrementing the signed 16-bit offset past the target instruction must not
- // cause overflow into the negative subrange, check for the max offset.
- if (offset != 0x7FFF) {
- uint32_t target = branch->GetTarget();
- if (std::binary_search(ds_fsm_target_pcs_.begin(), ds_fsm_target_pcs_.end(), target)) {
- uint32_t target_instruction = buffer_.Load<uint32_t>(target);
- if (IsAbsorbableInstruction(target_instruction)) {
- delayed_instruction = target_instruction;
- offset++;
- }
- }
- }
- }
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- B(offset);
- Emit(delayed_instruction);
- break;
- case Branch::kCondBranch:
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction == Branch::kUnfilledDelaySlot) {
- delayed_instruction = 0; // NOP.
- }
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR2(condition, lhs, rhs, offset);
- Emit(delayed_instruction);
- break;
- case Branch::kCall:
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction == Branch::kUnfilledDelaySlot) {
- delayed_instruction = 0; // NOP.
- }
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bal(offset);
- Emit(delayed_instruction);
- break;
- case Branch::kBareUncondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- B(offset);
- break;
- case Branch::kBareCondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR2(condition, lhs, rhs, offset);
- break;
- case Branch::kBareCall:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bal(offset);
- break;
-
- // R2 near label.
- case Branch::kLabel:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Addiu(lhs, GetR2PcRelBaseRegister(rhs), offset);
- break;
- // R2 near literal.
- case Branch::kLiteral:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lw(lhs, GetR2PcRelBaseRegister(rhs), offset);
- break;
-
- // R2 long branches.
- case Branch::kLongUncondBranch:
- // To get the value of the PC register we need to use the NAL instruction.
- // NAL clobbers the RA register. However, RA must be preserved if the
- // method is compiled without the entry/exit sequences that would take care
- // of preserving RA (typically, leaf methods don't preserve RA explicitly).
- // So, we need to preserve RA in some temporary storage ourselves. The AT
- // register can't be used for this because we need it to load a constant
- // which will be added to the value that NAL stores in RA. And we can't
- // use T9 for this in the context of the JNI compiler, which uses it
- // as a scratch register (see InterproceduralScratchRegister()).
- // If we were to add a 32-bit constant to RA using two ADDIU instructions,
- // we'd also need to use the ROTR instruction, which requires no less than
- // MIPSR2.
- // Perhaps, we could use T8 or one of R2's multiplier/divider registers
- // (LO or HI) or even a floating-point register, but that doesn't seem
- // like a nice solution. We may want this to work on both R6 and pre-R6.
- // For now simply use the stack for RA. This should be OK since for the
- // vast majority of code a short PC-relative branch is sufficient.
- // TODO: can this be improved?
- // TODO: consider generation of a shorter sequence when we know that RA
- // is explicitly preserved by the method entry/exit code.
- if (delayed_instruction != Branch::kUnfilledDelaySlot &&
- delayed_instruction != Branch::kUnfillableDelaySlot) {
- Emit(delayed_instruction);
- }
- Push(RA);
- Nal();
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lui(AT, High16Bits(offset));
- Ori(AT, AT, Low16Bits(offset));
- Addu(AT, AT, RA);
- Lw(RA, SP, 0);
- Jr(AT);
- DecreaseFrameSize(kStackAlignment);
- break;
- case Branch::kLongCondBranch:
- // The comment on case 'Branch::kLongUncondBranch' applies here as well.
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction != Branch::kUnfilledDelaySlot) {
- Emit(delayed_instruction);
- }
- // Note: the opposite condition branch encodes 8 as the distance, which is equal to the
- // number of instructions skipped:
- // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR).
- EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8);
- Push(RA);
- Nal();
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lui(AT, High16Bits(offset));
- Ori(AT, AT, Low16Bits(offset));
- Addu(AT, AT, RA);
- Lw(RA, SP, 0);
- Jr(AT);
- DecreaseFrameSize(kStackAlignment);
- break;
- case Branch::kLongCall:
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction != Branch::kUnfilledDelaySlot) {
- Emit(delayed_instruction);
- }
- Nal();
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lui(AT, High16Bits(offset));
- Ori(AT, AT, Low16Bits(offset));
- Addu(AT, AT, RA);
- Jalr(AT);
- Nop();
- break;
-
- // R2 far label.
- case Branch::kFarLabel:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lui(AT, High16Bits(offset));
- Ori(AT, AT, Low16Bits(offset));
- Addu(lhs, AT, GetR2PcRelBaseRegister(rhs));
- break;
- // R2 far literal.
- case Branch::kFarLiteral:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- offset += (offset & 0x8000) << 1; // Account for sign extension in lw.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lui(AT, High16Bits(offset));
- Addu(AT, AT, GetR2PcRelBaseRegister(rhs));
- Lw(lhs, AT, Low16Bits(offset));
- break;
-
- // R6 short branches.
- case Branch::kR6UncondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bc(offset);
- break;
- case Branch::kR6CondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR6(condition, lhs, rhs, offset);
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction != Branch::kUnfilledDelaySlot) {
- Emit(delayed_instruction);
- } else {
- // TODO: improve by filling the forbidden slot (IFF this is
- // a forbidden and not a delay slot).
- Nop();
- }
- break;
- case Branch::kR6Call:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Balc(offset);
- break;
- case Branch::kR6BareUncondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bc(offset);
- break;
- case Branch::kR6BareCondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR6(condition, lhs, rhs, offset);
- break;
- case Branch::kR6BareCall:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Balc(offset);
- break;
-
- // R6 near label.
- case Branch::kR6Label:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Addiupc(lhs, offset);
- break;
- // R6 near literal.
- case Branch::kR6Literal:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lwpc(lhs, offset);
- break;
-
- // R6 long branches.
- case Branch::kR6LongUncondBranch:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jic(AT, Low16Bits(offset));
- break;
- case Branch::kR6LongCondBranch:
- DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
- if (delayed_instruction != Branch::kUnfilledDelaySlot) {
- Emit(delayed_instruction);
- }
- EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
- offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jic(AT, Low16Bits(offset));
- break;
- case Branch::kR6LongCall:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- offset += (offset & 0x8000) << 1; // Account for sign extension in jialc.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jialc(AT, Low16Bits(offset));
- break;
-
- // R6 far label.
- case Branch::kR6FarLabel:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- offset += (offset & 0x8000) << 1; // Account for sign extension in addiu.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Addiu(lhs, AT, Low16Bits(offset));
- break;
- // R6 far literal.
- case Branch::kR6FarLiteral:
- DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
- offset += (offset & 0x8000) << 1; // Account for sign extension in lw.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Lw(lhs, AT, Low16Bits(offset));
- break;
- }
- CHECK_EQ(overwrite_location_, branch->GetEndLocation());
- CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
- if (patcher_label != nullptr) {
- // The patched instruction should look like one.
- uint32_t patched_instruction = buffer_.Load<uint32_t>(GetLabelLocation(patcher_label));
- CHECK(!IsAbsorbableInstruction(patched_instruction));
- }
-}
-
-void MipsAssembler::B(MipsLabel* label, bool is_bare) {
- Buncond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare);
-}
-
-void MipsAssembler::Bal(MipsLabel* label, bool is_bare) {
- Call(label, /* is_r6= */ (IsR6() && !is_bare), is_bare);
-}
-
-void MipsAssembler::Beq(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondEQ, rs, rt);
-}
-
-void MipsAssembler::Bne(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondNE, rs, rt);
-}
-
-void MipsAssembler::Beqz(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondEQZ, rt);
-}
-
-void MipsAssembler::Bnez(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondNEZ, rt);
-}
-
-void MipsAssembler::Bltz(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondLTZ, rt);
-}
-
-void MipsAssembler::Bgez(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondGEZ, rt);
-}
-
-void MipsAssembler::Blez(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondLEZ, rt);
-}
-
-void MipsAssembler::Bgtz(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ (IsR6() && !is_bare), is_bare, kCondGTZ, rt);
-}
-
-bool MipsAssembler::CanExchangeWithSlt(Register rs, Register rt) const {
- // If the instruction modifies AT, `rs` or `rt`, it can't be exchanged with the slt[u]
- // instruction because either slt[u] depends on `rs` or `rt` or the following
- // conditional branch depends on AT set by slt[u].
- // Likewise, if the instruction depends on AT, it can't be exchanged with slt[u]
- // because slt[u] changes AT.
- return (delay_slot_.instruction_ != 0 &&
- (delay_slot_.masks_.gpr_outs_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 &&
- (delay_slot_.masks_.gpr_ins_ & (1u << AT)) == 0);
-}
-
-void MipsAssembler::ExchangeWithSlt(const DelaySlot& forwarded_slot) {
- // Exchange the last two instructions in the assembler buffer.
- size_t size = buffer_.Size();
- CHECK_GE(size, 2 * sizeof(uint32_t));
- size_t pos1 = size - 2 * sizeof(uint32_t);
- size_t pos2 = size - sizeof(uint32_t);
- uint32_t instr1 = buffer_.Load<uint32_t>(pos1);
- uint32_t instr2 = buffer_.Load<uint32_t>(pos2);
- CHECK_EQ(instr1, forwarded_slot.instruction_);
- CHECK_EQ(instr2, delay_slot_.instruction_);
- buffer_.Store<uint32_t>(pos1, instr2);
- buffer_.Store<uint32_t>(pos2, instr1);
- // Set the current delay slot information to that of the last instruction
- // in the buffer.
- delay_slot_ = forwarded_slot;
-}
-
-void MipsAssembler::GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt) {
- // If possible, exchange the slt[u] instruction with the preceding instruction,
- // so it can fill the delay slot.
- DelaySlot forwarded_slot = delay_slot_;
- bool exchange = CanExchangeWithSlt(rs, rt);
- if (exchange) {
- // The last instruction cannot be used in a different delay slot,
- // do not commit the label before it (if any).
- DsFsmDropLabel();
- }
- if (unsigned_slt) {
- Sltu(AT, rs, rt);
- } else {
- Slt(AT, rs, rt);
- }
- if (exchange) {
- ExchangeWithSlt(forwarded_slot);
- }
-}
-
-void MipsAssembler::Blt(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- if (IsR6() && !is_bare) {
- Bcond(label, IsR6(), is_bare, kCondLT, rs, rt);
- } else if (!Branch::IsNop(kCondLT, rs, rt)) {
- // Synthesize the instruction (not available on R2).
- GenerateSltForCondBranch(/* unsigned_slt= */ false, rs, rt);
- Bnez(AT, label, is_bare);
- }
-}
-
-void MipsAssembler::Bge(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- if (IsR6() && !is_bare) {
- Bcond(label, IsR6(), is_bare, kCondGE, rs, rt);
- } else if (Branch::IsUncond(kCondGE, rs, rt)) {
- B(label, is_bare);
- } else {
- // Synthesize the instruction (not available on R2).
- GenerateSltForCondBranch(/* unsigned_slt= */ false, rs, rt);
- Beqz(AT, label, is_bare);
- }
-}
-
-void MipsAssembler::Bltu(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- if (IsR6() && !is_bare) {
- Bcond(label, IsR6(), is_bare, kCondLTU, rs, rt);
- } else if (!Branch::IsNop(kCondLTU, rs, rt)) {
- // Synthesize the instruction (not available on R2).
- GenerateSltForCondBranch(/* unsigned_slt= */ true, rs, rt);
- Bnez(AT, label, is_bare);
- }
-}
-
-void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- if (IsR6() && !is_bare) {
- Bcond(label, IsR6(), is_bare, kCondGEU, rs, rt);
- } else if (Branch::IsUncond(kCondGEU, rs, rt)) {
- B(label, is_bare);
- } else {
- // Synthesize the instruction (not available on R2).
- GenerateSltForCondBranch(/* unsigned_slt= */ true, rs, rt);
- Beqz(AT, label, is_bare);
- }
-}
-
-void MipsAssembler::Bc1f(MipsLabel* label, bool is_bare) {
- Bc1f(0, label, is_bare);
-}
-
-void MipsAssembler::Bc1f(int cc, MipsLabel* label, bool is_bare) {
- CHECK(IsUint<3>(cc)) << cc;
- Bcond(label, /* is_r6= */ false, is_bare, kCondF, static_cast<Register>(cc), ZERO);
-}
-
-void MipsAssembler::Bc1t(MipsLabel* label, bool is_bare) {
- Bc1t(0, label, is_bare);
-}
-
-void MipsAssembler::Bc1t(int cc, MipsLabel* label, bool is_bare) {
- CHECK(IsUint<3>(cc)) << cc;
- Bcond(label, /* is_r6= */ false, is_bare, kCondT, static_cast<Register>(cc), ZERO);
-}
-
-void MipsAssembler::Bc(MipsLabel* label, bool is_bare) {
- Buncond(label, /* is_r6= */ true, is_bare);
-}
-
-void MipsAssembler::Balc(MipsLabel* label, bool is_bare) {
- Call(label, /* is_r6= */ true, is_bare);
-}
-
-void MipsAssembler::Beqc(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondEQ, rs, rt);
-}
-
-void MipsAssembler::Bnec(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondNE, rs, rt);
-}
-
-void MipsAssembler::Beqzc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondEQZ, rt);
-}
-
-void MipsAssembler::Bnezc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondNEZ, rt);
-}
-
-void MipsAssembler::Bltzc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLTZ, rt);
-}
-
-void MipsAssembler::Bgezc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGEZ, rt);
-}
-
-void MipsAssembler::Blezc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLEZ, rt);
-}
-
-void MipsAssembler::Bgtzc(Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGTZ, rt);
-}
-
-void MipsAssembler::Bltc(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLT, rs, rt);
-}
-
-void MipsAssembler::Bgec(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGE, rs, rt);
-}
-
-void MipsAssembler::Bltuc(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLTU, rs, rt);
-}
-
-void MipsAssembler::Bgeuc(Register rs, Register rt, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGEU, rs, rt);
-}
-
-void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondF, static_cast<Register>(ft), ZERO);
-}
-
-void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondT, static_cast<Register>(ft), ZERO);
-}
-
-void MipsAssembler::AdjustBaseAndOffset(Register& base,
- int32_t& offset,
- bool is_doubleword,
- bool is_float) {
- // This method is used to adjust the base register and offset pair
- // for a load/store when the offset doesn't fit into int16_t.
- // It is assumed that `base + offset` is sufficiently aligned for memory
- // operands that are machine word in size or smaller. For doubleword-sized
- // operands it's assumed that `base` is a multiple of 8, while `offset`
- // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
- // and spilled variables on the stack accessed relative to the stack
- // pointer register).
- // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
- CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
-
- bool doubleword_aligned = IsAligned<kMipsDoublewordSize>(offset);
- bool two_accesses = is_doubleword && (!is_float || !doubleword_aligned);
-
- // IsInt<16> must be passed a signed value, hence the static cast below.
- if (IsInt<16>(offset) &&
- (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
- // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
- return;
- }
-
- // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
- uint32_t misalignment = offset & (kMipsDoublewordSize - 1);
-
- // Do not load the whole 32-bit `offset` if it can be represented as
- // a sum of two 16-bit signed offsets. This can save an instruction or two.
- // To simplify matters, only do this for a symmetric range of offsets from
- // about -64KB to about +64KB, allowing further addition of 4 when accessing
- // 64-bit variables with two 32-bit accesses.
- constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8.
- constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
- if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
- Addiu(AT, base, kMinOffsetForSimpleAdjustment);
- offset -= kMinOffsetForSimpleAdjustment;
- } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
- Addiu(AT, base, -kMinOffsetForSimpleAdjustment);
- offset += kMinOffsetForSimpleAdjustment;
- } else if (IsR6()) {
- // On R6 take advantage of the aui instruction, e.g.:
- // aui AT, base, offset_high
- // lw reg_lo, offset_low(AT)
- // lw reg_hi, (offset_low+4)(AT)
- // or when offset_low+4 overflows int16_t:
- // aui AT, base, offset_high
- // addiu AT, AT, 8
- // lw reg_lo, (offset_low-8)(AT)
- // lw reg_hi, (offset_low-4)(AT)
- int16_t offset_high = High16Bits(offset);
- int16_t offset_low = Low16Bits(offset);
- offset_high += (offset_low < 0) ? 1 : 0; // Account for offset sign extension in load/store.
- Aui(AT, base, offset_high);
- if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low + kMipsWordSize))) {
- // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
- Addiu(AT, AT, kMipsDoublewordSize);
- offset_low -= kMipsDoublewordSize;
- }
- offset = offset_low;
- } else {
- // Do not load the whole 32-bit `offset` if it can be represented as
- // a sum of three 16-bit signed offsets. This can save an instruction.
- // To simplify matters, only do this for a symmetric range of offsets from
- // about -96KB to about +96KB, allowing further addition of 4 when accessing
- // 64-bit variables with two 32-bit accesses.
- constexpr int32_t kMinOffsetForMediumAdjustment = 2 * kMinOffsetForSimpleAdjustment;
- constexpr int32_t kMaxOffsetForMediumAdjustment = 3 * kMinOffsetForSimpleAdjustment;
- if (0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
- Addiu(AT, base, kMinOffsetForMediumAdjustment / 2);
- Addiu(AT, AT, kMinOffsetForMediumAdjustment / 2);
- offset -= kMinOffsetForMediumAdjustment;
- } else if (-kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
- Addiu(AT, base, -kMinOffsetForMediumAdjustment / 2);
- Addiu(AT, AT, -kMinOffsetForMediumAdjustment / 2);
- offset += kMinOffsetForMediumAdjustment;
- } else {
- // Now that all shorter options have been exhausted, load the full 32-bit offset.
- int32_t loaded_offset = RoundDown(offset, kMipsDoublewordSize);
- LoadConst32(AT, loaded_offset);
- Addu(AT, AT, base);
- offset -= loaded_offset;
- }
- }
- base = AT;
-
- CHECK(IsInt<16>(offset));
- if (two_accesses) {
- CHECK(IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)));
- }
- CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1));
-}
-
-void MipsAssembler::AdjustBaseOffsetAndElementSizeShift(Register& base,
- int32_t& offset,
- int& element_size_shift) {
- // This method is used to adjust the base register, offset and element_size_shift
- // for a vector load/store when the offset doesn't fit into allowed number of bits.
- // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
- // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
- // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
- // If element_size_shift is non-negative at entry, it won't be changed, but offset
- // will be checked for appropriate alignment. If negative at entry, it will be
- // adjusted based on offset for maximum fit.
- // It's assumed that `base` is a multiple of 8.
- CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
-
- if (element_size_shift >= 0) {
- CHECK_LE(element_size_shift, TIMES_8);
- CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
- } else if (IsAligned<kMipsDoublewordSize>(offset)) {
- element_size_shift = TIMES_8;
- } else if (IsAligned<kMipsWordSize>(offset)) {
- element_size_shift = TIMES_4;
- } else if (IsAligned<kMipsHalfwordSize>(offset)) {
- element_size_shift = TIMES_2;
- } else {
- element_size_shift = TIMES_1;
- }
-
- const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df
- // will take.
- int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits.
- low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits.
- if (low == offset) {
- return; // `offset` fits into ld.df/st.df.
- }
-
- // First, see if `offset` can be represented as a sum of two or three signed offsets.
- // This can save an instruction or two.
-
- // Max int16_t that's a multiple of element size.
- const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
- // Max ld.df/st.df offset that's a multiple of element size.
- const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
- const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
- const int32_t kMinOffsetForMediumAdjustment = 2 * kMaxDeltaForSimpleAdjustment;
- const int32_t kMaxOffsetForMediumAdjustment = kMinOffsetForMediumAdjustment + kMaxLoadStoreOffset;
-
- if (IsInt<16>(offset)) {
- Addiu(AT, base, offset);
- offset = 0;
- } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
- Addiu(AT, base, kMaxDeltaForSimpleAdjustment);
- offset -= kMaxDeltaForSimpleAdjustment;
- } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
- Addiu(AT, base, -kMaxDeltaForSimpleAdjustment);
- offset += kMaxDeltaForSimpleAdjustment;
- } else if (!IsR6() && 0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
- Addiu(AT, base, kMaxDeltaForSimpleAdjustment);
- if (offset <= kMinOffsetForMediumAdjustment) {
- Addiu(AT, AT, offset - kMaxDeltaForSimpleAdjustment);
- offset = 0;
- } else {
- Addiu(AT, AT, kMaxDeltaForSimpleAdjustment);
- offset -= kMinOffsetForMediumAdjustment;
- }
- } else if (!IsR6() && -kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
- Addiu(AT, base, -kMaxDeltaForSimpleAdjustment);
- if (-kMinOffsetForMediumAdjustment <= offset) {
- Addiu(AT, AT, offset + kMaxDeltaForSimpleAdjustment);
- offset = 0;
- } else {
- Addiu(AT, AT, -kMaxDeltaForSimpleAdjustment);
- offset += kMinOffsetForMediumAdjustment;
- }
- } else {
- // 16-bit or smaller parts of `offset`:
- // |31 hi 16|15 mid 13-10|12-9 low 0|
- //
- // Instructions that supply each part as a signed integer addend:
- // |aui |addiu |ld.df/st.df |
- uint32_t tmp = static_cast<uint32_t>(offset) - low; // Exclude `low` from the rest of `offset`
- // (accounts for sign of `low`).
- tmp += (tmp & (UINT32_C(1) << 15)) << 1; // Account for sign extension in addiu.
- int16_t mid = Low16Bits(tmp);
- int16_t hi = High16Bits(tmp);
- if (IsR6()) {
- Aui(AT, base, hi);
- } else {
- Lui(AT, hi);
- Addu(AT, AT, base);
- }
- if (mid != 0) {
- Addiu(AT, AT, mid);
- }
- offset = low;
- }
- base = AT;
- CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
- CHECK(IsInt<10>(offset >> element_size_shift));
-}
-
-void MipsAssembler::LoadFromOffset(LoadOperandType type,
- Register reg,
- Register base,
- int32_t offset) {
- LoadFromOffset<>(type, reg, base, offset);
-}
-
-void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
- LoadSFromOffset<>(reg, base, offset);
-}
-
-void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) {
- LoadDFromOffset<>(reg, base, offset);
-}
-
-void MipsAssembler::LoadQFromOffset(FRegister reg, Register base, int32_t offset) {
- LoadQFromOffset<>(reg, base, offset);
-}
-
-void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
- size_t size) {
- MipsManagedRegister dst = m_dst.AsMips();
- if (dst.IsNoRegister()) {
- CHECK_EQ(0u, size) << dst;
- } else if (dst.IsCoreRegister()) {
- CHECK_EQ(kMipsWordSize, size) << dst;
- LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
- } else if (dst.IsRegisterPair()) {
- CHECK_EQ(kMipsDoublewordSize, size) << dst;
- LoadFromOffset(kLoadDoubleword, dst.AsRegisterPairLow(), src_register, src_offset);
- } else if (dst.IsFRegister()) {
- if (size == kMipsWordSize) {
- LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
- } else {
- CHECK_EQ(kMipsDoublewordSize, size) << dst;
- LoadDFromOffset(dst.AsFRegister(), src_register, src_offset);
- }
- } else if (dst.IsDRegister()) {
- CHECK_EQ(kMipsDoublewordSize, size) << dst;
- LoadDFromOffset(dst.AsOverlappingDRegisterLow(), src_register, src_offset);
- }
-}
-
-void MipsAssembler::StoreToOffset(StoreOperandType type,
- Register reg,
- Register base,
- int32_t offset) {
- StoreToOffset<>(type, reg, base, offset);
-}
-
-void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
- StoreSToOffset<>(reg, base, offset);
-}
-
-void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) {
- StoreDToOffset<>(reg, base, offset);
-}
-
-void MipsAssembler::StoreQToOffset(FRegister reg, Register base, int32_t offset) {
- StoreQToOffset<>(reg, base, offset);
-}
-
-static dwarf::Reg DWARFReg(Register reg) {
- return dwarf::Reg::MipsCore(static_cast<int>(reg));
-}
-
-constexpr size_t kFramePointerSize = 4;
-
-void MipsAssembler::BuildFrame(size_t frame_size,
- ManagedRegister method_reg,
- ArrayRef<const ManagedRegister> callee_save_regs,
- const ManagedRegisterEntrySpills& entry_spills) {
- CHECK_ALIGNED(frame_size, kStackAlignment);
- DCHECK(!overwriting_);
-
- // Increase frame to required size.
- IncreaseFrameSize(frame_size);
-
- // Push callee saves and return address.
- int stack_offset = frame_size - kFramePointerSize;
- StoreToOffset(kStoreWord, RA, SP, stack_offset);
- cfi_.RelOffset(DWARFReg(RA), stack_offset);
- for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
- stack_offset -= kFramePointerSize;
- Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
- StoreToOffset(kStoreWord, reg, SP, stack_offset);
- cfi_.RelOffset(DWARFReg(reg), stack_offset);
- }
-
- // Write out Method*.
- StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
-
- // Write out entry spills.
- int32_t offset = frame_size + kFramePointerSize;
- for (const ManagedRegisterSpill& spill : entry_spills) {
- MipsManagedRegister reg = spill.AsMips();
- if (reg.IsNoRegister()) {
- offset += spill.getSize();
- } else if (reg.IsCoreRegister()) {
- StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset);
- offset += kMipsWordSize;
- } else if (reg.IsFRegister()) {
- StoreSToOffset(reg.AsFRegister(), SP, offset);
- offset += kMipsWordSize;
- } else if (reg.IsDRegister()) {
- StoreDToOffset(reg.AsOverlappingDRegisterLow(), SP, offset);
- offset += kMipsDoublewordSize;
- }
- }
-}
-
-void MipsAssembler::RemoveFrame(size_t frame_size,
- ArrayRef<const ManagedRegister> callee_save_regs,
- bool may_suspend ATTRIBUTE_UNUSED) {
- CHECK_ALIGNED(frame_size, kStackAlignment);
- DCHECK(!overwriting_);
- cfi_.RememberState();
-
- // Pop callee saves and return address.
- int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
- for (size_t i = 0; i < callee_save_regs.size(); ++i) {
- Register reg = callee_save_regs[i].AsMips().AsCoreRegister();
- LoadFromOffset(kLoadWord, reg, SP, stack_offset);
- cfi_.Restore(DWARFReg(reg));
- stack_offset += kFramePointerSize;
- }
- LoadFromOffset(kLoadWord, RA, SP, stack_offset);
- cfi_.Restore(DWARFReg(RA));
-
- // Adjust the stack pointer in the delay slot if doing so doesn't break CFI.
- bool exchange = IsInt<16>(static_cast<int32_t>(frame_size));
- bool reordering = SetReorder(false);
- if (exchange) {
- // Jump to the return address.
- Jr(RA);
- // Decrease frame to required size.
- DecreaseFrameSize(frame_size); // Single instruction in delay slot.
- } else {
- // Decrease frame to required size.
- DecreaseFrameSize(frame_size);
- // Jump to the return address.
- Jr(RA);
- Nop(); // In delay slot.
- }
- SetReorder(reordering);
-
- // The CFI should be restored for any code that follows the exit block.
- cfi_.RestoreState();
- cfi_.DefCFAOffset(frame_size);
-}
-
-void MipsAssembler::IncreaseFrameSize(size_t adjust) {
- CHECK_ALIGNED(adjust, kFramePointerSize);
- Addiu32(SP, SP, -adjust);
- cfi_.AdjustCFAOffset(adjust);
- if (overwriting_) {
- cfi_.OverrideDelayedPC(overwrite_location_);
- }
-}
-
-void MipsAssembler::DecreaseFrameSize(size_t adjust) {
- CHECK_ALIGNED(adjust, kFramePointerSize);
- Addiu32(SP, SP, adjust);
- cfi_.AdjustCFAOffset(-adjust);
- if (overwriting_) {
- cfi_.OverrideDelayedPC(overwrite_location_);
- }
-}
-
-void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
- MipsManagedRegister src = msrc.AsMips();
- if (src.IsNoRegister()) {
- CHECK_EQ(0u, size);
- } else if (src.IsCoreRegister()) {
- CHECK_EQ(kMipsWordSize, size);
- StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
- } else if (src.IsRegisterPair()) {
- CHECK_EQ(kMipsDoublewordSize, size);
- StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
- StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
- SP, dest.Int32Value() + kMipsWordSize);
- } else if (src.IsFRegister()) {
- if (size == kMipsWordSize) {
- StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value());
- } else {
- CHECK_EQ(kMipsDoublewordSize, size);
- StoreDToOffset(src.AsFRegister(), SP, dest.Int32Value());
- }
- } else if (src.IsDRegister()) {
- CHECK_EQ(kMipsDoublewordSize, size);
- StoreDToOffset(src.AsOverlappingDRegisterLow(), SP, dest.Int32Value());
- }
-}
-
-void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
- MipsManagedRegister src = msrc.AsMips();
- CHECK(src.IsCoreRegister());
- StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
-}
-
-void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
- MipsManagedRegister src = msrc.AsMips();
- CHECK(src.IsCoreRegister());
- StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
-}
-
-void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
- ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadConst32(scratch.AsCoreRegister(), imm);
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
-}
-
-void MipsAssembler::StoreStackOffsetToThread(ThreadOffset32 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- Addiu32(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
- S1, thr_offs.Int32Value());
-}
-
-void MipsAssembler::StoreStackPointerToThread(ThreadOffset32 thr_offs) {
- StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
-}
-
-void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
- FrameOffset in_off, ManagedRegister mscratch) {
- MipsManagedRegister src = msrc.AsMips();
- MipsManagedRegister scratch = mscratch.AsMips();
- StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
-}
-
-void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
- return EmitLoad(mdest, SP, src.Int32Value(), size);
-}
-
-void MipsAssembler::LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) {
- return EmitLoad(mdest, S1, src.Int32Value(), size);
-}
-
-void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
- MipsManagedRegister dest = mdest.AsMips();
- CHECK(dest.IsCoreRegister());
- LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
-}
-
-void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
- bool unpoison_reference) {
- MipsManagedRegister dest = mdest.AsMips();
- CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
- LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
- base.AsMips().AsCoreRegister(), offs.Int32Value());
- if (unpoison_reference) {
- MaybeUnpoisonHeapReference(dest.AsCoreRegister());
- }
-}
-
-void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) {
- MipsManagedRegister dest = mdest.AsMips();
- CHECK(dest.IsCoreRegister() && base.AsMips().IsCoreRegister());
- LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
- base.AsMips().AsCoreRegister(), offs.Int32Value());
-}
-
-void MipsAssembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) {
- MipsManagedRegister dest = mdest.AsMips();
- CHECK(dest.IsCoreRegister());
- LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
-}
-
-void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
- UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
-}
-
-void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
- UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
-}
-
-void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
- MipsManagedRegister dest = mdest.AsMips();
- MipsManagedRegister src = msrc.AsMips();
- if (!dest.Equals(src)) {
- if (dest.IsCoreRegister()) {
- CHECK(src.IsCoreRegister()) << src;
- Move(dest.AsCoreRegister(), src.AsCoreRegister());
- } else if (dest.IsFRegister()) {
- CHECK(src.IsFRegister()) << src;
- if (size == kMipsWordSize) {
- MovS(dest.AsFRegister(), src.AsFRegister());
- } else {
- CHECK_EQ(kMipsDoublewordSize, size);
- MovD(dest.AsFRegister(), src.AsFRegister());
- }
- } else if (dest.IsDRegister()) {
- CHECK(src.IsDRegister()) << src;
- MovD(dest.AsOverlappingDRegisterLow(), src.AsOverlappingDRegisterLow());
- } else {
- CHECK(dest.IsRegisterPair()) << dest;
- CHECK(src.IsRegisterPair()) << src;
- // Ensure that the first move doesn't clobber the input of the second.
- if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
- Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
- Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
- } else {
- Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
- Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
- }
- }
- }
-}
-
-void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
-}
-
-void MipsAssembler::CopyRawPtrFromThread(FrameOffset fr_offs,
- ThreadOffset32 thr_offs,
- ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- S1, thr_offs.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
- SP, fr_offs.Int32Value());
-}
-
-void MipsAssembler::CopyRawPtrToThread(ThreadOffset32 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- SP, fr_offs.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
- S1, thr_offs.Int32Value());
-}
-
-void MipsAssembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- CHECK(size == kMipsWordSize || size == kMipsDoublewordSize) << size;
- if (size == kMipsWordSize) {
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
- } else if (size == kMipsDoublewordSize) {
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + kMipsWordSize);
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + kMipsWordSize);
- }
-}
-
-void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
- ManagedRegister mscratch, size_t size) {
- Register scratch = mscratch.AsMips().AsCoreRegister();
- CHECK_EQ(size, kMipsWordSize);
- LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
- StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
-}
-
-void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
- ManagedRegister mscratch, size_t size) {
- Register scratch = mscratch.AsMips().AsCoreRegister();
- CHECK_EQ(size, kMipsWordSize);
- LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
- StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
-}
-
-void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
- FrameOffset src_base ATTRIBUTE_UNUSED,
- Offset src_offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "no MIPS implementation";
-}
-
-void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
- ManagedRegister src, Offset src_offset,
- ManagedRegister mscratch, size_t size) {
- CHECK_EQ(size, kMipsWordSize);
- Register scratch = mscratch.AsMips().AsCoreRegister();
- LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
- StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
-}
-
-void MipsAssembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
- Offset dest_offset ATTRIBUTE_UNUSED,
- FrameOffset src ATTRIBUTE_UNUSED,
- Offset src_offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "no MIPS implementation";
-}
-
-void MipsAssembler::MemoryBarrier(ManagedRegister) {
- // TODO: sync?
- UNIMPLEMENTED(FATAL) << "no MIPS implementation";
-}
-
-void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
- FrameOffset handle_scope_offset,
- ManagedRegister min_reg,
- bool null_allowed) {
- MipsManagedRegister out_reg = mout_reg.AsMips();
- MipsManagedRegister in_reg = min_reg.AsMips();
- CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
- CHECK(out_reg.IsCoreRegister()) << out_reg;
- if (null_allowed) {
- MipsLabel null_arg;
- // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
- // the address in the handle scope holding the reference.
- // E.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset).
- if (in_reg.IsNoRegister()) {
- LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
- SP, handle_scope_offset.Int32Value());
- in_reg = out_reg;
- }
- if (!out_reg.Equals(in_reg)) {
- LoadConst32(out_reg.AsCoreRegister(), 0);
- }
- Beqz(in_reg.AsCoreRegister(), &null_arg);
- Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
- Bind(&null_arg);
- } else {
- Addiu32(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
- }
-}
-
-void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
- FrameOffset handle_scope_offset,
- ManagedRegister mscratch,
- bool null_allowed) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- if (null_allowed) {
- MipsLabel null_arg;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
- // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
- // the address in the handle scope holding the reference.
- // E.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset).
- Beqz(scratch.AsCoreRegister(), &null_arg);
- Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
- Bind(&null_arg);
- } else {
- Addiu32(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
- }
- StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
-}
-
-// Given a handle scope entry, load the associated reference.
-void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
- ManagedRegister min_reg) {
- MipsManagedRegister out_reg = mout_reg.AsMips();
- MipsManagedRegister in_reg = min_reg.AsMips();
- CHECK(out_reg.IsCoreRegister()) << out_reg;
- CHECK(in_reg.IsCoreRegister()) << in_reg;
- MipsLabel null_arg;
- if (!out_reg.Equals(in_reg)) {
- LoadConst32(out_reg.AsCoreRegister(), 0);
- }
- Beqz(in_reg.AsCoreRegister(), &null_arg);
- LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
- in_reg.AsCoreRegister(), 0);
- Bind(&null_arg);
-}
-
-void MipsAssembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
- bool could_be_null ATTRIBUTE_UNUSED) {
- // TODO: not validating references.
-}
-
-void MipsAssembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
- bool could_be_null ATTRIBUTE_UNUSED) {
- // TODO: not validating references.
-}
-
-void MipsAssembler::Jump(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
- MipsManagedRegister base = mbase.AsMips();
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(base.IsCoreRegister()) << base;
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- base.AsCoreRegister(), offset.Int32Value());
- Jr(scratch.AsCoreRegister());
- NopIfNoReordering();
-}
-
-void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
- MipsManagedRegister base = mbase.AsMips();
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(base.IsCoreRegister()) << base;
- CHECK(scratch.IsCoreRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- base.AsCoreRegister(), offset.Int32Value());
- Jalr(scratch.AsCoreRegister());
- NopIfNoReordering();
- // TODO: place reference map on call.
-}
-
-void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
- MipsManagedRegister scratch = mscratch.AsMips();
- CHECK(scratch.IsCoreRegister()) << scratch;
- // Call *(*(SP + base) + offset)
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, base.Int32Value());
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- scratch.AsCoreRegister(), offset.Int32Value());
- Jalr(scratch.AsCoreRegister());
- NopIfNoReordering();
- // TODO: place reference map on call.
-}
-
-void MipsAssembler::CallFromThread(ThreadOffset32 offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "no mips implementation";
-}
-
-void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
- Move(tr.AsMips().AsCoreRegister(), S1);
-}
-
-void MipsAssembler::GetCurrentThread(FrameOffset offset,
- ManagedRegister mscratch ATTRIBUTE_UNUSED) {
- StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
-}
-
-void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
- MipsManagedRegister scratch = mscratch.AsMips();
- exception_blocks_.emplace_back(scratch, stack_adjust);
- LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
- S1, Thread::ExceptionOffset<kMipsPointerSize>().Int32Value());
- Bnez(scratch.AsCoreRegister(), exception_blocks_.back().Entry());
-}
-
-void MipsAssembler::EmitExceptionPoll(MipsExceptionSlowPath* exception) {
- Bind(exception->Entry());
- if (exception->stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSize(exception->stack_adjust_);
- }
- // Pass exception object as argument.
- // Don't care about preserving A0 as this call won't return.
- CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
- Move(A0, exception->scratch_.AsCoreRegister());
- // Set up call to Thread::Current()->pDeliverException.
- LoadFromOffset(kLoadWord, T9, S1,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pDeliverException).Int32Value());
- Jr(T9);
- NopIfNoReordering();
-
- // Call never returns.
- Break();
-}
-
-} // namespace mips
-} // namespace art
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
deleted file mode 100644
index 3a4e0ce..0000000
--- a/compiler/utils/mips/assembler_mips.h
+++ /dev/null
@@ -1,1829 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
-#define ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
-
-#include <deque>
-#include <utility>
-#include <vector>
-
-#include "arch/mips/instruction_set_features_mips.h"
-#include "base/arena_containers.h"
-#include "base/enums.h"
-#include "base/globals.h"
-#include "base/macros.h"
-#include "base/stl_util_identity.h"
-#include "constants_mips.h"
-#include "heap_poisoning.h"
-#include "managed_register_mips.h"
-#include "offsets.h"
-#include "utils/assembler.h"
-#include "utils/jni_macro_assembler.h"
-#include "utils/label.h"
-
-namespace art {
-namespace mips {
-
-static constexpr size_t kMipsHalfwordSize = 2;
-static constexpr size_t kMipsWordSize = 4;
-static constexpr size_t kMipsDoublewordSize = 8;
-
-enum LoadOperandType {
- kLoadSignedByte,
- kLoadUnsignedByte,
- kLoadSignedHalfword,
- kLoadUnsignedHalfword,
- kLoadWord,
- kLoadDoubleword,
- kLoadQuadword
-};
-
-enum StoreOperandType {
- kStoreByte,
- kStoreHalfword,
- kStoreWord,
- kStoreDoubleword,
- kStoreQuadword
-};
-
-// Used to test the values returned by ClassS/ClassD.
-enum FPClassMaskType {
- kSignalingNaN = 0x001,
- kQuietNaN = 0x002,
- kNegativeInfinity = 0x004,
- kNegativeNormal = 0x008,
- kNegativeSubnormal = 0x010,
- kNegativeZero = 0x020,
- kPositiveInfinity = 0x040,
- kPositiveNormal = 0x080,
- kPositiveSubnormal = 0x100,
- kPositiveZero = 0x200,
-};
-
-// Instruction description in terms of input and output registers.
-// Used for instruction reordering.
-struct InOutRegMasks {
- InOutRegMasks()
- : gpr_outs_(0), gpr_ins_(0), fpr_outs_(0), fpr_ins_(0), cc_outs_(0), cc_ins_(0) {}
-
- inline InOutRegMasks& GprOuts(Register reg) {
- gpr_outs_ |= (1u << reg);
- gpr_outs_ &= ~1u; // Ignore register ZERO.
- return *this;
- }
- template<typename T, typename... Ts>
- inline InOutRegMasks& GprOuts(T one, Ts... more) { GprOuts(one); GprOuts(more...); return *this; }
-
- inline InOutRegMasks& GprIns(Register reg) {
- gpr_ins_ |= (1u << reg);
- gpr_ins_ &= ~1u; // Ignore register ZERO.
- return *this;
- }
- template<typename T, typename... Ts>
- inline InOutRegMasks& GprIns(T one, Ts... more) { GprIns(one); GprIns(more...); return *this; }
-
- inline InOutRegMasks& GprInOuts(Register reg) { GprIns(reg); GprOuts(reg); return *this; }
- template<typename T, typename... Ts>
- inline InOutRegMasks& GprInOuts(T one, Ts... more) {
- GprInOuts(one);
- GprInOuts(more...);
- return *this;
- }
-
- inline InOutRegMasks& FprOuts(FRegister reg) { fpr_outs_ |= (1u << reg); return *this; }
- inline InOutRegMasks& FprOuts(VectorRegister reg) { return FprOuts(static_cast<FRegister>(reg)); }
- template<typename T, typename... Ts>
- inline InOutRegMasks& FprOuts(T one, Ts... more) { FprOuts(one); FprOuts(more...); return *this; }
-
- inline InOutRegMasks& FprIns(FRegister reg) { fpr_ins_ |= (1u << reg); return *this; }
- inline InOutRegMasks& FprIns(VectorRegister reg) { return FprIns(static_cast<FRegister>(reg)); }
- template<typename T, typename... Ts>
- inline InOutRegMasks& FprIns(T one, Ts... more) { FprIns(one); FprIns(more...); return *this; }
-
- inline InOutRegMasks& FprInOuts(FRegister reg) { FprIns(reg); FprOuts(reg); return *this; }
- inline InOutRegMasks& FprInOuts(VectorRegister reg) {
- return FprInOuts(static_cast<FRegister>(reg));
- }
- template<typename T, typename... Ts>
- inline InOutRegMasks& FprInOuts(T one, Ts... more) {
- FprInOuts(one);
- FprInOuts(more...);
- return *this;
- }
-
- inline InOutRegMasks& CcOuts(int cc) { cc_outs_ |= (1u << cc); return *this; }
- template<typename T, typename... Ts>
- inline InOutRegMasks& CcOuts(T one, Ts... more) { CcOuts(one); CcOuts(more...); return *this; }
-
- inline InOutRegMasks& CcIns(int cc) { cc_ins_ |= (1u << cc); return *this; }
- template<typename T, typename... Ts>
- inline InOutRegMasks& CcIns(T one, Ts... more) { CcIns(one); CcIns(more...); return *this; }
-
- // Mask of output GPRs for the instruction.
- uint32_t gpr_outs_;
- // Mask of input GPRs for the instruction.
- uint32_t gpr_ins_;
- // Mask of output FPRs for the instruction.
- uint32_t fpr_outs_;
- // Mask of input FPRs for the instruction.
- uint32_t fpr_ins_;
- // Mask of output FPU condition code flags for the instruction.
- uint32_t cc_outs_;
- // Mask of input FPU condition code flags for the instruction.
- uint32_t cc_ins_;
-
- // TODO: add LO and HI.
-};
-
-class MipsLabel : public Label {
- public:
- MipsLabel() : prev_branch_id_plus_one_(0) {}
-
- MipsLabel(MipsLabel&& src)
- : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {}
-
- void AdjustBoundPosition(int delta) {
- CHECK(IsBound());
- // Bound label's position is negative, hence decrementing it.
- position_ -= delta;
- }
-
- private:
- uint32_t prev_branch_id_plus_one_; // To get distance from preceding branch, if any.
-
- friend class MipsAssembler;
- DISALLOW_COPY_AND_ASSIGN(MipsLabel);
-};
-
-// Assembler literal is a value embedded in code, retrieved using a PC-relative load.
-class Literal {
- public:
- static constexpr size_t kMaxSize = 8;
-
- Literal(uint32_t size, const uint8_t* data)
- : label_(), size_(size) {
- DCHECK_LE(size, Literal::kMaxSize);
- memcpy(data_, data, size);
- }
-
- template <typename T>
- T GetValue() const {
- DCHECK_EQ(size_, sizeof(T));
- T value;
- memcpy(&value, data_, sizeof(T));
- return value;
- }
-
- uint32_t GetSize() const {
- return size_;
- }
-
- const uint8_t* GetData() const {
- return data_;
- }
-
- MipsLabel* GetLabel() {
- return &label_;
- }
-
- const MipsLabel* GetLabel() const {
- return &label_;
- }
-
- private:
- MipsLabel label_;
- const uint32_t size_;
- uint8_t data_[kMaxSize];
-
- DISALLOW_COPY_AND_ASSIGN(Literal);
-};
-
-// Jump table: table of labels emitted after the literals. Similar to literals.
-class JumpTable {
- public:
- explicit JumpTable(std::vector<MipsLabel*>&& labels)
- : label_(), labels_(std::move(labels)) {
- }
-
- uint32_t GetSize() const {
- return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t);
- }
-
- const std::vector<MipsLabel*>& GetData() const {
- return labels_;
- }
-
- MipsLabel* GetLabel() {
- return &label_;
- }
-
- const MipsLabel* GetLabel() const {
- return &label_;
- }
-
- private:
- MipsLabel label_;
- std::vector<MipsLabel*> labels_;
-
- DISALLOW_COPY_AND_ASSIGN(JumpTable);
-};
-
-// Slowpath entered when Thread::Current()->_exception is non-null.
-class MipsExceptionSlowPath {
- public:
- explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
- : scratch_(scratch), stack_adjust_(stack_adjust) {}
-
- MipsExceptionSlowPath(MipsExceptionSlowPath&& src)
- : scratch_(src.scratch_),
- stack_adjust_(src.stack_adjust_),
- exception_entry_(std::move(src.exception_entry_)) {}
-
- private:
- MipsLabel* Entry() { return &exception_entry_; }
- const MipsManagedRegister scratch_;
- const size_t stack_adjust_;
- MipsLabel exception_entry_;
-
- friend class MipsAssembler;
- DISALLOW_COPY_AND_ASSIGN(MipsExceptionSlowPath);
-};
-
-class MipsAssembler final : public Assembler, public JNIMacroAssembler<PointerSize::k32> {
- public:
- using JNIBase = JNIMacroAssembler<PointerSize::k32>;
-
- explicit MipsAssembler(ArenaAllocator* allocator,
- const MipsInstructionSetFeatures* instruction_set_features = nullptr)
- : Assembler(allocator),
- overwriting_(false),
- overwrite_location_(0),
- reordering_(true),
- ds_fsm_state_(kExpectingLabel),
- ds_fsm_target_pc_(0),
- literals_(allocator->Adapter(kArenaAllocAssembler)),
- jump_tables_(allocator->Adapter(kArenaAllocAssembler)),
- last_position_adjustment_(0),
- last_old_position_(0),
- last_branch_id_(0),
- has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false),
- isa_features_(instruction_set_features) {
- cfi().DelayEmittingAdvancePCs();
- }
-
- size_t CodeSize() const override { return Assembler::CodeSize(); }
- size_t CodePosition() override;
- DebugFrameOpCodeWriterForAssembler& cfi() override { return Assembler::cfi(); }
-
- virtual ~MipsAssembler() {
- for (auto& branch : branches_) {
- CHECK(branch.IsResolved());
- }
- }
-
- // Emit Machine Instructions.
- void Addu(Register rd, Register rs, Register rt);
- void Addiu(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label);
- void Addiu(Register rt, Register rs, uint16_t imm16);
- void Subu(Register rd, Register rs, Register rt);
-
- void MultR2(Register rs, Register rt); // R2
- void MultuR2(Register rs, Register rt); // R2
- void DivR2(Register rs, Register rt); // R2
- void DivuR2(Register rs, Register rt); // R2
- void MulR2(Register rd, Register rs, Register rt); // R2
- void DivR2(Register rd, Register rs, Register rt); // R2
- void ModR2(Register rd, Register rs, Register rt); // R2
- void DivuR2(Register rd, Register rs, Register rt); // R2
- void ModuR2(Register rd, Register rs, Register rt); // R2
- void MulR6(Register rd, Register rs, Register rt); // R6
- void MuhR6(Register rd, Register rs, Register rt); // R6
- void MuhuR6(Register rd, Register rs, Register rt); // R6
- void DivR6(Register rd, Register rs, Register rt); // R6
- void ModR6(Register rd, Register rs, Register rt); // R6
- void DivuR6(Register rd, Register rs, Register rt); // R6
- void ModuR6(Register rd, Register rs, Register rt); // R6
-
- void And(Register rd, Register rs, Register rt);
- void Andi(Register rt, Register rs, uint16_t imm16);
- void Or(Register rd, Register rs, Register rt);
- void Ori(Register rt, Register rs, uint16_t imm16);
- void Xor(Register rd, Register rs, Register rt);
- void Xori(Register rt, Register rs, uint16_t imm16);
- void Nor(Register rd, Register rs, Register rt);
-
- void Movz(Register rd, Register rs, Register rt); // R2
- void Movn(Register rd, Register rs, Register rt); // R2
- void Seleqz(Register rd, Register rs, Register rt); // R6
- void Selnez(Register rd, Register rs, Register rt); // R6
- void ClzR6(Register rd, Register rs);
- void ClzR2(Register rd, Register rs);
- void CloR6(Register rd, Register rs);
- void CloR2(Register rd, Register rs);
-
- void Seb(Register rd, Register rt); // R2+
- void Seh(Register rd, Register rt); // R2+
- void Wsbh(Register rd, Register rt); // R2+
- void Bitswap(Register rd, Register rt); // R6
-
- void Sll(Register rd, Register rt, int shamt);
- void Srl(Register rd, Register rt, int shamt);
- void Rotr(Register rd, Register rt, int shamt); // R2+
- void Sra(Register rd, Register rt, int shamt);
- void Sllv(Register rd, Register rt, Register rs);
- void Srlv(Register rd, Register rt, Register rs);
- void Rotrv(Register rd, Register rt, Register rs); // R2+
- void Srav(Register rd, Register rt, Register rs);
- void Ext(Register rd, Register rt, int pos, int size); // R2+
- void Ins(Register rd, Register rt, int pos, int size); // R2+
- void Lsa(Register rd, Register rs, Register rt, int saPlusOne); // R6
- void ShiftAndAdd(Register dst, Register src_idx, Register src_base, int shamt, Register tmp = AT);
-
- void Lb(Register rt, Register rs, uint16_t imm16);
- void Lh(Register rt, Register rs, uint16_t imm16);
- void Lw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label);
- void Lw(Register rt, Register rs, uint16_t imm16);
- void Lwl(Register rt, Register rs, uint16_t imm16);
- void Lwr(Register rt, Register rs, uint16_t imm16);
- void Lbu(Register rt, Register rs, uint16_t imm16);
- void Lhu(Register rt, Register rs, uint16_t imm16);
- void Lwpc(Register rs, uint32_t imm19); // R6
- void Lui(Register rt, uint16_t imm16);
- void Aui(Register rt, Register rs, uint16_t imm16); // R6
- void AddUpper(Register rt, Register rs, uint16_t imm16, Register tmp = AT);
- void Sync(uint32_t stype);
- void Mfhi(Register rd); // R2
- void Mflo(Register rd); // R2
-
- void Sb(Register rt, Register rs, uint16_t imm16);
- void Sh(Register rt, Register rs, uint16_t imm16);
- void Sw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label);
- void Sw(Register rt, Register rs, uint16_t imm16);
- void Swl(Register rt, Register rs, uint16_t imm16);
- void Swr(Register rt, Register rs, uint16_t imm16);
-
- void LlR2(Register rt, Register base, int16_t imm16 = 0);
- void ScR2(Register rt, Register base, int16_t imm16 = 0);
- void LlR6(Register rt, Register base, int16_t imm9 = 0);
- void ScR6(Register rt, Register base, int16_t imm9 = 0);
-
- void Slt(Register rd, Register rs, Register rt);
- void Sltu(Register rd, Register rs, Register rt);
- void Slti(Register rt, Register rs, uint16_t imm16);
- void Sltiu(Register rt, Register rs, uint16_t imm16);
-
- // Branches and jumps to immediate offsets/addresses do not take care of their
- // delay/forbidden slots and generally should not be used directly. This applies
- // to the following R2 and R6 branch/jump instructions with imm16, imm21, addr26
- // offsets/addresses.
- // Use branches/jumps to labels instead.
- void B(uint16_t imm16);
- void Bal(uint16_t imm16);
- void Beq(Register rs, Register rt, uint16_t imm16);
- void Bne(Register rs, Register rt, uint16_t imm16);
- void Beqz(Register rt, uint16_t imm16);
- void Bnez(Register rt, uint16_t imm16);
- void Bltz(Register rt, uint16_t imm16);
- void Bgez(Register rt, uint16_t imm16);
- void Blez(Register rt, uint16_t imm16);
- void Bgtz(Register rt, uint16_t imm16);
- void Bc1f(uint16_t imm16); // R2
- void Bc1f(int cc, uint16_t imm16); // R2
- void Bc1t(uint16_t imm16); // R2
- void Bc1t(int cc, uint16_t imm16); // R2
- void J(uint32_t addr26);
- void Jal(uint32_t addr26);
- // Jalr() and Jr() fill their delay slots when reordering is enabled.
- // When reordering is disabled, the delay slots must be filled manually.
- // You may use NopIfNoReordering() to fill them when reordering is disabled.
- void Jalr(Register rd, Register rs);
- void Jalr(Register rs);
- void Jr(Register rs);
- // Nal() does not fill its delay slot. It must be filled manually.
- void Nal();
- void Auipc(Register rs, uint16_t imm16); // R6
- void Addiupc(Register rs, uint32_t imm19); // R6
- void Bc(uint32_t imm26); // R6
- void Balc(uint32_t imm26); // R6
- void Jic(Register rt, uint16_t imm16); // R6
- void Jialc(Register rt, uint16_t imm16); // R6
- void Bltc(Register rs, Register rt, uint16_t imm16); // R6
- void Bltzc(Register rt, uint16_t imm16); // R6
- void Bgtzc(Register rt, uint16_t imm16); // R6
- void Bgec(Register rs, Register rt, uint16_t imm16); // R6
- void Bgezc(Register rt, uint16_t imm16); // R6
- void Blezc(Register rt, uint16_t imm16); // R6
- void Bltuc(Register rs, Register rt, uint16_t imm16); // R6
- void Bgeuc(Register rs, Register rt, uint16_t imm16); // R6
- void Beqc(Register rs, Register rt, uint16_t imm16); // R6
- void Bnec(Register rs, Register rt, uint16_t imm16); // R6
- void Beqzc(Register rs, uint32_t imm21); // R6
- void Bnezc(Register rs, uint32_t imm21); // R6
- void Bc1eqz(FRegister ft, uint16_t imm16); // R6
- void Bc1nez(FRegister ft, uint16_t imm16); // R6
-
- void AddS(FRegister fd, FRegister fs, FRegister ft);
- void SubS(FRegister fd, FRegister fs, FRegister ft);
- void MulS(FRegister fd, FRegister fs, FRegister ft);
- void DivS(FRegister fd, FRegister fs, FRegister ft);
- void AddD(FRegister fd, FRegister fs, FRegister ft);
- void SubD(FRegister fd, FRegister fs, FRegister ft);
- void MulD(FRegister fd, FRegister fs, FRegister ft);
- void DivD(FRegister fd, FRegister fs, FRegister ft);
- void SqrtS(FRegister fd, FRegister fs);
- void SqrtD(FRegister fd, FRegister fs);
- void AbsS(FRegister fd, FRegister fs);
- void AbsD(FRegister fd, FRegister fs);
- void MovS(FRegister fd, FRegister fs);
- void MovD(FRegister fd, FRegister fs);
- void NegS(FRegister fd, FRegister fs);
- void NegD(FRegister fd, FRegister fs);
-
- void CunS(FRegister fs, FRegister ft); // R2
- void CunS(int cc, FRegister fs, FRegister ft); // R2
- void CeqS(FRegister fs, FRegister ft); // R2
- void CeqS(int cc, FRegister fs, FRegister ft); // R2
- void CueqS(FRegister fs, FRegister ft); // R2
- void CueqS(int cc, FRegister fs, FRegister ft); // R2
- void ColtS(FRegister fs, FRegister ft); // R2
- void ColtS(int cc, FRegister fs, FRegister ft); // R2
- void CultS(FRegister fs, FRegister ft); // R2
- void CultS(int cc, FRegister fs, FRegister ft); // R2
- void ColeS(FRegister fs, FRegister ft); // R2
- void ColeS(int cc, FRegister fs, FRegister ft); // R2
- void CuleS(FRegister fs, FRegister ft); // R2
- void CuleS(int cc, FRegister fs, FRegister ft); // R2
- void CunD(FRegister fs, FRegister ft); // R2
- void CunD(int cc, FRegister fs, FRegister ft); // R2
- void CeqD(FRegister fs, FRegister ft); // R2
- void CeqD(int cc, FRegister fs, FRegister ft); // R2
- void CueqD(FRegister fs, FRegister ft); // R2
- void CueqD(int cc, FRegister fs, FRegister ft); // R2
- void ColtD(FRegister fs, FRegister ft); // R2
- void ColtD(int cc, FRegister fs, FRegister ft); // R2
- void CultD(FRegister fs, FRegister ft); // R2
- void CultD(int cc, FRegister fs, FRegister ft); // R2
- void ColeD(FRegister fs, FRegister ft); // R2
- void ColeD(int cc, FRegister fs, FRegister ft); // R2
- void CuleD(FRegister fs, FRegister ft); // R2
- void CuleD(int cc, FRegister fs, FRegister ft); // R2
- void CmpUnS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpEqS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUeqS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpLtS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUltS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpLeS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUleS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpOrS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUneS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpNeS(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUnD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpEqD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUeqD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpLtD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUltD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpLeD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUleD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpOrD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpUneD(FRegister fd, FRegister fs, FRegister ft); // R6
- void CmpNeD(FRegister fd, FRegister fs, FRegister ft); // R6
- void Movf(Register rd, Register rs, int cc = 0); // R2
- void Movt(Register rd, Register rs, int cc = 0); // R2
- void MovfS(FRegister fd, FRegister fs, int cc = 0); // R2
- void MovfD(FRegister fd, FRegister fs, int cc = 0); // R2
- void MovtS(FRegister fd, FRegister fs, int cc = 0); // R2
- void MovtD(FRegister fd, FRegister fs, int cc = 0); // R2
- void MovzS(FRegister fd, FRegister fs, Register rt); // R2
- void MovzD(FRegister fd, FRegister fs, Register rt); // R2
- void MovnS(FRegister fd, FRegister fs, Register rt); // R2
- void MovnD(FRegister fd, FRegister fs, Register rt); // R2
- void SelS(FRegister fd, FRegister fs, FRegister ft); // R6
- void SelD(FRegister fd, FRegister fs, FRegister ft); // R6
- void SeleqzS(FRegister fd, FRegister fs, FRegister ft); // R6
- void SeleqzD(FRegister fd, FRegister fs, FRegister ft); // R6
- void SelnezS(FRegister fd, FRegister fs, FRegister ft); // R6
- void SelnezD(FRegister fd, FRegister fs, FRegister ft); // R6
- void ClassS(FRegister fd, FRegister fs); // R6
- void ClassD(FRegister fd, FRegister fs); // R6
- void MinS(FRegister fd, FRegister fs, FRegister ft); // R6
- void MinD(FRegister fd, FRegister fs, FRegister ft); // R6
- void MaxS(FRegister fd, FRegister fs, FRegister ft); // R6
- void MaxD(FRegister fd, FRegister fs, FRegister ft); // R6
-
- void TruncLS(FRegister fd, FRegister fs); // R2+, FR=1
- void TruncLD(FRegister fd, FRegister fs); // R2+, FR=1
- void TruncWS(FRegister fd, FRegister fs);
- void TruncWD(FRegister fd, FRegister fs);
- void Cvtsw(FRegister fd, FRegister fs);
- void Cvtdw(FRegister fd, FRegister fs);
- void Cvtsd(FRegister fd, FRegister fs);
- void Cvtds(FRegister fd, FRegister fs);
- void Cvtsl(FRegister fd, FRegister fs); // R2+, FR=1
- void Cvtdl(FRegister fd, FRegister fs); // R2+, FR=1
- void FloorWS(FRegister fd, FRegister fs);
- void FloorWD(FRegister fd, FRegister fs);
-
- // Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
- // when loading the value as 32-bit halves. This applies to all 32-bit FPR loads:
- // Mtc1(), Mthc1(), MoveToFpuHigh(), Lwc1(). Even if you need two Mtc1()'s or two
- // Lwc1()'s to load a pair of 32-bit FPRs and these loads do not interfere with one
- // another (unlike Mtc1() and Mthc1() with 64-bit FPRs), maintain the order:
- // low then high.
- //
- // Also, prefer MoveFromFpuHigh()/MoveToFpuHigh() over Mfhc1()/Mthc1() and Mfc1()/Mtc1().
- // This will save you some if statements.
- FRegister GetFpuRegLow(FRegister reg);
- void Mfc1(Register rt, FRegister fs);
- void Mtc1(Register rt, FRegister fs);
- void Mfhc1(Register rt, FRegister fs);
- void Mthc1(Register rt, FRegister fs);
- void MoveFromFpuHigh(Register rt, FRegister fs);
- void MoveToFpuHigh(Register rt, FRegister fs);
- void Lwc1(FRegister ft, Register rs, uint16_t imm16);
- void Ldc1(FRegister ft, Register rs, uint16_t imm16);
- void Swc1(FRegister ft, Register rs, uint16_t imm16);
- void Sdc1(FRegister ft, Register rs, uint16_t imm16);
-
- void Break();
- void Nop();
- void NopIfNoReordering();
- void Move(Register rd, Register rs);
- void Clear(Register rd);
- void Not(Register rd, Register rs);
-
- // MSA instructions.
- void AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void Ffint_sW(VectorRegister wd, VectorRegister ws);
- void Ffint_sD(VectorRegister wd, VectorRegister ws);
- void Ftint_sW(VectorRegister wd, VectorRegister ws);
- void Ftint_sD(VectorRegister wd, VectorRegister ws);
-
- void SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- // Immediate shift instructions, where shamtN denotes shift amount (must be between 0 and 2^N-1).
- void SlliB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SlliH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SlliW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SlliD(VectorRegister wd, VectorRegister ws, int shamt6);
- void SraiB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SraiH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SraiW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SraiD(VectorRegister wd, VectorRegister ws, int shamt6);
- void SrliB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SrliH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SrliW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SrliD(VectorRegister wd, VectorRegister ws, int shamt6);
-
- void MoveV(VectorRegister wd, VectorRegister ws);
- void SplatiB(VectorRegister wd, VectorRegister ws, int n4);
- void SplatiH(VectorRegister wd, VectorRegister ws, int n3);
- void SplatiW(VectorRegister wd, VectorRegister ws, int n2);
- void SplatiD(VectorRegister wd, VectorRegister ws, int n1);
- void Copy_sB(Register rd, VectorRegister ws, int n4);
- void Copy_sH(Register rd, VectorRegister ws, int n3);
- void Copy_sW(Register rd, VectorRegister ws, int n2);
- void Copy_uB(Register rd, VectorRegister ws, int n4);
- void Copy_uH(Register rd, VectorRegister ws, int n3);
- void InsertB(VectorRegister wd, Register rs, int n4);
- void InsertH(VectorRegister wd, Register rs, int n3);
- void InsertW(VectorRegister wd, Register rs, int n2);
- void FillB(VectorRegister wd, Register rs);
- void FillH(VectorRegister wd, Register rs);
- void FillW(VectorRegister wd, Register rs);
-
- void LdiB(VectorRegister wd, int imm8);
- void LdiH(VectorRegister wd, int imm10);
- void LdiW(VectorRegister wd, int imm10);
- void LdiD(VectorRegister wd, int imm10);
- void LdB(VectorRegister wd, Register rs, int offset);
- void LdH(VectorRegister wd, Register rs, int offset);
- void LdW(VectorRegister wd, Register rs, int offset);
- void LdD(VectorRegister wd, Register rs, int offset);
- void StB(VectorRegister wd, Register rs, int offset);
- void StH(VectorRegister wd, Register rs, int offset);
- void StW(VectorRegister wd, Register rs, int offset);
- void StD(VectorRegister wd, Register rs, int offset);
-
- void IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void PcntB(VectorRegister wd, VectorRegister ws);
- void PcntH(VectorRegister wd, VectorRegister ws);
- void PcntW(VectorRegister wd, VectorRegister ws);
- void PcntD(VectorRegister wd, VectorRegister ws);
-
- // Helper for replicating floating point value in all destination elements.
- void ReplicateFPToVectorRegister(VectorRegister dst, FRegister src, bool is_double);
-
- // Higher level composite instructions.
- void LoadConst32(Register rd, int32_t value);
- void LoadConst64(Register reg_hi, Register reg_lo, int64_t value);
- void LoadDConst64(FRegister rd, int64_t value, Register temp);
- void LoadSConst32(FRegister r, int32_t value, Register temp);
- void Addiu32(Register rt, Register rs, int32_t value, Register rtmp = AT);
-
- void Bind(MipsLabel* label);
- // When `is_bare` is false, the branches will promote to long (if the range
- // of the individual branch instruction is insufficient) and the delay/
- // forbidden slots will be taken care of.
- // Use `is_bare = false` when the branch target may be out of reach of the
- // individual branch instruction. IOW, this is for general purpose use.
- //
- // When `is_bare` is true, just the branch instructions will be generated
- // leaving delay/forbidden slot filling up to the caller and the branches
- // won't promote to long if the range is insufficient (you'll get a
- // compilation error when the range is exceeded).
- // Use `is_bare = true` when the branch target is known to be within reach
- // of the individual branch instruction. This is intended for small local
- // optimizations around delay/forbidden slots.
- // Also prefer using `is_bare = true` if the code near the branch is to be
- // patched or analyzed at run time (e.g. introspection) to
- // - show the intent and
- // - fail during compilation rather than during patching/execution if the
- // bare branch range is insufficent but the code size and layout are
- // expected to remain unchanged
- //
- // R2 branches with delay slots that are also available on R6.
- // On R6 when `is_bare` is false these convert to equivalent R6 compact
- // branches (to reduce code size). On R2 or when `is_bare` is true they
- // remain R2 branches with delay slots.
- void B(MipsLabel* label, bool is_bare = false);
- void Bal(MipsLabel* label, bool is_bare = false);
- void Beq(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- void Bne(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- void Beqz(Register rt, MipsLabel* label, bool is_bare = false);
- void Bnez(Register rt, MipsLabel* label, bool is_bare = false);
- void Bltz(Register rt, MipsLabel* label, bool is_bare = false);
- void Bgez(Register rt, MipsLabel* label, bool is_bare = false);
- void Blez(Register rt, MipsLabel* label, bool is_bare = false);
- void Bgtz(Register rt, MipsLabel* label, bool is_bare = false);
- void Blt(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- void Bge(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- void Bltu(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- void Bgeu(Register rs, Register rt, MipsLabel* label, bool is_bare = false);
- // R2-only branches with delay slots.
- void Bc1f(MipsLabel* label, bool is_bare = false); // R2
- void Bc1f(int cc, MipsLabel* label, bool is_bare = false); // R2
- void Bc1t(MipsLabel* label, bool is_bare = false); // R2
- void Bc1t(int cc, MipsLabel* label, bool is_bare = false); // R2
- // R6-only compact branches without delay/forbidden slots.
- void Bc(MipsLabel* label, bool is_bare = false); // R6
- void Balc(MipsLabel* label, bool is_bare = false); // R6
- // R6-only compact branches with forbidden slots.
- void Beqc(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bnec(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Beqzc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bnezc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bltzc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bgezc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Blezc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bgtzc(Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bltc(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bgec(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bltuc(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- void Bgeuc(Register rs, Register rt, MipsLabel* label, bool is_bare = false); // R6
- // R6-only branches with delay slots.
- void Bc1eqz(FRegister ft, MipsLabel* label, bool is_bare = false); // R6
- void Bc1nez(FRegister ft, MipsLabel* label, bool is_bare = false); // R6
-
- void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
- void AdjustBaseAndOffset(Register& base,
- int32_t& offset,
- bool is_doubleword,
- bool is_float = false);
- void AdjustBaseOffsetAndElementSizeShift(Register& base,
- int32_t& offset,
- int& element_size_shift);
-
- private:
- // This will be used as an argument for loads/stores
- // when there is no need for implicit null checks.
- struct NoImplicitNullChecker {
- void operator()() const {}
- };
-
- public:
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreConstToOffset(StoreOperandType type,
- int64_t value,
- Register base,
- int32_t offset,
- Register temp,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- // We permit `base` and `temp` to coincide (however, we check that neither is AT),
- // in which case the `base` register may be overwritten in the process.
- CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base.
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kStoreDoubleword));
- uint32_t low = Low32Bits(value);
- uint32_t high = High32Bits(value);
- Register reg;
- // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp`
- // to load and hold the value but we can use AT instead as AT hasn't been used yet.
- // Otherwise, `temp` can be used for the value. And if `temp` is the same as the
- // original `base` (that is, `base` prior to the adjustment), the original `base`
- // register will be overwritten.
- if (base == temp) {
- temp = AT;
- }
- if (low == 0) {
- reg = ZERO;
- } else {
- reg = temp;
- LoadConst32(reg, low);
- }
- switch (type) {
- case kStoreByte:
- Sb(reg, base, offset);
- break;
- case kStoreHalfword:
- Sh(reg, base, offset);
- break;
- case kStoreWord:
- Sw(reg, base, offset);
- break;
- case kStoreDoubleword:
- Sw(reg, base, offset);
- null_checker();
- if (high == 0) {
- reg = ZERO;
- } else {
- reg = temp;
- if (high != low) {
- LoadConst32(reg, high);
- }
- }
- Sw(reg, base, offset + kMipsWordSize);
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kStoreDoubleword) {
- null_checker();
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadFromOffset(LoadOperandType type,
- Register reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kLoadDoubleword));
- switch (type) {
- case kLoadSignedByte:
- Lb(reg, base, offset);
- break;
- case kLoadUnsignedByte:
- Lbu(reg, base, offset);
- break;
- case kLoadSignedHalfword:
- Lh(reg, base, offset);
- break;
- case kLoadUnsignedHalfword:
- Lhu(reg, base, offset);
- break;
- case kLoadWord:
- Lw(reg, base, offset);
- break;
- case kLoadDoubleword:
- if (reg == base) {
- // This will clobber the base when loading the lower register. Since we have to load the
- // higher register as well, this will fail. Solution: reverse the order.
- Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
- null_checker();
- Lw(reg, base, offset);
- } else {
- Lw(reg, base, offset);
- null_checker();
- Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
- }
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kLoadDoubleword) {
- null_checker();
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadSFromOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ false, /* is_float= */ true);
- Lwc1(reg, base, offset);
- null_checker();
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadDFromOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ true, /* is_float= */ true);
- if (IsAligned<kMipsDoublewordSize>(offset)) {
- Ldc1(reg, base, offset);
- null_checker();
- } else {
- if (Is32BitFPU()) {
- Lwc1(reg, base, offset);
- null_checker();
- Lwc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
- } else {
- // 64-bit FPU.
- Lwc1(reg, base, offset);
- null_checker();
- Lw(T8, base, offset + kMipsWordSize);
- Mthc1(T8, reg);
- }
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadQFromOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- int element_size_shift = -1;
- AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
- switch (element_size_shift) {
- case TIMES_1: LdB(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_2: LdH(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_4: LdW(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_8: LdD(static_cast<VectorRegister>(reg), base, offset); break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- null_checker();
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreToOffset(StoreOperandType type,
- Register reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- // Must not use AT as `reg`, so as not to overwrite the value being stored
- // with the adjusted `base`.
- CHECK_NE(reg, AT);
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kStoreDoubleword));
- switch (type) {
- case kStoreByte:
- Sb(reg, base, offset);
- break;
- case kStoreHalfword:
- Sh(reg, base, offset);
- break;
- case kStoreWord:
- Sw(reg, base, offset);
- break;
- case kStoreDoubleword:
- CHECK_NE(reg, base);
- CHECK_NE(static_cast<Register>(reg + 1), base);
- Sw(reg, base, offset);
- null_checker();
- Sw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kStoreDoubleword) {
- null_checker();
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreSToOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ false, /* is_float= */ true);
- Swc1(reg, base, offset);
- null_checker();
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreDToOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ true, /* is_float= */ true);
- if (IsAligned<kMipsDoublewordSize>(offset)) {
- Sdc1(reg, base, offset);
- null_checker();
- } else {
- if (Is32BitFPU()) {
- Swc1(reg, base, offset);
- null_checker();
- Swc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
- } else {
- // 64-bit FPU.
- Mfhc1(T8, reg);
- Swc1(reg, base, offset);
- null_checker();
- Sw(T8, base, offset + kMipsWordSize);
- }
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreQToOffset(FRegister reg,
- Register base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- int element_size_shift = -1;
- AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
- switch (element_size_shift) {
- case TIMES_1: StB(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_2: StH(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_4: StW(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_8: StD(static_cast<VectorRegister>(reg), base, offset); break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- null_checker();
- }
-
- void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
- void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
- void LoadDFromOffset(FRegister reg, Register base, int32_t offset);
- void LoadQFromOffset(FRegister reg, Register base, int32_t offset);
- void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
- void StoreSToOffset(FRegister reg, Register base, int32_t offset);
- void StoreDToOffset(FRegister reg, Register base, int32_t offset);
- void StoreQToOffset(FRegister reg, Register base, int32_t offset);
-
- // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
- void Emit(uint32_t value);
-
- // Push/pop composite routines.
- void Push(Register rs);
- void Pop(Register rd);
- void PopAndReturn(Register rd, Register rt);
-
- //
- // Heap poisoning.
- //
-
- // Poison a heap reference contained in `src` and store it in `dst`.
- void PoisonHeapReference(Register dst, Register src) {
- // dst = -src.
- Subu(dst, ZERO, src);
- }
- // Poison a heap reference contained in `reg`.
- void PoisonHeapReference(Register reg) {
- // reg = -reg.
- PoisonHeapReference(reg, reg);
- }
- // Unpoison a heap reference contained in `reg`.
- void UnpoisonHeapReference(Register reg) {
- // reg = -reg.
- Subu(reg, ZERO, reg);
- }
- // Poison a heap reference contained in `reg` if heap poisoning is enabled.
- void MaybePoisonHeapReference(Register reg) {
- if (kPoisonHeapReferences) {
- PoisonHeapReference(reg);
- }
- }
- // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
- void MaybeUnpoisonHeapReference(Register reg) {
- if (kPoisonHeapReferences) {
- UnpoisonHeapReference(reg);
- }
- }
-
- void Bind(Label* label) override {
- Bind(down_cast<MipsLabel*>(label));
- }
- void Jump(Label* label ATTRIBUTE_UNUSED) override {
- UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS";
- }
-
- // Don't warn about a different virtual Bind/Jump in the base class.
- using JNIBase::Bind;
- using JNIBase::Jump;
-
- // Create a new label that can be used with Jump/Bind calls.
- std::unique_ptr<JNIMacroLabel> CreateLabel() override {
- LOG(FATAL) << "Not implemented on MIPS32";
- UNREACHABLE();
- }
- // Emit an unconditional jump to the label.
- void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS32";
- UNREACHABLE();
- }
- // Emit a conditional jump to the label by applying a unary condition test to the register.
- void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED,
- JNIMacroUnaryCondition cond ATTRIBUTE_UNUSED,
- ManagedRegister test ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS32";
- UNREACHABLE();
- }
-
- // Code at this offset will serve as the target for the Jump call.
- void Bind(JNIMacroLabel* label ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS32";
- UNREACHABLE();
- }
-
- // Create a new literal with a given value.
- // NOTE: Force the template parameter to be explicitly specified.
- template <typename T>
- Literal* NewLiteral(typename Identity<T>::type value) {
- static_assert(std::is_integral<T>::value, "T must be an integral type.");
- return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
- }
-
- // Load label address using PC-relative addressing.
- // To be used with data labels in the literal / jump table area only and not
- // with regular code labels.
- //
- // For R6 base_reg must be ZERO.
- //
- // On R2 there are two possible uses w.r.t. base_reg:
- //
- // - base_reg = ZERO:
- // The NAL instruction will be generated as part of the load and it will
- // clobber the RA register.
- //
- // - base_reg != ZERO:
- // The RA-clobbering NAL instruction won't be generated as part of the load.
- // The label pc_rel_base_label_ must be bound (with BindPcRelBaseLabel())
- // and base_reg must hold the address of the label. Example:
- // __ Nal();
- // __ Move(S3, RA);
- // __ BindPcRelBaseLabel(); // S3 holds the address of pc_rel_base_label_.
- // __ LoadLabelAddress(A0, S3, label1);
- // __ LoadLabelAddress(A1, S3, label2);
- // __ LoadLiteral(V0, S3, literal1);
- // __ LoadLiteral(V1, S3, literal2);
- void LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label);
-
- // Create a new literal with the given data.
- Literal* NewLiteral(size_t size, const uint8_t* data);
-
- // Load literal using PC-relative addressing.
- // See the above comments for LoadLabelAddress() on the value of base_reg.
- void LoadLiteral(Register dest_reg, Register base_reg, Literal* literal);
-
- // Create a jump table for the given labels that will be emitted when finalizing.
- // When the table is emitted, offsets will be relative to the location of the table.
- // The table location is determined by the location of its label (the label precedes
- // the table data) and should be loaded using LoadLabelAddress().
- JumpTable* CreateJumpTable(std::vector<MipsLabel*>&& labels);
-
- //
- // Overridden common assembler high-level functionality.
- //
-
- // Emit code that will create an activation on the stack.
- void BuildFrame(size_t frame_size,
- ManagedRegister method_reg,
- ArrayRef<const ManagedRegister> callee_save_regs,
- const ManagedRegisterEntrySpills& entry_spills) override;
-
- // Emit code that will remove an activation from the stack.
- void RemoveFrame(size_t frame_size,
- ArrayRef<const ManagedRegister> callee_save_regs,
- bool may_suspend) override;
-
- void IncreaseFrameSize(size_t adjust) override;
- void DecreaseFrameSize(size_t adjust) override;
-
- // Store routines.
- void Store(FrameOffset offs, ManagedRegister msrc, size_t size) override;
- void StoreRef(FrameOffset dest, ManagedRegister msrc) override;
- void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) override;
-
- void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) override;
-
- void StoreStackOffsetToThread(ThreadOffset32 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) override;
-
- void StoreStackPointerToThread(ThreadOffset32 thr_offs) override;
-
- void StoreSpanning(FrameOffset dest,
- ManagedRegister msrc,
- FrameOffset in_off,
- ManagedRegister mscratch) override;
-
- // Load routines.
- void Load(ManagedRegister mdest, FrameOffset src, size_t size) override;
-
- void LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) override;
-
- void LoadRef(ManagedRegister dest, FrameOffset src) override;
-
- void LoadRef(ManagedRegister mdest,
- ManagedRegister base,
- MemberOffset offs,
- bool unpoison_reference) override;
-
- void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) override;
-
- void LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) override;
-
- // Copying routines.
- void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) override;
-
- void CopyRawPtrFromThread(FrameOffset fr_offs,
- ThreadOffset32 thr_offs,
- ManagedRegister mscratch) override;
-
- void CopyRawPtrToThread(ThreadOffset32 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) override;
-
- void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) override;
-
- void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) override;
-
- void Copy(FrameOffset dest,
- ManagedRegister src_base,
- Offset src_offset,
- ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(ManagedRegister dest_base,
- Offset dest_offset,
- FrameOffset src,
- ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(FrameOffset dest,
- FrameOffset src_base,
- Offset src_offset,
- ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(ManagedRegister dest,
- Offset dest_offset,
- ManagedRegister src,
- Offset src_offset,
- ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(FrameOffset dest,
- Offset dest_offset,
- FrameOffset src,
- Offset src_offset,
- ManagedRegister mscratch,
- size_t size) override;
-
- void MemoryBarrier(ManagedRegister) override;
-
- // Sign extension.
- void SignExtend(ManagedRegister mreg, size_t size) override;
-
- // Zero extension.
- void ZeroExtend(ManagedRegister mreg, size_t size) override;
-
- // Exploit fast access in managed code to Thread::Current().
- void GetCurrentThread(ManagedRegister tr) override;
- void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) override;
-
- // Set up out_reg to hold a Object** into the handle scope, or to be null if the
- // value is null and null_allowed. in_reg holds a possibly stale reference
- // that can be used to avoid loading the handle scope entry to see if the value is
- // null.
- void CreateHandleScopeEntry(ManagedRegister out_reg,
- FrameOffset handlescope_offset,
- ManagedRegister in_reg,
- bool null_allowed) override;
-
- // Set up out_off to hold a Object** into the handle scope, or to be null if the
- // value is null and null_allowed.
- void CreateHandleScopeEntry(FrameOffset out_off,
- FrameOffset handlescope_offset,
- ManagedRegister mscratch,
- bool null_allowed) override;
-
- // src holds a handle scope entry (Object**) load this into dst.
- void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) override;
-
- // Heap::VerifyObject on src. In some cases (such as a reference to this) we
- // know that src may not be null.
- void VerifyObject(ManagedRegister src, bool could_be_null) override;
- void VerifyObject(FrameOffset src, bool could_be_null) override;
-
- // Jump to address held at [base+offset] (used for tail calls).
- void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-
- // Call to address held at [base+offset].
- void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) override;
- void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) override;
- void CallFromThread(ThreadOffset32 offset, ManagedRegister mscratch) override;
-
- // Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) override;
-
- // Emit slow paths queued during assembly and promote short branches to long if needed.
- void FinalizeCode() override;
-
- // Emit branches and finalize all instructions.
- void FinalizeInstructions(const MemoryRegion& region) override;
-
- // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS,
- // must be used instead of MipsLabel::GetPosition()).
- uint32_t GetLabelLocation(const MipsLabel* label) const;
-
- // Get the final position of a label after local fixup based on the old position
- // recorded before FinalizeCode().
- uint32_t GetAdjustedPosition(uint32_t old_position);
-
- // R2 doesn't have PC-relative addressing, which we need to access literals. We simulate it by
- // reading the PC value into a general-purpose register with the NAL instruction and then loading
- // literals through this base register. The code generator calls this method (at most once per
- // method being compiled) to bind a label to the location for which the PC value is acquired.
- // The assembler then computes literal offsets relative to this label.
- void BindPcRelBaseLabel();
-
- // Returns the location of the label bound with BindPcRelBaseLabel().
- uint32_t GetPcRelBaseLabelLocation() const;
-
- // Note that PC-relative literal loads are handled as pseudo branches because they need very
- // similar relocation and may similarly expand in size to accomodate for larger offsets relative
- // to PC.
- enum BranchCondition {
- kCondLT,
- kCondGE,
- kCondLE,
- kCondGT,
- kCondLTZ,
- kCondGEZ,
- kCondLEZ,
- kCondGTZ,
- kCondEQ,
- kCondNE,
- kCondEQZ,
- kCondNEZ,
- kCondLTU,
- kCondGEU,
- kCondF, // Floating-point predicate false.
- kCondT, // Floating-point predicate true.
- kUncond,
- };
- friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs);
-
- // Enables or disables instruction reordering (IOW, automatic filling of delay slots)
- // similarly to ".set reorder" / ".set noreorder" in traditional MIPS assembly.
- // Returns the last state, which may be useful for temporary enabling/disabling of
- // reordering.
- bool SetReorder(bool enable);
-
- private:
- // Description of the last instruction in terms of input and output registers.
- // Used to make the decision of moving the instruction into a delay slot.
- struct DelaySlot {
- DelaySlot();
-
- // Encoded instruction that may be used to fill the delay slot or 0
- // (0 conveniently represents NOP).
- uint32_t instruction_;
-
- // Input/output register masks.
- InOutRegMasks masks_;
-
- // Label for patchable instructions to allow moving them into delay slots.
- MipsLabel* patcher_label_;
- };
-
- // Delay slot finite state machine's (DS FSM's) state. The FSM state is updated
- // upon every new instruction and label generated. The FSM detects instructions
- // suitable for delay slots and immediately preceded with labels. These are target
- // instructions for branches. If an unconditional R2 branch does not get its delay
- // slot filled with the immediately preceding instruction, it may instead get the
- // slot filled with the target instruction (the branch will need its offset
- // incremented past the target instruction). We call this "absorption". The FSM
- // records PCs of the target instructions suitable for this optimization.
- enum DsFsmState {
- kExpectingLabel,
- kExpectingInstruction,
- kExpectingCommit
- };
- friend std::ostream& operator<<(std::ostream& os, const DsFsmState& rhs);
-
- class Branch {
- public:
- enum Type {
- // R2 short branches (can be promoted to long).
- kUncondBranch,
- kCondBranch,
- kCall,
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- kBareUncondBranch,
- kBareCondBranch,
- kBareCall,
- // R2 near label.
- kLabel,
- // R2 near literal.
- kLiteral,
- // R2 long branches.
- kLongUncondBranch,
- kLongCondBranch,
- kLongCall,
- // R2 far label.
- kFarLabel,
- // R2 far literal.
- kFarLiteral,
- // R6 short branches (can be promoted to long).
- kR6UncondBranch,
- kR6CondBranch,
- kR6Call,
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- kR6BareUncondBranch,
- kR6BareCondBranch,
- kR6BareCall,
- // R6 near label.
- kR6Label,
- // R6 near literal.
- kR6Literal,
- // R6 long branches.
- kR6LongUncondBranch,
- kR6LongCondBranch,
- kR6LongCall,
- // R6 far label.
- kR6FarLabel,
- // R6 far literal.
- kR6FarLiteral,
- };
- // Bit sizes of offsets defined as enums to minimize chance of typos.
- enum OffsetBits {
- kOffset16 = 16,
- kOffset18 = 18,
- kOffset21 = 21,
- kOffset23 = 23,
- kOffset28 = 28,
- kOffset32 = 32,
- };
-
- static constexpr uint32_t kUnresolved = 0xffffffff; // Unresolved target_
- static constexpr int32_t kMaxBranchLength = 32;
- static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t);
- // The following two instruction encodings can never legally occur in branch delay
- // slots and are used as markers.
- //
- // kUnfilledDelaySlot means that the branch may use either the preceding or the target
- // instruction to fill its delay slot (the latter is only possible with unconditional
- // R2 branches and is termed here as "absorption").
- static constexpr uint32_t kUnfilledDelaySlot = 0x10000000; // beq zero, zero, 0.
- // kUnfillableDelaySlot means that the branch cannot use an instruction (other than NOP)
- // to fill its delay slot. This is only used for unconditional R2 branches to prevent
- // absorption of the target instruction when reordering is disabled.
- static constexpr uint32_t kUnfillableDelaySlot = 0x13FF0000; // beq ra, ra, 0.
-
- struct BranchInfo {
- // Branch length as a number of 4-byte-long instructions.
- uint32_t length;
- // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's
- // PC-relative offset (or its most significant 16-bit half, which goes first).
- uint32_t instr_offset;
- // Different MIPS instructions with PC-relative offsets apply said offsets to slightly
- // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte
- // instructions) from the instruction containing the offset.
- uint32_t pc_org;
- // How large (in bits) a PC-relative offset can be for a given type of branch (kR6CondBranch
- // and kR6BareCondBranch are an exception: use kOffset23 for beqzc/bnezc).
- OffsetBits offset_size;
- // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift
- // count.
- int offset_shift;
- };
- static const BranchInfo branch_info_[/* Type */];
-
- // Unconditional branch or call.
- Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call, bool is_bare);
- // Conditional branch.
- Branch(bool is_r6,
- uint32_t location,
- uint32_t target,
- BranchCondition condition,
- Register lhs_reg,
- Register rhs_reg,
- bool is_bare);
- // Label address (in literal area) or literal.
- Branch(bool is_r6,
- uint32_t location,
- Register dest_reg,
- Register base_reg,
- Type label_or_literal_type);
-
- // Some conditional branches with lhs = rhs are effectively NOPs, while some
- // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs.
- // So, we need a way to identify such branches in order to emit no instructions for them
- // or change them to unconditional.
- static bool IsNop(BranchCondition condition, Register lhs, Register rhs);
- static bool IsUncond(BranchCondition condition, Register lhs, Register rhs);
-
- static BranchCondition OppositeCondition(BranchCondition cond);
-
- Type GetType() const;
- BranchCondition GetCondition() const;
- Register GetLeftRegister() const;
- Register GetRightRegister() const;
- uint32_t GetTarget() const;
- uint32_t GetLocation() const;
- uint32_t GetOldLocation() const;
- uint32_t GetPrecedingInstructionLength(Type type) const;
- uint32_t GetPrecedingInstructionSize(Type type) const;
- uint32_t GetLength() const;
- uint32_t GetOldLength() const;
- uint32_t GetSize() const;
- uint32_t GetOldSize() const;
- uint32_t GetEndLocation() const;
- uint32_t GetOldEndLocation() const;
- bool IsBare() const;
- bool IsLong() const;
- bool IsResolved() const;
-
- // Various helpers for branch delay slot management.
- bool CanHaveDelayedInstruction(const DelaySlot& delay_slot) const;
- void SetDelayedInstruction(uint32_t instruction, MipsLabel* patcher_label = nullptr);
- uint32_t GetDelayedInstruction() const;
- MipsLabel* GetPatcherLabel() const;
- void DecrementLocations();
-
- // Returns the bit size of the signed offset that the branch instruction can handle.
- OffsetBits GetOffsetSize() const;
-
- // Calculates the distance between two byte locations in the assembler buffer and
- // returns the number of bits needed to represent the distance as a signed integer.
- //
- // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc),
- // and 26 (bc) bits, which are additionally shifted left 2 positions at run time.
- //
- // Composite branches (made of several instructions) with longer reach have 32-bit
- // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first).
- // The composite branches cover the range of PC + +/-2GB on MIPS32 CPUs. However,
- // the range is not end-to-end on MIPS64 (unless addresses are forced to zero- or
- // sign-extend from 32 to 64 bits by the appropriate CPU configuration).
- // Consider the following implementation of a long unconditional branch, for
- // example:
- //
- // auipc at, offset_31_16 // at = pc + sign_extend(offset_31_16) << 16
- // jic at, offset_15_0 // pc = at + sign_extend(offset_15_0)
- //
- // Both of the above instructions take 16-bit signed offsets as immediate operands.
- // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000
- // due to sign extension. This must be compensated for by incrementing offset_31_16
- // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is
- // 0x7FFF, adding 1 will overflow the positive offset into the negative range.
- // Therefore, the long branch range is something like from PC - 0x80000000 to
- // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side.
- //
- // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special
- // case with the addiu instruction and a 16 bit offset.
- static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target);
-
- // Resolve a branch when the target is known.
- void Resolve(uint32_t target);
-
- // Relocate a branch by a given delta if needed due to expansion of this or another
- // branch at a given location by this delta (just changes location_ and target_).
- void Relocate(uint32_t expand_location, uint32_t delta);
-
- // If the branch is short, changes its type to long.
- void PromoteToLong();
-
- // If necessary, updates the type by promoting a short branch to a long branch
- // based on the branch location and target. Returns the amount (in bytes) by
- // which the branch size has increased.
- // max_short_distance caps the maximum distance between location_ and target_
- // that is allowed for short branches. This is for debugging/testing purposes.
- // max_short_distance = 0 forces all short branches to become long.
- // Use the implicit default argument when not debugging/testing.
- uint32_t PromoteIfNeeded(uint32_t location,
- uint32_t max_short_distance = std::numeric_limits<uint32_t>::max());
-
- // Returns the location of the instruction(s) containing the offset.
- uint32_t GetOffsetLocation() const;
-
- // Calculates and returns the offset ready for encoding in the branch instruction(s).
- uint32_t GetOffset(uint32_t location) const;
-
- private:
- // Completes branch construction by determining and recording its type.
- void InitializeType(Type initial_type, bool is_r6);
- // Helper for the above.
- void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type);
-
- uint32_t old_location_; // Offset into assembler buffer in bytes.
- uint32_t location_; // Offset into assembler buffer in bytes.
- uint32_t target_; // Offset into assembler buffer in bytes.
-
- uint32_t lhs_reg_; // Left-hand side register in conditional branches or
- // FPU condition code. Destination register in literals.
- uint32_t rhs_reg_; // Right-hand side register in conditional branches.
- // Base register in literals (ZERO on R6).
- BranchCondition condition_; // Condition for conditional branches.
-
- Type type_; // Current type of the branch.
- Type old_type_; // Initial type of the branch.
-
- uint32_t delayed_instruction_; // Encoded instruction for the delay slot or
- // kUnfilledDelaySlot if none but fillable or
- // kUnfillableDelaySlot if none and unfillable
- // (the latter is only used for unconditional R2
- // branches).
-
- MipsLabel* patcher_label_; // Patcher label for the instruction in the delay slot.
- };
- friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs);
- friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs);
-
- uint32_t EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
- uint32_t EmitI(int opcode, Register rs, Register rt, uint16_t imm);
- uint32_t EmitI21(int opcode, Register rs, uint32_t imm21);
- uint32_t EmitI26(int opcode, uint32_t imm26);
- uint32_t EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
- uint32_t EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
- void EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16);
- void EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21);
- uint32_t EmitMsa3R(int operation,
- int df,
- VectorRegister wt,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode);
- uint32_t EmitMsaBIT(int operation,
- int df_m,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode);
- uint32_t EmitMsaELM(int operation,
- int df_n,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode);
- uint32_t EmitMsaMI10(int s10, Register rs, VectorRegister wd, int minor_opcode, int df);
- uint32_t EmitMsaI10(int operation, int df, int i10, VectorRegister wd, int minor_opcode);
- uint32_t EmitMsa2R(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode);
- uint32_t EmitMsa2RF(int operation,
- int df,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode);
-
- void Buncond(MipsLabel* label, bool is_r6, bool is_bare);
- void Bcond(MipsLabel* label,
- bool is_r6,
- bool is_bare,
- BranchCondition condition,
- Register lhs,
- Register rhs = ZERO);
- void Call(MipsLabel* label, bool is_r6, bool is_bare);
- void FinalizeLabeledBranch(MipsLabel* label);
-
- // Various helpers for branch delay slot management.
- InOutRegMasks& DsFsmInstr(uint32_t instruction, MipsLabel* patcher_label = nullptr);
- void DsFsmInstrNop(uint32_t instruction);
- void DsFsmLabel();
- void DsFsmCommitLabel();
- void DsFsmDropLabel();
- void MoveInstructionToDelaySlot(Branch& branch);
- bool CanExchangeWithSlt(Register rs, Register rt) const;
- void ExchangeWithSlt(const DelaySlot& forwarded_slot);
- void GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt);
-
- Branch* GetBranch(uint32_t branch_id);
- const Branch* GetBranch(uint32_t branch_id) const;
- uint32_t GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const;
- uint32_t GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const;
- void BindRelativeToPrecedingBranch(MipsLabel* label,
- uint32_t prev_branch_id_plus_one,
- uint32_t position);
-
- void EmitLiterals();
- void ReserveJumpTableSpace();
- void EmitJumpTables();
- void PromoteBranches();
- void EmitBranch(uint32_t branch_id);
- void EmitBranches();
- void PatchCFI(size_t number_of_delayed_adjust_pcs);
-
- // Emits exception block.
- void EmitExceptionPoll(MipsExceptionSlowPath* exception);
-
- bool HasMsa() const {
- return has_msa_;
- }
-
- bool IsR6() const {
- if (isa_features_ != nullptr) {
- return isa_features_->IsR6();
- } else {
- return false;
- }
- }
-
- bool Is32BitFPU() const {
- if (isa_features_ != nullptr) {
- return isa_features_->Is32BitFloatingPoint();
- } else {
- return true;
- }
- }
-
- // List of exception blocks to generate at the end of the code cache.
- std::vector<MipsExceptionSlowPath> exception_blocks_;
-
- std::vector<Branch> branches_;
-
- // Whether appending instructions at the end of the buffer or overwriting the existing ones.
- bool overwriting_;
- // The current overwrite location.
- uint32_t overwrite_location_;
-
- // Whether instruction reordering (IOW, automatic filling of delay slots) is enabled.
- bool reordering_;
- // Information about the last instruction that may be used to fill a branch delay slot.
- DelaySlot delay_slot_;
- // Delay slot FSM state.
- DsFsmState ds_fsm_state_;
- // PC of the current labeled target instruction.
- uint32_t ds_fsm_target_pc_;
- // PCs of labeled target instructions.
- std::vector<uint32_t> ds_fsm_target_pcs_;
-
- // Use std::deque<> for literal labels to allow insertions at the end
- // without invalidating pointers and references to existing elements.
- ArenaDeque<Literal> literals_;
-
- // Jump table list.
- ArenaDeque<JumpTable> jump_tables_;
-
- // There's no PC-relative addressing on MIPS32R2. So, in order to access literals relative to PC
- // we get PC using the NAL instruction. This label marks the position within the assembler buffer
- // that PC (from NAL) points to.
- MipsLabel pc_rel_base_label_;
-
- // Data for GetAdjustedPosition(), see the description there.
- uint32_t last_position_adjustment_;
- uint32_t last_old_position_;
- uint32_t last_branch_id_;
-
- const bool has_msa_;
-
- const MipsInstructionSetFeatures* isa_features_;
-
- DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
-};
-
-} // namespace mips
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
diff --git a/compiler/utils/mips/assembler_mips32r5_test.cc b/compiler/utils/mips/assembler_mips32r5_test.cc
deleted file mode 100644
index 98fc44b..0000000
--- a/compiler/utils/mips/assembler_mips32r5_test.cc
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (C) 2017 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 "assembler_mips.h"
-
-#include <map>
-
-#include "base/stl_util.h"
-#include "utils/assembler_test.h"
-
-#define __ GetAssembler()->
-
-namespace art {
-
-struct MIPSCpuRegisterCompare {
- bool operator()(const mips::Register& a, const mips::Register& b) const {
- return a < b;
- }
-};
-
-class AssemblerMIPS32r5Test : public AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t,
- mips::VectorRegister> {
- public:
- using Base = AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t,
- mips::VectorRegister>;
-
- // These tests were taking too long, so we hide the DriverStr() from AssemblerTest<>
- // and reimplement it without the verification against `assembly_string`. b/73903608
- void DriverStr(const std::string& assembly_string ATTRIBUTE_UNUSED,
- const std::string& test_name ATTRIBUTE_UNUSED) {
- GetAssembler()->FinalizeCode();
- std::vector<uint8_t> data(GetAssembler()->CodeSize());
- MemoryRegion code(data.data(), data.size());
- GetAssembler()->FinalizeInstructions(code);
- }
-
- AssemblerMIPS32r5Test() :
- instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r5", nullptr)) {
- }
-
- protected:
- // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
- std::string GetArchitectureString() override {
- return "mips";
- }
-
- std::string GetAssemblerParameters() override {
- return " --no-warn -32 -march=mips32r5 -mmsa";
- }
-
- void Pad(std::vector<uint8_t>& data) override {
- // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple
- // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't
- // pad, so, in order for two assembler outputs to match, we need to match the padding as well.
- // NOP is encoded as four zero bytes on MIPS.
- size_t pad_size = RoundUp(data.size(), 16u) - data.size();
- data.insert(data.end(), pad_size, 0);
- }
-
- std::string GetDisassembleParameters() override {
- return " -D -bbinary -mmips:isa32r5";
- }
-
- mips::MipsAssembler* CreateAssembler(ArenaAllocator* allocator) override {
- return new (allocator) mips::MipsAssembler(allocator, instruction_set_features_.get());
- }
-
- void SetUpHelpers() override {
- if (registers_.size() == 0) {
- registers_.push_back(new mips::Register(mips::ZERO));
- registers_.push_back(new mips::Register(mips::AT));
- registers_.push_back(new mips::Register(mips::V0));
- registers_.push_back(new mips::Register(mips::V1));
- registers_.push_back(new mips::Register(mips::A0));
- registers_.push_back(new mips::Register(mips::A1));
- registers_.push_back(new mips::Register(mips::A2));
- registers_.push_back(new mips::Register(mips::A3));
- registers_.push_back(new mips::Register(mips::T0));
- registers_.push_back(new mips::Register(mips::T1));
- registers_.push_back(new mips::Register(mips::T2));
- registers_.push_back(new mips::Register(mips::T3));
- registers_.push_back(new mips::Register(mips::T4));
- registers_.push_back(new mips::Register(mips::T5));
- registers_.push_back(new mips::Register(mips::T6));
- registers_.push_back(new mips::Register(mips::T7));
- registers_.push_back(new mips::Register(mips::S0));
- registers_.push_back(new mips::Register(mips::S1));
- registers_.push_back(new mips::Register(mips::S2));
- registers_.push_back(new mips::Register(mips::S3));
- registers_.push_back(new mips::Register(mips::S4));
- registers_.push_back(new mips::Register(mips::S5));
- registers_.push_back(new mips::Register(mips::S6));
- registers_.push_back(new mips::Register(mips::S7));
- registers_.push_back(new mips::Register(mips::T8));
- registers_.push_back(new mips::Register(mips::T9));
- registers_.push_back(new mips::Register(mips::K0));
- registers_.push_back(new mips::Register(mips::K1));
- registers_.push_back(new mips::Register(mips::GP));
- registers_.push_back(new mips::Register(mips::SP));
- registers_.push_back(new mips::Register(mips::FP));
- registers_.push_back(new mips::Register(mips::RA));
-
- secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
- secondary_register_names_.emplace(mips::Register(mips::AT), "at");
- secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
- secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
- secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
- secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
- secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
- secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
- secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
- secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
- secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
- secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
- secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
- secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
- secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
- secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
- secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
- secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
- secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
- secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
- secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
- secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
- secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
- secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
- secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
- secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
- secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
- secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
- secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
- secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
- secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
- secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
-
- fp_registers_.push_back(new mips::FRegister(mips::F0));
- fp_registers_.push_back(new mips::FRegister(mips::F1));
- fp_registers_.push_back(new mips::FRegister(mips::F2));
- fp_registers_.push_back(new mips::FRegister(mips::F3));
- fp_registers_.push_back(new mips::FRegister(mips::F4));
- fp_registers_.push_back(new mips::FRegister(mips::F5));
- fp_registers_.push_back(new mips::FRegister(mips::F6));
- fp_registers_.push_back(new mips::FRegister(mips::F7));
- fp_registers_.push_back(new mips::FRegister(mips::F8));
- fp_registers_.push_back(new mips::FRegister(mips::F9));
- fp_registers_.push_back(new mips::FRegister(mips::F10));
- fp_registers_.push_back(new mips::FRegister(mips::F11));
- fp_registers_.push_back(new mips::FRegister(mips::F12));
- fp_registers_.push_back(new mips::FRegister(mips::F13));
- fp_registers_.push_back(new mips::FRegister(mips::F14));
- fp_registers_.push_back(new mips::FRegister(mips::F15));
- fp_registers_.push_back(new mips::FRegister(mips::F16));
- fp_registers_.push_back(new mips::FRegister(mips::F17));
- fp_registers_.push_back(new mips::FRegister(mips::F18));
- fp_registers_.push_back(new mips::FRegister(mips::F19));
- fp_registers_.push_back(new mips::FRegister(mips::F20));
- fp_registers_.push_back(new mips::FRegister(mips::F21));
- fp_registers_.push_back(new mips::FRegister(mips::F22));
- fp_registers_.push_back(new mips::FRegister(mips::F23));
- fp_registers_.push_back(new mips::FRegister(mips::F24));
- fp_registers_.push_back(new mips::FRegister(mips::F25));
- fp_registers_.push_back(new mips::FRegister(mips::F26));
- fp_registers_.push_back(new mips::FRegister(mips::F27));
- fp_registers_.push_back(new mips::FRegister(mips::F28));
- fp_registers_.push_back(new mips::FRegister(mips::F29));
- fp_registers_.push_back(new mips::FRegister(mips::F30));
- fp_registers_.push_back(new mips::FRegister(mips::F31));
-
- vec_registers_.push_back(new mips::VectorRegister(mips::W0));
- vec_registers_.push_back(new mips::VectorRegister(mips::W1));
- vec_registers_.push_back(new mips::VectorRegister(mips::W2));
- vec_registers_.push_back(new mips::VectorRegister(mips::W3));
- vec_registers_.push_back(new mips::VectorRegister(mips::W4));
- vec_registers_.push_back(new mips::VectorRegister(mips::W5));
- vec_registers_.push_back(new mips::VectorRegister(mips::W6));
- vec_registers_.push_back(new mips::VectorRegister(mips::W7));
- vec_registers_.push_back(new mips::VectorRegister(mips::W8));
- vec_registers_.push_back(new mips::VectorRegister(mips::W9));
- vec_registers_.push_back(new mips::VectorRegister(mips::W10));
- vec_registers_.push_back(new mips::VectorRegister(mips::W11));
- vec_registers_.push_back(new mips::VectorRegister(mips::W12));
- vec_registers_.push_back(new mips::VectorRegister(mips::W13));
- vec_registers_.push_back(new mips::VectorRegister(mips::W14));
- vec_registers_.push_back(new mips::VectorRegister(mips::W15));
- vec_registers_.push_back(new mips::VectorRegister(mips::W16));
- vec_registers_.push_back(new mips::VectorRegister(mips::W17));
- vec_registers_.push_back(new mips::VectorRegister(mips::W18));
- vec_registers_.push_back(new mips::VectorRegister(mips::W19));
- vec_registers_.push_back(new mips::VectorRegister(mips::W20));
- vec_registers_.push_back(new mips::VectorRegister(mips::W21));
- vec_registers_.push_back(new mips::VectorRegister(mips::W22));
- vec_registers_.push_back(new mips::VectorRegister(mips::W23));
- vec_registers_.push_back(new mips::VectorRegister(mips::W24));
- vec_registers_.push_back(new mips::VectorRegister(mips::W25));
- vec_registers_.push_back(new mips::VectorRegister(mips::W26));
- vec_registers_.push_back(new mips::VectorRegister(mips::W27));
- vec_registers_.push_back(new mips::VectorRegister(mips::W28));
- vec_registers_.push_back(new mips::VectorRegister(mips::W29));
- vec_registers_.push_back(new mips::VectorRegister(mips::W30));
- vec_registers_.push_back(new mips::VectorRegister(mips::W31));
- }
- }
-
- void TearDown() override {
- AssemblerTest::TearDown();
- STLDeleteElements(®isters_);
- STLDeleteElements(&fp_registers_);
- STLDeleteElements(&vec_registers_);
- }
-
- std::vector<mips::MipsLabel> GetAddresses() override {
- UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
- UNREACHABLE();
- }
-
- std::vector<mips::Register*> GetRegisters() override {
- return registers_;
- }
-
- std::vector<mips::FRegister*> GetFPRegisters() override {
- return fp_registers_;
- }
-
- std::vector<mips::VectorRegister*> GetVectorRegisters() override {
- return vec_registers_;
- }
-
- uint32_t CreateImmediate(int64_t imm_value) override {
- return imm_value;
- }
-
- std::string GetSecondaryRegisterName(const mips::Register& reg) override {
- CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
- return secondary_register_names_[reg];
- }
-
- std::string RepeatInsn(size_t count, const std::string& insn) {
- std::string result;
- for (; count != 0u; --count) {
- result += insn;
- }
- return result;
- }
-
- private:
- std::vector<mips::Register*> registers_;
- std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
-
- std::vector<mips::FRegister*> fp_registers_;
- std::vector<mips::VectorRegister*> vec_registers_;
- std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_;
-};
-
-TEST_F(AssemblerMIPS32r5Test, Toolchain) {
- EXPECT_TRUE(CheckTools());
-}
-
-TEST_F(AssemblerMIPS32r5Test, LoadQFromOffset) {
- __ LoadQFromOffset(mips::F0, mips::A0, 0);
- __ LoadQFromOffset(mips::F0, mips::A0, 1);
- __ LoadQFromOffset(mips::F0, mips::A0, 2);
- __ LoadQFromOffset(mips::F0, mips::A0, 4);
- __ LoadQFromOffset(mips::F0, mips::A0, 8);
- __ LoadQFromOffset(mips::F0, mips::A0, 511);
- __ LoadQFromOffset(mips::F0, mips::A0, 512);
- __ LoadQFromOffset(mips::F0, mips::A0, 513);
- __ LoadQFromOffset(mips::F0, mips::A0, 514);
- __ LoadQFromOffset(mips::F0, mips::A0, 516);
- __ LoadQFromOffset(mips::F0, mips::A0, 1022);
- __ LoadQFromOffset(mips::F0, mips::A0, 1024);
- __ LoadQFromOffset(mips::F0, mips::A0, 1025);
- __ LoadQFromOffset(mips::F0, mips::A0, 1026);
- __ LoadQFromOffset(mips::F0, mips::A0, 1028);
- __ LoadQFromOffset(mips::F0, mips::A0, 2044);
- __ LoadQFromOffset(mips::F0, mips::A0, 2048);
- __ LoadQFromOffset(mips::F0, mips::A0, 2049);
- __ LoadQFromOffset(mips::F0, mips::A0, 2050);
- __ LoadQFromOffset(mips::F0, mips::A0, 2052);
- __ LoadQFromOffset(mips::F0, mips::A0, 4088);
- __ LoadQFromOffset(mips::F0, mips::A0, 4096);
- __ LoadQFromOffset(mips::F0, mips::A0, 4097);
- __ LoadQFromOffset(mips::F0, mips::A0, 4098);
- __ LoadQFromOffset(mips::F0, mips::A0, 4100);
- __ LoadQFromOffset(mips::F0, mips::A0, 4104);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFC);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x8000);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x10000);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x12345678);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x12350078);
- __ LoadQFromOffset(mips::F0, mips::A0, -256);
- __ LoadQFromOffset(mips::F0, mips::A0, -511);
- __ LoadQFromOffset(mips::F0, mips::A0, -513);
- __ LoadQFromOffset(mips::F0, mips::A0, -1022);
- __ LoadQFromOffset(mips::F0, mips::A0, -1026);
- __ LoadQFromOffset(mips::F0, mips::A0, -2044);
- __ LoadQFromOffset(mips::F0, mips::A0, -2052);
- __ LoadQFromOffset(mips::F0, mips::A0, -4096);
- __ LoadQFromOffset(mips::F0, mips::A0, -4104);
- __ LoadQFromOffset(mips::F0, mips::A0, -32768);
- __ LoadQFromOffset(mips::F0, mips::A0, -36856);
- __ LoadQFromOffset(mips::F0, mips::A0, 36856);
- __ LoadQFromOffset(mips::F0, mips::A0, -69608);
- __ LoadQFromOffset(mips::F0, mips::A0, 69608);
- __ LoadQFromOffset(mips::F0, mips::A0, 0xABCDEF00);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFFABCD);
-
- const char* expected =
- "ld.d $w0, 0($a0)\n"
- "ld.b $w0, 1($a0)\n"
- "ld.h $w0, 2($a0)\n"
- "ld.w $w0, 4($a0)\n"
- "ld.d $w0, 8($a0)\n"
- "ld.b $w0, 511($a0)\n"
- "ld.d $w0, 512($a0)\n"
- "addiu $at, $a0, 513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, 514($a0)\n"
- "ld.w $w0, 516($a0)\n"
- "ld.h $w0, 1022($a0)\n"
- "ld.d $w0, 1024($a0)\n"
- "addiu $at, $a0, 1025\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, 1028($a0)\n"
- "ld.w $w0, 2044($a0)\n"
- "ld.d $w0, 2048($a0)\n"
- "addiu $at, $a0, 2049\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 2050\n"
- "ld.h $w0, 0($at)\n"
- "addiu $at, $a0, 2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, 4088($a0)\n"
- "addiu $at, $a0, 4096\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, 4097\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 4098\n"
- "ld.h $w0, 0($at)\n"
- "addiu $at, $a0, 4100\n"
- "ld.w $w0, 0($at)\n"
- "addiu $at, $a0, 4104\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FFC\n"
- "ld.w $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ld.d $w0, 8($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 32760\n"
- "ld.d $w0, 16($at)\n"
- "lui $at, 4660\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, 24576\n"
- "ld.d $w0, -2440($at) # 0xF678\n"
- "lui $at, 4661\n"
- "addu $at, $at, $a0\n"
- "ld.d $w0, 120($at)\n"
- "ld.d $w0, -256($a0)\n"
- "ld.b $w0, -511($a0)\n"
- "addiu $at, $a0, -513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, -1022($a0)\n"
- "addiu $at, $a0, -1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, -2044($a0)\n"
- "addiu $at, $a0, -2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, -4096($a0)\n"
- "addiu $at, $a0, -4104\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, -32768\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, -32760\n"
- "addiu $at, $at, -4096\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 4096\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, -32760\n"
- "addiu $at, $at, -32760\n"
- "ld.d $w0, -4088($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 32760\n"
- "ld.d $w0, 4088($at)\n"
- "lui $at, 0xABCE\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, -8192 # 0xE000\n"
- "ld.d $w0, 0xF00($at)\n"
- "lui $at, 0x8000\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, -21504 # 0xAC00\n"
- "ld.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "LoadQFromOffset");
-}
-
-TEST_F(AssemblerMIPS32r5Test, StoreQToOffset) {
- __ StoreQToOffset(mips::F0, mips::A0, 0);
- __ StoreQToOffset(mips::F0, mips::A0, 1);
- __ StoreQToOffset(mips::F0, mips::A0, 2);
- __ StoreQToOffset(mips::F0, mips::A0, 4);
- __ StoreQToOffset(mips::F0, mips::A0, 8);
- __ StoreQToOffset(mips::F0, mips::A0, 511);
- __ StoreQToOffset(mips::F0, mips::A0, 512);
- __ StoreQToOffset(mips::F0, mips::A0, 513);
- __ StoreQToOffset(mips::F0, mips::A0, 514);
- __ StoreQToOffset(mips::F0, mips::A0, 516);
- __ StoreQToOffset(mips::F0, mips::A0, 1022);
- __ StoreQToOffset(mips::F0, mips::A0, 1024);
- __ StoreQToOffset(mips::F0, mips::A0, 1025);
- __ StoreQToOffset(mips::F0, mips::A0, 1026);
- __ StoreQToOffset(mips::F0, mips::A0, 1028);
- __ StoreQToOffset(mips::F0, mips::A0, 2044);
- __ StoreQToOffset(mips::F0, mips::A0, 2048);
- __ StoreQToOffset(mips::F0, mips::A0, 2049);
- __ StoreQToOffset(mips::F0, mips::A0, 2050);
- __ StoreQToOffset(mips::F0, mips::A0, 2052);
- __ StoreQToOffset(mips::F0, mips::A0, 4088);
- __ StoreQToOffset(mips::F0, mips::A0, 4096);
- __ StoreQToOffset(mips::F0, mips::A0, 4097);
- __ StoreQToOffset(mips::F0, mips::A0, 4098);
- __ StoreQToOffset(mips::F0, mips::A0, 4100);
- __ StoreQToOffset(mips::F0, mips::A0, 4104);
- __ StoreQToOffset(mips::F0, mips::A0, 0x7FFC);
- __ StoreQToOffset(mips::F0, mips::A0, 0x8000);
- __ StoreQToOffset(mips::F0, mips::A0, 0x10000);
- __ StoreQToOffset(mips::F0, mips::A0, 0x12345678);
- __ StoreQToOffset(mips::F0, mips::A0, 0x12350078);
- __ StoreQToOffset(mips::F0, mips::A0, -256);
- __ StoreQToOffset(mips::F0, mips::A0, -511);
- __ StoreQToOffset(mips::F0, mips::A0, -513);
- __ StoreQToOffset(mips::F0, mips::A0, -1022);
- __ StoreQToOffset(mips::F0, mips::A0, -1026);
- __ StoreQToOffset(mips::F0, mips::A0, -2044);
- __ StoreQToOffset(mips::F0, mips::A0, -2052);
- __ StoreQToOffset(mips::F0, mips::A0, -4096);
- __ StoreQToOffset(mips::F0, mips::A0, -4104);
- __ StoreQToOffset(mips::F0, mips::A0, -32768);
- __ StoreQToOffset(mips::F0, mips::A0, -36856);
- __ StoreQToOffset(mips::F0, mips::A0, 36856);
- __ StoreQToOffset(mips::F0, mips::A0, -69608);
- __ StoreQToOffset(mips::F0, mips::A0, 69608);
- __ StoreQToOffset(mips::F0, mips::A0, 0xABCDEF00);
- __ StoreQToOffset(mips::F0, mips::A0, 0x7FFFABCD);
-
- const char* expected =
- "st.d $w0, 0($a0)\n"
- "st.b $w0, 1($a0)\n"
- "st.h $w0, 2($a0)\n"
- "st.w $w0, 4($a0)\n"
- "st.d $w0, 8($a0)\n"
- "st.b $w0, 511($a0)\n"
- "st.d $w0, 512($a0)\n"
- "addiu $at, $a0, 513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, 514($a0)\n"
- "st.w $w0, 516($a0)\n"
- "st.h $w0, 1022($a0)\n"
- "st.d $w0, 1024($a0)\n"
- "addiu $at, $a0, 1025\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, 1028($a0)\n"
- "st.w $w0, 2044($a0)\n"
- "st.d $w0, 2048($a0)\n"
- "addiu $at, $a0, 2049\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 2050\n"
- "st.h $w0, 0($at)\n"
- "addiu $at, $a0, 2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, 4088($a0)\n"
- "addiu $at, $a0, 4096\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, 4097\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 4098\n"
- "st.h $w0, 0($at)\n"
- "addiu $at, $a0, 4100\n"
- "st.w $w0, 0($at)\n"
- "addiu $at, $a0, 4104\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FFC\n"
- "st.w $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "st.d $w0, 8($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 32760\n"
- "st.d $w0, 16($at)\n"
- "lui $at, 4660\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, 24576\n"
- "st.d $w0, -2440($at) # 0xF678\n"
- "lui $at, 4661\n"
- "addu $at, $at, $a0\n"
- "st.d $w0, 120($at)\n"
- "st.d $w0, -256($a0)\n"
- "st.b $w0, -511($a0)\n"
- "addiu $at, $a0, -513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, -1022($a0)\n"
- "addiu $at, $a0, -1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, -2044($a0)\n"
- "addiu $at, $a0, -2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, -4096($a0)\n"
- "addiu $at, $a0, -4104\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, -32768\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, -32760\n"
- "addiu $at, $at, -4096\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 4096\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, -32760\n"
- "addiu $at, $at, -32760\n"
- "st.d $w0, -4088($at)\n"
- "addiu $at, $a0, 32760\n"
- "addiu $at, $at, 32760\n"
- "st.d $w0, 4088($at)\n"
- "lui $at, 0xABCE\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, -8192 # 0xE000\n"
- "st.d $w0, 0xF00($at)\n"
- "lui $at, 0x8000\n"
- "addu $at, $at, $a0\n"
- "addiu $at, $at, -21504 # 0xAC00\n"
- "st.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "StoreQToOffset");
-}
-
-#undef __
-} // namespace art
diff --git a/compiler/utils/mips/assembler_mips32r6_test.cc b/compiler/utils/mips/assembler_mips32r6_test.cc
deleted file mode 100644
index a465a68..0000000
--- a/compiler/utils/mips/assembler_mips32r6_test.cc
+++ /dev/null
@@ -1,2528 +0,0 @@
-/*
- * Copyright (C) 2016 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 "assembler_mips.h"
-
-#include <map>
-
-#include "base/stl_util.h"
-#include "utils/assembler_test.h"
-
-#define __ GetAssembler()->
-
-namespace art {
-
-struct MIPSCpuRegisterCompare {
- bool operator()(const mips::Register& a, const mips::Register& b) const {
- return a < b;
- }
-};
-
-class AssemblerMIPS32r6Test : public AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t,
- mips::VectorRegister> {
- public:
- using Base = AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t,
- mips::VectorRegister>;
-
- // These tests were taking too long, so we hide the DriverStr() from AssemblerTest<>
- // and reimplement it without the verification against `assembly_string`. b/73903608
- void DriverStr(const std::string& assembly_string ATTRIBUTE_UNUSED,
- const std::string& test_name ATTRIBUTE_UNUSED) {
- GetAssembler()->FinalizeCode();
- std::vector<uint8_t> data(GetAssembler()->CodeSize());
- MemoryRegion code(data.data(), data.size());
- GetAssembler()->FinalizeInstructions(code);
- }
-
- AssemblerMIPS32r6Test() :
- instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r6", nullptr)) {
- }
-
- protected:
- // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
- std::string GetArchitectureString() override {
- return "mips";
- }
-
- std::string GetAssemblerCmdName() override {
- // We assemble and link for MIPS32R6. See GetAssemblerParameters() for details.
- return "gcc";
- }
-
- std::string GetAssemblerParameters() override {
- // We assemble and link for MIPS32R6. The reason is that object files produced for MIPS32R6
- // (and MIPS64R6) with the GNU assembler don't have correct final offsets in PC-relative
- // branches in the .text section and so they require a relocation pass (there's a relocation
- // section, .rela.text, that has the needed info to fix up the branches).
- // We use "-modd-spreg" so we can use odd-numbered single precision FPU registers.
- // We put the code at address 0x1000000 (instead of 0) to avoid overlapping with the
- // .MIPS.abiflags section (there doesn't seem to be a way to suppress its generation easily).
- return " -march=mips32r6 -mmsa -modd-spreg -Wa,--no-warn"
- " -Wl,-Ttext=0x1000000 -Wl,-e0x1000000 -nostdlib";
- }
-
- void Pad(std::vector<uint8_t>& data) override {
- // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple
- // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't
- // pad, so, in order for two assembler outputs to match, we need to match the padding as well.
- // NOP is encoded as four zero bytes on MIPS.
- size_t pad_size = RoundUp(data.size(), 16u) - data.size();
- data.insert(data.end(), pad_size, 0);
- }
-
- std::string GetDisassembleParameters() override {
- return " -D -bbinary -mmips:isa32r6";
- }
-
- mips::MipsAssembler* CreateAssembler(ArenaAllocator* allocator) override {
- return new (allocator) mips::MipsAssembler(allocator, instruction_set_features_.get());
- }
-
- void SetUpHelpers() override {
- if (registers_.size() == 0) {
- registers_.push_back(new mips::Register(mips::ZERO));
- registers_.push_back(new mips::Register(mips::AT));
- registers_.push_back(new mips::Register(mips::V0));
- registers_.push_back(new mips::Register(mips::V1));
- registers_.push_back(new mips::Register(mips::A0));
- registers_.push_back(new mips::Register(mips::A1));
- registers_.push_back(new mips::Register(mips::A2));
- registers_.push_back(new mips::Register(mips::A3));
- registers_.push_back(new mips::Register(mips::T0));
- registers_.push_back(new mips::Register(mips::T1));
- registers_.push_back(new mips::Register(mips::T2));
- registers_.push_back(new mips::Register(mips::T3));
- registers_.push_back(new mips::Register(mips::T4));
- registers_.push_back(new mips::Register(mips::T5));
- registers_.push_back(new mips::Register(mips::T6));
- registers_.push_back(new mips::Register(mips::T7));
- registers_.push_back(new mips::Register(mips::S0));
- registers_.push_back(new mips::Register(mips::S1));
- registers_.push_back(new mips::Register(mips::S2));
- registers_.push_back(new mips::Register(mips::S3));
- registers_.push_back(new mips::Register(mips::S4));
- registers_.push_back(new mips::Register(mips::S5));
- registers_.push_back(new mips::Register(mips::S6));
- registers_.push_back(new mips::Register(mips::S7));
- registers_.push_back(new mips::Register(mips::T8));
- registers_.push_back(new mips::Register(mips::T9));
- registers_.push_back(new mips::Register(mips::K0));
- registers_.push_back(new mips::Register(mips::K1));
- registers_.push_back(new mips::Register(mips::GP));
- registers_.push_back(new mips::Register(mips::SP));
- registers_.push_back(new mips::Register(mips::FP));
- registers_.push_back(new mips::Register(mips::RA));
-
- secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
- secondary_register_names_.emplace(mips::Register(mips::AT), "at");
- secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
- secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
- secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
- secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
- secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
- secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
- secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
- secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
- secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
- secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
- secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
- secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
- secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
- secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
- secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
- secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
- secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
- secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
- secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
- secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
- secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
- secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
- secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
- secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
- secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
- secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
- secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
- secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
- secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
- secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
-
- fp_registers_.push_back(new mips::FRegister(mips::F0));
- fp_registers_.push_back(new mips::FRegister(mips::F1));
- fp_registers_.push_back(new mips::FRegister(mips::F2));
- fp_registers_.push_back(new mips::FRegister(mips::F3));
- fp_registers_.push_back(new mips::FRegister(mips::F4));
- fp_registers_.push_back(new mips::FRegister(mips::F5));
- fp_registers_.push_back(new mips::FRegister(mips::F6));
- fp_registers_.push_back(new mips::FRegister(mips::F7));
- fp_registers_.push_back(new mips::FRegister(mips::F8));
- fp_registers_.push_back(new mips::FRegister(mips::F9));
- fp_registers_.push_back(new mips::FRegister(mips::F10));
- fp_registers_.push_back(new mips::FRegister(mips::F11));
- fp_registers_.push_back(new mips::FRegister(mips::F12));
- fp_registers_.push_back(new mips::FRegister(mips::F13));
- fp_registers_.push_back(new mips::FRegister(mips::F14));
- fp_registers_.push_back(new mips::FRegister(mips::F15));
- fp_registers_.push_back(new mips::FRegister(mips::F16));
- fp_registers_.push_back(new mips::FRegister(mips::F17));
- fp_registers_.push_back(new mips::FRegister(mips::F18));
- fp_registers_.push_back(new mips::FRegister(mips::F19));
- fp_registers_.push_back(new mips::FRegister(mips::F20));
- fp_registers_.push_back(new mips::FRegister(mips::F21));
- fp_registers_.push_back(new mips::FRegister(mips::F22));
- fp_registers_.push_back(new mips::FRegister(mips::F23));
- fp_registers_.push_back(new mips::FRegister(mips::F24));
- fp_registers_.push_back(new mips::FRegister(mips::F25));
- fp_registers_.push_back(new mips::FRegister(mips::F26));
- fp_registers_.push_back(new mips::FRegister(mips::F27));
- fp_registers_.push_back(new mips::FRegister(mips::F28));
- fp_registers_.push_back(new mips::FRegister(mips::F29));
- fp_registers_.push_back(new mips::FRegister(mips::F30));
- fp_registers_.push_back(new mips::FRegister(mips::F31));
-
- vec_registers_.push_back(new mips::VectorRegister(mips::W0));
- vec_registers_.push_back(new mips::VectorRegister(mips::W1));
- vec_registers_.push_back(new mips::VectorRegister(mips::W2));
- vec_registers_.push_back(new mips::VectorRegister(mips::W3));
- vec_registers_.push_back(new mips::VectorRegister(mips::W4));
- vec_registers_.push_back(new mips::VectorRegister(mips::W5));
- vec_registers_.push_back(new mips::VectorRegister(mips::W6));
- vec_registers_.push_back(new mips::VectorRegister(mips::W7));
- vec_registers_.push_back(new mips::VectorRegister(mips::W8));
- vec_registers_.push_back(new mips::VectorRegister(mips::W9));
- vec_registers_.push_back(new mips::VectorRegister(mips::W10));
- vec_registers_.push_back(new mips::VectorRegister(mips::W11));
- vec_registers_.push_back(new mips::VectorRegister(mips::W12));
- vec_registers_.push_back(new mips::VectorRegister(mips::W13));
- vec_registers_.push_back(new mips::VectorRegister(mips::W14));
- vec_registers_.push_back(new mips::VectorRegister(mips::W15));
- vec_registers_.push_back(new mips::VectorRegister(mips::W16));
- vec_registers_.push_back(new mips::VectorRegister(mips::W17));
- vec_registers_.push_back(new mips::VectorRegister(mips::W18));
- vec_registers_.push_back(new mips::VectorRegister(mips::W19));
- vec_registers_.push_back(new mips::VectorRegister(mips::W20));
- vec_registers_.push_back(new mips::VectorRegister(mips::W21));
- vec_registers_.push_back(new mips::VectorRegister(mips::W22));
- vec_registers_.push_back(new mips::VectorRegister(mips::W23));
- vec_registers_.push_back(new mips::VectorRegister(mips::W24));
- vec_registers_.push_back(new mips::VectorRegister(mips::W25));
- vec_registers_.push_back(new mips::VectorRegister(mips::W26));
- vec_registers_.push_back(new mips::VectorRegister(mips::W27));
- vec_registers_.push_back(new mips::VectorRegister(mips::W28));
- vec_registers_.push_back(new mips::VectorRegister(mips::W29));
- vec_registers_.push_back(new mips::VectorRegister(mips::W30));
- vec_registers_.push_back(new mips::VectorRegister(mips::W31));
- }
- }
-
- void TearDown() override {
- AssemblerTest::TearDown();
- STLDeleteElements(®isters_);
- STLDeleteElements(&fp_registers_);
- STLDeleteElements(&vec_registers_);
- }
-
- std::vector<mips::MipsLabel> GetAddresses() override {
- UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
- UNREACHABLE();
- }
-
- std::vector<mips::Register*> GetRegisters() override {
- return registers_;
- }
-
- std::vector<mips::FRegister*> GetFPRegisters() override {
- return fp_registers_;
- }
-
- std::vector<mips::VectorRegister*> GetVectorRegisters() override {
- return vec_registers_;
- }
-
- uint32_t CreateImmediate(int64_t imm_value) override {
- return imm_value;
- }
-
- std::string GetSecondaryRegisterName(const mips::Register& reg) override {
- CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
- return secondary_register_names_[reg];
- }
-
- std::string RepeatInsn(size_t count, const std::string& insn) {
- std::string result;
- for (; count != 0u; --count) {
- result += insn;
- }
- return result;
- }
-
- void BranchHelper(void (mips::MipsAssembler::*f)(mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool has_slot,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label1, label2;
- (Base::GetAssembler()->*f)(&label1, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label1);
- (Base::GetAssembler()->*f)(&label2, is_bare);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label2);
- (Base::GetAssembler()->*f)(&label1, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " 1f\n" +
- ((is_bare || !has_slot) ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- instr_name + " 2f\n" +
- ((is_bare || !has_slot) ? "" : "nop\n") +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- "2:\n" +
- instr_name + " 1b\n" +
- ((is_bare || !has_slot) ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondOneRegHelper(void (mips::MipsAssembler::*f)(mips::Register,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(mips::A0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(mips::A1, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a1, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register,
- mips::Register,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(mips::A2, mips::A3, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, $a1, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a2, $a3, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchFpuCondHelper(void (mips::MipsAssembler::*f)(mips::FRegister,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(mips::F0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(mips::F30, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $f0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $f30, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- private:
- std::vector<mips::Register*> registers_;
- std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
-
- std::vector<mips::FRegister*> fp_registers_;
- std::vector<mips::VectorRegister*> vec_registers_;
- std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_;
-};
-
-
-TEST_F(AssemblerMIPS32r6Test, Toolchain) {
- // This test is disabled as `gcc` (used as MIPS32 assembler, see
- // `AssemblerMIPS32r6Test.GetAssemblerCmdName`) is being removed from Android
- // (see b/147336214 and b/147240075).
- TEST_DISABLED();
- EXPECT_TRUE(CheckTools());
-}
-
-TEST_F(AssemblerMIPS32r6Test, MulR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::MulR6, "mul ${reg1}, ${reg2}, ${reg3}"), "MulR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MuhR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::MuhR6, "muh ${reg1}, ${reg2}, ${reg3}"), "MuhR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MuhuR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::MuhuR6, "muhu ${reg1}, ${reg2}, ${reg3}"), "MuhuR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, DivR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::DivR6, "div ${reg1}, ${reg2}, ${reg3}"), "DivR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ModR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::ModR6, "mod ${reg1}, ${reg2}, ${reg3}"), "ModR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, DivuR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::DivuR6, "divu ${reg1}, ${reg2}, ${reg3}"), "DivuR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ModuR6) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::ModuR6, "modu ${reg1}, ${reg2}, ${reg3}"), "ModuR6");
-}
-
-//////////
-// MISC //
-//////////
-
-TEST_F(AssemblerMIPS32r6Test, Aui) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Aui, 16, "aui ${reg1}, ${reg2}, {imm}"), "Aui");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Auipc) {
- DriverStr(RepeatRIb(&mips::MipsAssembler::Auipc, 16, "auipc ${reg}, {imm}"), "Auipc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Lwpc) {
- // Lwpc() takes an unsigned 19-bit immediate, while the GNU assembler needs a signed offset,
- // hence the sign extension from bit 18 with `imm - ((imm & 0x40000) << 1)`.
- // The GNU assembler also wants the offset to be a multiple of 4, which it will shift right
- // by 2 positions when encoding, hence `<< 2` to compensate for that shift.
- // We capture the value of the immediate with `.set imm, {imm}` because the value is needed
- // twice for the sign extension, but `{imm}` is substituted only once.
- const char* code = ".set imm, {imm}\nlw ${reg}, ((imm - ((imm & 0x40000) << 1)) << 2)($pc)";
- DriverStr(RepeatRIb(&mips::MipsAssembler::Lwpc, 19, code), "Lwpc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Addiupc) {
- // The comment from the Lwpc() test applies to this Addiupc() test as well.
- const char* code = ".set imm, {imm}\naddiupc ${reg}, (imm - ((imm & 0x40000) << 1)) << 2";
- DriverStr(RepeatRIb(&mips::MipsAssembler::Addiupc, 19, code), "Addiupc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bitswap) {
- DriverStr(RepeatRR(&mips::MipsAssembler::Bitswap, "bitswap ${reg1}, ${reg2}"), "bitswap");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Lsa) {
- DriverStr(RepeatRRRIb(&mips::MipsAssembler::Lsa,
- 2,
- "lsa ${reg1}, ${reg2}, ${reg3}, {imm}",
- 1),
- "lsa");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Seleqz) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Seleqz, "seleqz ${reg1}, ${reg2}, ${reg3}"), "seleqz");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Selnez) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Selnez, "selnez ${reg1}, ${reg2}, ${reg3}"), "selnez");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ClzR6) {
- DriverStr(RepeatRR(&mips::MipsAssembler::ClzR6, "clz ${reg1}, ${reg2}"), "clzR6");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CloR6) {
- DriverStr(RepeatRR(&mips::MipsAssembler::CloR6, "clo ${reg1}, ${reg2}"), "cloR6");
-}
-
-////////////////////
-// FLOATING POINT //
-////////////////////
-
-TEST_F(AssemblerMIPS32r6Test, SelS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SelS, "sel.s ${reg1}, ${reg2}, ${reg3}"), "sel.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SelD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SelD, "sel.d ${reg1}, ${reg2}, ${reg3}"), "sel.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SeleqzS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SeleqzS, "seleqz.s ${reg1}, ${reg2}, ${reg3}"),
- "seleqz.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SeleqzD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SeleqzD, "seleqz.d ${reg1}, ${reg2}, ${reg3}"),
- "seleqz.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SelnezS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SelnezS, "selnez.s ${reg1}, ${reg2}, ${reg3}"),
- "selnez.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SelnezD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SelnezD, "selnez.d ${reg1}, ${reg2}, ${reg3}"),
- "selnez.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ClassS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::ClassS, "class.s ${reg1}, ${reg2}"), "class.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ClassD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::ClassD, "class.d ${reg1}, ${reg2}"), "class.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MinS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MinS, "min.s ${reg1}, ${reg2}, ${reg3}"), "min.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MinD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MinD, "min.d ${reg1}, ${reg2}, ${reg3}"), "min.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaxS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MaxS, "max.s ${reg1}, ${reg2}, ${reg3}"), "max.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaxD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MaxD, "max.d ${reg1}, ${reg2}, ${reg3}"), "max.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUnS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnS, "cmp.un.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.un.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpEqS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqS, "cmp.eq.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.eq.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUeqS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqS, "cmp.ueq.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ueq.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpLtS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtS, "cmp.lt.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.lt.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUltS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltS, "cmp.ult.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ult.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpLeS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeS, "cmp.le.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.le.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUleS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleS, "cmp.ule.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ule.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpOrS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrS, "cmp.or.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.or.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUneS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneS, "cmp.une.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.une.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpNeS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeS, "cmp.ne.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ne.s");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUnD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnD, "cmp.un.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.un.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpEqD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqD, "cmp.eq.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.eq.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUeqD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqD, "cmp.ueq.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ueq.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpLtD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtD, "cmp.lt.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.lt.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUltD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltD, "cmp.ult.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ult.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpLeD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeD, "cmp.le.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.le.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUleD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleD, "cmp.ule.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ule.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpOrD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrD, "cmp.or.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.or.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpUneD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneD, "cmp.une.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.une.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, CmpNeD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeD, "cmp.ne.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ne.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LoadDFromOffset) {
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8000);
- __ LoadDFromOffset(mips::F0, mips::A0, +0);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FF8);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFB);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFC);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFF);
- __ LoadDFromOffset(mips::F0, mips::A0, -0xFFF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8008);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8001);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x8000);
- __ LoadDFromOffset(mips::F0, mips::A0, +0xFFF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF1);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF1);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF8);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE9);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE9);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FF0);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x12345678);
-
- const char* expected =
- "ldc1 $f0, -0x8000($a0)\n"
- "ldc1 $f0, 0($a0)\n"
- "ldc1 $f0, 0x7FF8($a0)\n"
- "lwc1 $f0, 0x7FFB($a0)\n"
- "lw $t8, 0x7FFF($a0)\n"
- "mthc1 $t8, $f0\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f0, 4($at)\n"
- "lw $t8, 8($at)\n"
- "mthc1 $t8, $f0\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f0, 7($at)\n"
- "lw $t8, 11($at)\n"
- "mthc1 $t8, $f0\n"
- "addiu $at, $a0, -0x7FF8\n"
- "ldc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "ldc1 $f0, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "lwc1 $f0, -9($at)\n"
- "lw $t8, -5($at)\n"
- "mthc1 $t8, $f0\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ldc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ldc1 $f0, 0x7FF8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "ldc1 $f0, -0x7FE8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "ldc1 $f0, 0x8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "lwc1 $f0, 0xF($at)\n"
- "lw $t8, 0x13($at)\n"
- "mthc1 $t8, $f0\n"
- "aui $at, $a0, 0x1\n"
- "lwc1 $f0, -0xF($at)\n"
- "lw $t8, -0xB($at)\n"
- "mthc1 $t8, $f0\n"
- "aui $at, $a0, 0x1\n"
- "ldc1 $f0, -0x8($at)\n"
- "aui $at, $a0, 0x1\n"
- "ldc1 $f0, 0x7FE8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "ldc1 $f0, -0x7FF0($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "lwc1 $f0, -0x7FE9($at)\n"
- "lw $t8, -0x7FE5($at)\n"
- "mthc1 $t8, $f0\n"
- "aui $at, $a0, 0x1\n"
- "lwc1 $f0, 0x7FE9($at)\n"
- "lw $t8, 0x7FED($at)\n"
- "mthc1 $t8, $f0\n"
- "aui $at, $a0, 0x1\n"
- "ldc1 $f0, 0x7FF0($at)\n"
- "aui $at, $a0, 0x1234\n"
- "ldc1 $f0, 0x5678($at)\n";
- DriverStr(expected, "LoadDFromOffset");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LoadQFromOffset) {
- __ LoadQFromOffset(mips::F0, mips::A0, 0);
- __ LoadQFromOffset(mips::F0, mips::A0, 1);
- __ LoadQFromOffset(mips::F0, mips::A0, 2);
- __ LoadQFromOffset(mips::F0, mips::A0, 4);
- __ LoadQFromOffset(mips::F0, mips::A0, 8);
- __ LoadQFromOffset(mips::F0, mips::A0, 511);
- __ LoadQFromOffset(mips::F0, mips::A0, 512);
- __ LoadQFromOffset(mips::F0, mips::A0, 513);
- __ LoadQFromOffset(mips::F0, mips::A0, 514);
- __ LoadQFromOffset(mips::F0, mips::A0, 516);
- __ LoadQFromOffset(mips::F0, mips::A0, 1022);
- __ LoadQFromOffset(mips::F0, mips::A0, 1024);
- __ LoadQFromOffset(mips::F0, mips::A0, 1025);
- __ LoadQFromOffset(mips::F0, mips::A0, 1026);
- __ LoadQFromOffset(mips::F0, mips::A0, 1028);
- __ LoadQFromOffset(mips::F0, mips::A0, 2044);
- __ LoadQFromOffset(mips::F0, mips::A0, 2048);
- __ LoadQFromOffset(mips::F0, mips::A0, 2049);
- __ LoadQFromOffset(mips::F0, mips::A0, 2050);
- __ LoadQFromOffset(mips::F0, mips::A0, 2052);
- __ LoadQFromOffset(mips::F0, mips::A0, 4088);
- __ LoadQFromOffset(mips::F0, mips::A0, 4096);
- __ LoadQFromOffset(mips::F0, mips::A0, 4097);
- __ LoadQFromOffset(mips::F0, mips::A0, 4098);
- __ LoadQFromOffset(mips::F0, mips::A0, 4100);
- __ LoadQFromOffset(mips::F0, mips::A0, 4104);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFC);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x8000);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x10000);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x12345678);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x12350078);
- __ LoadQFromOffset(mips::F0, mips::A0, -256);
- __ LoadQFromOffset(mips::F0, mips::A0, -511);
- __ LoadQFromOffset(mips::F0, mips::A0, -513);
- __ LoadQFromOffset(mips::F0, mips::A0, -1022);
- __ LoadQFromOffset(mips::F0, mips::A0, -1026);
- __ LoadQFromOffset(mips::F0, mips::A0, -2044);
- __ LoadQFromOffset(mips::F0, mips::A0, -2052);
- __ LoadQFromOffset(mips::F0, mips::A0, -4096);
- __ LoadQFromOffset(mips::F0, mips::A0, -4104);
- __ LoadQFromOffset(mips::F0, mips::A0, -32768);
- __ LoadQFromOffset(mips::F0, mips::A0, 0xABCDEF00);
- __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFFABCD);
-
- const char* expected =
- "ld.d $w0, 0($a0)\n"
- "ld.b $w0, 1($a0)\n"
- "ld.h $w0, 2($a0)\n"
- "ld.w $w0, 4($a0)\n"
- "ld.d $w0, 8($a0)\n"
- "ld.b $w0, 511($a0)\n"
- "ld.d $w0, 512($a0)\n"
- "addiu $at, $a0, 513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, 514($a0)\n"
- "ld.w $w0, 516($a0)\n"
- "ld.h $w0, 1022($a0)\n"
- "ld.d $w0, 1024($a0)\n"
- "addiu $at, $a0, 1025\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, 1028($a0)\n"
- "ld.w $w0, 2044($a0)\n"
- "ld.d $w0, 2048($a0)\n"
- "addiu $at, $a0, 2049\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 2050\n"
- "ld.h $w0, 0($at)\n"
- "addiu $at, $a0, 2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, 4088($a0)\n"
- "addiu $at, $a0, 4096\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, 4097\n"
- "ld.b $w0, 0($at)\n"
- "addiu $at, $a0, 4098\n"
- "ld.h $w0, 0($at)\n"
- "addiu $at, $a0, 4100\n"
- "ld.w $w0, 0($at)\n"
- "addiu $at, $a0, 4104\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FFC\n"
- "ld.w $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ld.d $w0, 8($at)\n"
- "aui $at, $a0, 0x1\n"
- "ld.d $w0, 0($at)\n"
- "aui $at, $a0, 0x1234\n"
- "addiu $at, $at, 0x6000\n"
- "ld.d $w0, -2440($at) # 0xF678\n"
- "aui $at, $a0, 0x1235\n"
- "ld.d $w0, 0x78($at)\n"
- "ld.d $w0, -256($a0)\n"
- "ld.b $w0, -511($a0)\n"
- "addiu $at, $a0, -513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, -1022($a0)\n"
- "addiu $at, $a0, -1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, -2044($a0)\n"
- "addiu $at, $a0, -2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, -4096($a0)\n"
- "addiu $at, $a0, -4104\n"
- "ld.d $w0, 0($at)\n"
- "addiu $at, $a0, -32768\n"
- "ld.d $w0, 0($at)\n"
- "aui $at, $a0, 0xABCE\n"
- "addiu $at, $at, -8192 # 0xE000\n"
- "ld.d $w0, 0xF00($at)\n"
- "aui $at, $a0, 0x8000\n"
- "addiu $at, $at, -21504 # 0xAC00\n"
- "ld.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "LoadQFromOffset");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StoreDToOffset) {
- __ StoreDToOffset(mips::F0, mips::A0, -0x8000);
- __ StoreDToOffset(mips::F0, mips::A0, +0);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FF8);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFB);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFC);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFF);
- __ StoreDToOffset(mips::F0, mips::A0, -0xFFF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x8008);
- __ StoreDToOffset(mips::F0, mips::A0, -0x8001);
- __ StoreDToOffset(mips::F0, mips::A0, +0x8000);
- __ StoreDToOffset(mips::F0, mips::A0, +0xFFF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FE8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF1);
- __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF1);
- __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF8);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FE8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FE9);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FE9);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FF0);
- __ StoreDToOffset(mips::F0, mips::A0, +0x12345678);
-
- const char* expected =
- "sdc1 $f0, -0x8000($a0)\n"
- "sdc1 $f0, 0($a0)\n"
- "sdc1 $f0, 0x7FF8($a0)\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, 0x7FFB($a0)\n"
- "sw $t8, 0x7FFF($a0)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, 4($at)\n"
- "sw $t8, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, 7($at)\n"
- "sw $t8, 11($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "sdc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "sdc1 $f0, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, -9($at)\n"
- "sw $t8, -5($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "sdc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "sdc1 $f0, 0x7FF8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "sdc1 $f0, -0x7FE8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "sdc1 $f0, 0x8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, 0xF($at)\n"
- "sw $t8, 0x13($at)\n"
- "aui $at, $a0, 0x1\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, -0xF($at)\n"
- "sw $t8, -0xB($at)\n"
- "aui $at, $a0, 0x1\n"
- "sdc1 $f0, -0x8($at)\n"
- "aui $at, $a0, 0x1\n"
- "sdc1 $f0, 0x7FE8($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "sdc1 $f0, -0x7FF0($at)\n"
- "aui $at, $a0, 0xFFFF\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, -0x7FE9($at)\n"
- "sw $t8, -0x7FE5($at)\n"
- "aui $at, $a0, 0x1\n"
- "mfhc1 $t8, $f0\n"
- "swc1 $f0, 0x7FE9($at)\n"
- "sw $t8, 0x7FED($at)\n"
- "aui $at, $a0, 0x1\n"
- "sdc1 $f0, 0x7FF0($at)\n"
- "aui $at, $a0, 0x1234\n"
- "sdc1 $f0, 0x5678($at)\n";
- DriverStr(expected, "StoreDToOffset");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StoreQToOffset) {
- __ StoreQToOffset(mips::F0, mips::A0, 0);
- __ StoreQToOffset(mips::F0, mips::A0, 1);
- __ StoreQToOffset(mips::F0, mips::A0, 2);
- __ StoreQToOffset(mips::F0, mips::A0, 4);
- __ StoreQToOffset(mips::F0, mips::A0, 8);
- __ StoreQToOffset(mips::F0, mips::A0, 511);
- __ StoreQToOffset(mips::F0, mips::A0, 512);
- __ StoreQToOffset(mips::F0, mips::A0, 513);
- __ StoreQToOffset(mips::F0, mips::A0, 514);
- __ StoreQToOffset(mips::F0, mips::A0, 516);
- __ StoreQToOffset(mips::F0, mips::A0, 1022);
- __ StoreQToOffset(mips::F0, mips::A0, 1024);
- __ StoreQToOffset(mips::F0, mips::A0, 1025);
- __ StoreQToOffset(mips::F0, mips::A0, 1026);
- __ StoreQToOffset(mips::F0, mips::A0, 1028);
- __ StoreQToOffset(mips::F0, mips::A0, 2044);
- __ StoreQToOffset(mips::F0, mips::A0, 2048);
- __ StoreQToOffset(mips::F0, mips::A0, 2049);
- __ StoreQToOffset(mips::F0, mips::A0, 2050);
- __ StoreQToOffset(mips::F0, mips::A0, 2052);
- __ StoreQToOffset(mips::F0, mips::A0, 4088);
- __ StoreQToOffset(mips::F0, mips::A0, 4096);
- __ StoreQToOffset(mips::F0, mips::A0, 4097);
- __ StoreQToOffset(mips::F0, mips::A0, 4098);
- __ StoreQToOffset(mips::F0, mips::A0, 4100);
- __ StoreQToOffset(mips::F0, mips::A0, 4104);
- __ StoreQToOffset(mips::F0, mips::A0, 0x7FFC);
- __ StoreQToOffset(mips::F0, mips::A0, 0x8000);
- __ StoreQToOffset(mips::F0, mips::A0, 0x10000);
- __ StoreQToOffset(mips::F0, mips::A0, 0x12345678);
- __ StoreQToOffset(mips::F0, mips::A0, 0x12350078);
- __ StoreQToOffset(mips::F0, mips::A0, -256);
- __ StoreQToOffset(mips::F0, mips::A0, -511);
- __ StoreQToOffset(mips::F0, mips::A0, -513);
- __ StoreQToOffset(mips::F0, mips::A0, -1022);
- __ StoreQToOffset(mips::F0, mips::A0, -1026);
- __ StoreQToOffset(mips::F0, mips::A0, -2044);
- __ StoreQToOffset(mips::F0, mips::A0, -2052);
- __ StoreQToOffset(mips::F0, mips::A0, -4096);
- __ StoreQToOffset(mips::F0, mips::A0, -4104);
- __ StoreQToOffset(mips::F0, mips::A0, -32768);
- __ StoreQToOffset(mips::F0, mips::A0, 0xABCDEF00);
- __ StoreQToOffset(mips::F0, mips::A0, 0x7FFFABCD);
-
- const char* expected =
- "st.d $w0, 0($a0)\n"
- "st.b $w0, 1($a0)\n"
- "st.h $w0, 2($a0)\n"
- "st.w $w0, 4($a0)\n"
- "st.d $w0, 8($a0)\n"
- "st.b $w0, 511($a0)\n"
- "st.d $w0, 512($a0)\n"
- "addiu $at, $a0, 513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, 514($a0)\n"
- "st.w $w0, 516($a0)\n"
- "st.h $w0, 1022($a0)\n"
- "st.d $w0, 1024($a0)\n"
- "addiu $at, $a0, 1025\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, 1028($a0)\n"
- "st.w $w0, 2044($a0)\n"
- "st.d $w0, 2048($a0)\n"
- "addiu $at, $a0, 2049\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 2050\n"
- "st.h $w0, 0($at)\n"
- "addiu $at, $a0, 2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, 4088($a0)\n"
- "addiu $at, $a0, 4096\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, 4097\n"
- "st.b $w0, 0($at)\n"
- "addiu $at, $a0, 4098\n"
- "st.h $w0, 0($at)\n"
- "addiu $at, $a0, 4100\n"
- "st.w $w0, 0($at)\n"
- "addiu $at, $a0, 4104\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FFC\n"
- "st.w $w0, 0($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "st.d $w0, 8($at)\n"
- "aui $at, $a0, 0x1\n"
- "st.d $w0, 0($at)\n"
- "aui $at, $a0, 0x1234\n"
- "addiu $at, $at, 0x6000\n"
- "st.d $w0, -2440($at) # 0xF678\n"
- "aui $at, $a0, 0x1235\n"
- "st.d $w0, 0x78($at)\n"
- "st.d $w0, -256($a0)\n"
- "st.b $w0, -511($a0)\n"
- "addiu $at, $a0, -513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, -1022($a0)\n"
- "addiu $at, $a0, -1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, -2044($a0)\n"
- "addiu $at, $a0, -2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, -4096($a0)\n"
- "addiu $at, $a0, -4104\n"
- "st.d $w0, 0($at)\n"
- "addiu $at, $a0, -32768\n"
- "st.d $w0, 0($at)\n"
- "aui $at, $a0, 0xABCE\n"
- "addiu $at, $at, -8192 # 0xE000\n"
- "st.d $w0, 0xF00($at)\n"
- "aui $at, $a0, 0x8000\n"
- "addiu $at, $at, -21504 # 0xAC00\n"
- "st.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "StoreQToOffset");
-}
-
-//////////////
-// BRANCHES //
-//////////////
-
-TEST_F(AssemblerMIPS32r6Test, Bc) {
- BranchHelper(&mips::MipsAssembler::Bc, "Bc", /* has_slot= */ false);
-}
-
-TEST_F(AssemblerMIPS32r6Test, Balc) {
- BranchHelper(&mips::MipsAssembler::Balc, "Balc", /* has_slot= */ false);
-}
-
-TEST_F(AssemblerMIPS32r6Test, Beqc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beqc, "Beqc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bnec) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bnec, "Bnec");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Beqzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqzc, "Beqzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bnezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnezc, "Bnezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bltzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltzc, "Bltzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgezc, "Bgezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Blezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blezc, "Blezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgtzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtzc, "Bgtzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bltc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltc, "Bltc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgec) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgec, "Bgec");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bltuc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltuc, "Bltuc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgeuc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeuc, "Bgeuc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bc1eqz) {
- BranchFpuCondHelper(&mips::MipsAssembler::Bc1eqz, "Bc1eqz");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bc1nez) {
- BranchFpuCondHelper(&mips::MipsAssembler::Bc1nez, "Bc1nez");
-}
-
-TEST_F(AssemblerMIPS32r6Test, B) {
- BranchHelper(&mips::MipsAssembler::B, "Bc", /* has_slot= */ false);
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bal) {
- BranchHelper(&mips::MipsAssembler::Bal, "Balc", /* has_slot= */ false);
-}
-
-TEST_F(AssemblerMIPS32r6Test, Beq) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beqc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bne) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bnec");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Beqz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bnez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bltz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Blez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blezc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgtz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Blt) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Bltc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bge) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bgec");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bltu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltuc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Bgeu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeuc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBc) {
- BranchHelper(&mips::MipsAssembler::Bc, "Bc", /* has_slot= */ false, /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBalc) {
- BranchHelper(&mips::MipsAssembler::Balc, "Balc", /* has_slot= */ false, /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBeqc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beqc, "Beqc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBnec) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bnec, "Bnec", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBeqzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqzc, "Beqzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBnezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnezc, "Bnezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBltzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltzc, "Bltzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgezc, "Bgezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBlezc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blezc, "Blezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgtzc) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtzc, "Bgtzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBltc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltc, "Bltc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgec) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgec, "Bgec", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBltuc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltuc, "Bltuc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgeuc) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeuc, "Bgeuc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBc1eqz) {
- BranchFpuCondHelper(&mips::MipsAssembler::Bc1eqz, "Bc1eqz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBc1nez) {
- BranchFpuCondHelper(&mips::MipsAssembler::Bc1nez, "Bc1nez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareB) {
- BranchHelper(&mips::MipsAssembler::B, "B", /* has_slot= */ true, /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBal) {
- BranchHelper(&mips::MipsAssembler::Bal, "Bal", /* has_slot= */ true, /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBeq) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBne) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBeqz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBnez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBltz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBlez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgtz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBlt) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Blt", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBge) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bge", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBltu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltu", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, BareBgeu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeu", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS32r6Test, LongBeqc) {
- mips::MipsLabel label;
- __ Beqc(mips::A0, mips::A1, &label);
- constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Beqc(mips::A2, mips::A3, &label);
-
- uint32_t offset_forward = 2 + kAdduCount1; // 2: account for auipc and jic.
- offset_forward <<= 2;
- offset_forward += (offset_forward & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(kAdduCount2 + 1); // 1: account for bnec.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "bnec $a0, $a1, 1f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "1:\n" <<
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
- "2:\n" <<
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
- "bnec $a2, $a3, 3f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "3:\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBeqc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LongBeqzc) {
- constexpr uint32_t kNopCount1 = (1u << 20) + 1;
- constexpr uint32_t kNopCount2 = (1u << 20) + 1;
- constexpr uint32_t kRequiredCapacity = (kNopCount1 + kNopCount2 + 6u) * 4u;
- ASSERT_LT(__ GetBuffer()->Capacity(), kRequiredCapacity);
- __ GetBuffer()->ExtendCapacity(kRequiredCapacity);
- mips::MipsLabel label;
- __ Beqzc(mips::A0, &label);
- for (uint32_t i = 0; i != kNopCount1; ++i) {
- __ Nop();
- }
- __ Bind(&label);
- for (uint32_t i = 0; i != kNopCount2; ++i) {
- __ Nop();
- }
- __ Beqzc(mips::A2, &label);
-
- uint32_t offset_forward = 2 + kNopCount1; // 2: account for auipc and jic.
- offset_forward <<= 2;
- offset_forward += (offset_forward & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(kNopCount2 + 1); // 1: account for bnezc.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- // Note, we're using the ".fill" directive to tell the assembler to generate many NOPs
- // instead of generating them ourselves in the source code. This saves test time.
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "bnezc $a0, 1f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "1:\n" <<
- ".fill 0x" << std::hex << kNopCount1 << " , 4, 0\n"
- "2:\n" <<
- ".fill 0x" << std::hex << kNopCount2 << " , 4, 0\n"
- "bnezc $a2, 3f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "3:\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBeqzc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LongBc) {
- constexpr uint32_t kNopCount1 = (1u << 25) + 1;
- constexpr uint32_t kNopCount2 = (1u << 25) + 1;
- constexpr uint32_t kRequiredCapacity = (kNopCount1 + kNopCount2 + 6u) * 4u;
- ASSERT_LT(__ GetBuffer()->Capacity(), kRequiredCapacity);
- __ GetBuffer()->ExtendCapacity(kRequiredCapacity);
- mips::MipsLabel label1, label2;
- __ Bc(&label1);
- for (uint32_t i = 0; i != kNopCount1; ++i) {
- __ Nop();
- }
- __ Bind(&label1);
- __ Bc(&label2);
- for (uint32_t i = 0; i != kNopCount2; ++i) {
- __ Nop();
- }
- __ Bind(&label2);
- __ Bc(&label1);
-
- uint32_t offset_forward1 = 2 + kNopCount1; // 2: account for auipc and jic.
- offset_forward1 <<= 2;
- offset_forward1 += (offset_forward1 & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_forward2 = 2 + kNopCount2; // 2: account for auipc and jic.
- offset_forward2 <<= 2;
- offset_forward2 += (offset_forward2 & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(2 + kNopCount2); // 2: account for auipc and jic.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- // Note, we're using the ".fill" directive to tell the assembler to generate many NOPs
- // instead of generating them ourselves in the source code. This saves a few minutes
- // of test time.
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward1) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward1) << "\n"
- ".fill 0x" << std::hex << kNopCount1 << " , 4, 0\n"
- "1:\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward2) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward2) << "\n"
- ".fill 0x" << std::hex << kNopCount2 << " , 4, 0\n"
- "2:\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBc");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ImpossibleReordering) {
- mips::MipsLabel label;
- __ SetReorder(true);
- __ Bind(&label);
-
- __ CmpLtD(mips::F0, mips::F2, mips::F4);
- __ Bc1nez(mips::F0, &label); // F0 dependency.
-
- __ MulD(mips::F10, mips::F2, mips::F4);
- __ Bc1eqz(mips::F10, &label); // F10 dependency.
-
- std::string expected =
- ".set noreorder\n"
- "1:\n"
-
- "cmp.lt.d $f0, $f2, $f4\n"
- "bc1nez $f0, 1b\n"
- "nop\n"
-
- "mul.d $f10, $f2, $f4\n"
- "bc1eqz $f10, 1b\n"
- "nop\n";
- DriverStr(expected, "ImpossibleReordering");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Reordering) {
- mips::MipsLabel label;
- __ SetReorder(true);
- __ Bind(&label);
-
- __ CmpLtD(mips::F0, mips::F2, mips::F4);
- __ Bc1nez(mips::F2, &label);
-
- __ MulD(mips::F0, mips::F2, mips::F4);
- __ Bc1eqz(mips::F4, &label);
-
- std::string expected =
- ".set noreorder\n"
- "1:\n"
-
- "bc1nez $f2, 1b\n"
- "cmp.lt.d $f0, $f2, $f4\n"
-
- "bc1eqz $f4, 1b\n"
- "mul.d $f0, $f2, $f4\n";
- DriverStr(expected, "Reordering");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SetReorder) {
- mips::MipsLabel label1, label2, label3, label4;
-
- __ SetReorder(true);
- __ Bind(&label1);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bc1nez(mips::F0, &label1);
-
- __ SetReorder(false);
- __ Bind(&label2);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bc1nez(mips::F0, &label2);
-
- __ SetReorder(true);
- __ Bind(&label3);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bc1eqz(mips::F0, &label3);
-
- __ SetReorder(false);
- __ Bind(&label4);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bc1eqz(mips::F0, &label4);
-
- std::string expected =
- ".set noreorder\n"
- "1:\n"
- "bc1nez $f0, 1b\n"
- "addu $t0, $t1, $t2\n"
-
- "2:\n"
- "addu $t0, $t1, $t2\n"
- "bc1nez $f0, 2b\n"
- "nop\n"
-
- "3:\n"
- "bc1eqz $f0, 3b\n"
- "addu $t0, $t1, $t2\n"
-
- "4:\n"
- "addu $t0, $t1, $t2\n"
- "bc1eqz $f0, 4b\n"
- "nop\n";
- DriverStr(expected, "SetReorder");
-}
-
-TEST_F(AssemblerMIPS32r6Test, ReorderPatchedInstruction) {
- __ SetReorder(true);
- mips::MipsLabel label1, label2;
- mips::MipsLabel patcher_label1, patcher_label2, patcher_label3, patcher_label4, patcher_label5;
- __ Lw(mips::V0, mips::A0, 0x5678, &patcher_label1);
- __ Bc1eqz(mips::F0, &label1);
- constexpr uint32_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label1);
- __ Sw(mips::V0, mips::A0, 0x5678, &patcher_label2);
- __ Bc1nez(mips::F2, &label2);
- constexpr uint32_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label2);
- __ Addiu(mips::V0, mips::A0, 0x5678, &patcher_label3);
- __ Bc1eqz(mips::F4, &label1);
- __ Lw(mips::V0, mips::A0, 0x5678, &patcher_label4);
- __ Jalr(mips::T9);
- __ Sw(mips::V0, mips::A0, 0x5678, &patcher_label5);
- __ Bltc(mips::V0, mips::V1, &label2);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n"
- "bc1eqz $f0, 1f\n"
- "lw $v0, 0x5678($a0)\n" +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n"
- "bc1nez $f2, 2f\n"
- "sw $v0, 0x5678($a0)\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- "2:\n"
- "bc1eqz $f4, 1b\n"
- "addiu $v0, $a0, 0x5678\n"
- "jalr $t9\n"
- "lw $v0, 0x5678($a0)\n"
- "sw $v0, 0x5678($a0)\n"
- "bltc $v0, $v1, 2b\n"
- "nop\n"
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, "ReorderPatchedInstruction");
- EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 1 * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + 3) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label3), (kAdduCount1 + kAdduCount2 + 5) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label4), (kAdduCount1 + kAdduCount2 + 7) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label5), (kAdduCount1 + kAdduCount2 + 8) * 4u);
-}
-
-TEST_F(AssemblerMIPS32r6Test, LongBranchReorder) {
- mips::MipsLabel label, patcher_label1, patcher_label2;
- __ SetReorder(true);
- __ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label1);
- __ Bc1nez(mips::F0, &label);
- constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label2);
- __ Bc1eqz(mips::F0, &label);
-
- uint32_t offset_forward = 2 + kAdduCount1; // 2: account for auipc and jic.
- offset_forward <<= 2;
- offset_forward += (offset_forward & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(kAdduCount2 + 2); // 2: account for subu and bc1nez.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "addiu $t0, $t1, 0x5678\n"
- "bc1eqz $f0, 1f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "1:\n" <<
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
- "2:\n" <<
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
- "addiu $t0, $t1, 0x5678\n"
- "bc1nez $f0, 3f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "3:\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBranchReorder");
- EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 0 * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + kAdduCount2 + 4) * 4u);
-}
-
-///////////////////////
-// Loading Constants //
-///////////////////////
-
-TEST_F(AssemblerMIPS32r6Test, LoadFarthestNearLabelAddress) {
- mips::MipsLabel label;
- __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
- constexpr size_t kAdduCount = 0x3FFDE;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- "lapc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n";
- DriverStr(expected, "LoadFarthestNearLabelAddress");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LoadNearestFarLabelAddress) {
- mips::MipsLabel label;
- __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
- constexpr size_t kAdduCount = 0x3FFDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "addiu $v0, $at, %lo(2f - 1b)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n";
- DriverStr(expected, "LoadNearestFarLabelAddress");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LoadFarthestNearLiteral) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips::V0, mips::ZERO, literal);
- constexpr size_t kAdduCount = 0x3FFDE;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
-
- std::string expected =
- "lwpc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadFarthestNearLiteral");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LoadNearestFarLiteral) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips::V0, mips::ZERO, literal);
- constexpr size_t kAdduCount = 0x3FFDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "lw $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadNearestFarLiteral");
-}
-
-// MSA instructions.
-
-TEST_F(AssemblerMIPS32r6Test, AndV) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::AndV, "and.v ${reg1}, ${reg2}, ${reg3}"), "and.v");
-}
-
-TEST_F(AssemblerMIPS32r6Test, OrV) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::OrV, "or.v ${reg1}, ${reg2}, ${reg3}"), "or.v");
-}
-
-TEST_F(AssemblerMIPS32r6Test, NorV) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::NorV, "nor.v ${reg1}, ${reg2}, ${reg3}"), "nor.v");
-}
-
-TEST_F(AssemblerMIPS32r6Test, XorV) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::XorV, "xor.v ${reg1}, ${reg2}, ${reg3}"), "xor.v");
-}
-
-TEST_F(AssemblerMIPS32r6Test, AddvB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::AddvB, "addv.b ${reg1}, ${reg2}, ${reg3}"), "addv.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, AddvH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::AddvH, "addv.h ${reg1}, ${reg2}, ${reg3}"), "addv.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, AddvW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::AddvW, "addv.w ${reg1}, ${reg2}, ${reg3}"), "addv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, AddvD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::AddvD, "addv.d ${reg1}, ${reg2}, ${reg3}"), "addv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SubvB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SubvB, "subv.b ${reg1}, ${reg2}, ${reg3}"), "subv.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SubvH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SubvH, "subv.h ${reg1}, ${reg2}, ${reg3}"), "subv.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SubvW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SubvW, "subv.w ${reg1}, ${reg2}, ${reg3}"), "subv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SubvD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SubvD, "subv.d ${reg1}, ${reg2}, ${reg3}"), "subv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_sB, "asub_s.b ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_sH, "asub_s.h ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_sW, "asub_s.w ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_sD, "asub_s.d ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_uB, "asub_u.b ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_uH, "asub_u.h ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_uW, "asub_u.w ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Asub_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Asub_uD, "asub_u.d ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MulvB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MulvB, "mulv.b ${reg1}, ${reg2}, ${reg3}"), "mulv.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MulvH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MulvH, "mulv.h ${reg1}, ${reg2}, ${reg3}"), "mulv.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MulvW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MulvW, "mulv.w ${reg1}, ${reg2}, ${reg3}"), "mulv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MulvD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MulvD, "mulv.d ${reg1}, ${reg2}, ${reg3}"), "mulv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_sB, "div_s.b ${reg1}, ${reg2}, ${reg3}"),
- "div_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_sH, "div_s.h ${reg1}, ${reg2}, ${reg3}"),
- "div_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_sW, "div_s.w ${reg1}, ${reg2}, ${reg3}"),
- "div_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_sD, "div_s.d ${reg1}, ${reg2}, ${reg3}"),
- "div_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_uB, "div_u.b ${reg1}, ${reg2}, ${reg3}"),
- "div_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_uH, "div_u.h ${reg1}, ${reg2}, ${reg3}"),
- "div_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_uW, "div_u.w ${reg1}, ${reg2}, ${reg3}"),
- "div_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Div_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Div_uD, "div_u.d ${reg1}, ${reg2}, ${reg3}"),
- "div_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_sB, "mod_s.b ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_sH, "mod_s.h ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_sW, "mod_s.w ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_sD, "mod_s.d ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_uB, "mod_u.b ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_uH, "mod_u.h ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_uW, "mod_u.w ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Mod_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Mod_uD, "mod_u.d ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Add_aB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Add_aB, "add_a.b ${reg1}, ${reg2}, ${reg3}"),
- "add_a.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Add_aH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Add_aH, "add_a.h ${reg1}, ${reg2}, ${reg3}"),
- "add_a.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Add_aW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Add_aW, "add_a.w ${reg1}, ${reg2}, ${reg3}"),
- "add_a.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Add_aD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Add_aD, "add_a.d ${reg1}, ${reg2}, ${reg3}"),
- "add_a.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_sB, "ave_s.b ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_sH, "ave_s.h ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_sW, "ave_s.w ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_sD, "ave_s.d ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_uB, "ave_u.b ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_uH, "ave_u.h ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_uW, "ave_u.w ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ave_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Ave_uD, "ave_u.d ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_sB, "aver_s.b ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_sH, "aver_s.h ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_sW, "aver_s.w ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_sD, "aver_s.d ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_uB, "aver_u.b ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_uH, "aver_u.h ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_uW, "aver_u.w ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Aver_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Aver_uD, "aver_u.d ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_sB, "max_s.b ${reg1}, ${reg2}, ${reg3}"),
- "max_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_sH, "max_s.h ${reg1}, ${reg2}, ${reg3}"),
- "max_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_sW, "max_s.w ${reg1}, ${reg2}, ${reg3}"),
- "max_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_sD, "max_s.d ${reg1}, ${reg2}, ${reg3}"),
- "max_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_uB, "max_u.b ${reg1}, ${reg2}, ${reg3}"),
- "max_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_uH, "max_u.h ${reg1}, ${reg2}, ${reg3}"),
- "max_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_uW, "max_u.w ${reg1}, ${reg2}, ${reg3}"),
- "max_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Max_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Max_uD, "max_u.d ${reg1}, ${reg2}, ${reg3}"),
- "max_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_sB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_sB, "min_s.b ${reg1}, ${reg2}, ${reg3}"),
- "min_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_sH, "min_s.h ${reg1}, ${reg2}, ${reg3}"),
- "min_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_sW, "min_s.w ${reg1}, ${reg2}, ${reg3}"),
- "min_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_sD, "min_s.d ${reg1}, ${reg2}, ${reg3}"),
- "min_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_uB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_uB, "min_u.b ${reg1}, ${reg2}, ${reg3}"),
- "min_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_uH, "min_u.h ${reg1}, ${reg2}, ${reg3}"),
- "min_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_uW, "min_u.w ${reg1}, ${reg2}, ${reg3}"),
- "min_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Min_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Min_uD, "min_u.d ${reg1}, ${reg2}, ${reg3}"),
- "min_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FaddW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FaddW, "fadd.w ${reg1}, ${reg2}, ${reg3}"), "fadd.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FaddD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FaddD, "fadd.d ${reg1}, ${reg2}, ${reg3}"), "fadd.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FsubW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FsubW, "fsub.w ${reg1}, ${reg2}, ${reg3}"), "fsub.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FsubD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FsubD, "fsub.d ${reg1}, ${reg2}, ${reg3}"), "fsub.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmulW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmulW, "fmul.w ${reg1}, ${reg2}, ${reg3}"), "fmul.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmulD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmulD, "fmul.d ${reg1}, ${reg2}, ${reg3}"), "fmul.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FdivW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FdivW, "fdiv.w ${reg1}, ${reg2}, ${reg3}"), "fdiv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FdivD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FdivD, "fdiv.d ${reg1}, ${reg2}, ${reg3}"), "fdiv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmaxW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmaxW, "fmax.w ${reg1}, ${reg2}, ${reg3}"), "fmax.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmaxD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmaxD, "fmax.d ${reg1}, ${reg2}, ${reg3}"), "fmax.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FminW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FminW, "fmin.w ${reg1}, ${reg2}, ${reg3}"), "fmin.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FminD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FminD, "fmin.d ${reg1}, ${reg2}, ${reg3}"), "fmin.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ffint_sW) {
- DriverStr(RepeatVV(&mips::MipsAssembler::Ffint_sW, "ffint_s.w ${reg1}, ${reg2}"), "ffint_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ffint_sD) {
- DriverStr(RepeatVV(&mips::MipsAssembler::Ffint_sD, "ffint_s.d ${reg1}, ${reg2}"), "ffint_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ftint_sW) {
- DriverStr(RepeatVV(&mips::MipsAssembler::Ftint_sW, "ftint_s.w ${reg1}, ${reg2}"), "ftint_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Ftint_sD) {
- DriverStr(RepeatVV(&mips::MipsAssembler::Ftint_sD, "ftint_s.d ${reg1}, ${reg2}"), "ftint_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SllB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SllB, "sll.b ${reg1}, ${reg2}, ${reg3}"), "sll.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SllH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SllH, "sll.h ${reg1}, ${reg2}, ${reg3}"), "sll.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SllW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SllW, "sll.w ${reg1}, ${reg2}, ${reg3}"), "sll.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SllD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SllD, "sll.d ${reg1}, ${reg2}, ${reg3}"), "sll.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SraB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SraB, "sra.b ${reg1}, ${reg2}, ${reg3}"), "sra.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SraH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SraH, "sra.h ${reg1}, ${reg2}, ${reg3}"), "sra.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SraW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SraW, "sra.w ${reg1}, ${reg2}, ${reg3}"), "sra.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SraD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SraD, "sra.d ${reg1}, ${reg2}, ${reg3}"), "sra.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SrlB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SrlB, "srl.b ${reg1}, ${reg2}, ${reg3}"), "srl.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SrlH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SrlH, "srl.h ${reg1}, ${reg2}, ${reg3}"), "srl.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SrlW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SrlW, "srl.w ${reg1}, ${reg2}, ${reg3}"), "srl.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SrlD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::SrlD, "srl.d ${reg1}, ${reg2}, ${reg3}"), "srl.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SlliB) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SlliB, 3, "slli.b ${reg1}, ${reg2}, {imm}"), "slli.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SlliH) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SlliH, 4, "slli.h ${reg1}, ${reg2}, {imm}"), "slli.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SlliW) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SlliW, 5, "slli.w ${reg1}, ${reg2}, {imm}"), "slli.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SlliD) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SlliD, 6, "slli.d ${reg1}, ${reg2}, {imm}"), "slli.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MoveV) {
- DriverStr(RepeatVV(&mips::MipsAssembler::MoveV, "move.v ${reg1}, ${reg2}"), "move.v");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SplatiB) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SplatiB, 4, "splati.b ${reg1}, ${reg2}[{imm}]"),
- "splati.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SplatiH) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SplatiH, 3, "splati.h ${reg1}, ${reg2}[{imm}]"),
- "splati.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SplatiW) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SplatiW, 2, "splati.w ${reg1}, ${reg2}[{imm}]"),
- "splati.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, SplatiD) {
- DriverStr(RepeatVVIb(&mips::MipsAssembler::SplatiD, 1, "splati.d ${reg1}, ${reg2}[{imm}]"),
- "splati.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Copy_sB) {
- DriverStr(RepeatRVIb(&mips::MipsAssembler::Copy_sB, 4, "copy_s.b ${reg1}, ${reg2}[{imm}]"),
- "copy_s.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Copy_sH) {
- DriverStr(RepeatRVIb(&mips::MipsAssembler::Copy_sH, 3, "copy_s.h ${reg1}, ${reg2}[{imm}]"),
- "copy_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Copy_sW) {
- DriverStr(RepeatRVIb(&mips::MipsAssembler::Copy_sW, 2, "copy_s.w ${reg1}, ${reg2}[{imm}]"),
- "copy_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Copy_uB) {
- DriverStr(RepeatRVIb(&mips::MipsAssembler::Copy_uB, 4, "copy_u.b ${reg1}, ${reg2}[{imm}]"),
- "copy_u.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Copy_uH) {
- DriverStr(RepeatRVIb(&mips::MipsAssembler::Copy_uH, 3, "copy_u.h ${reg1}, ${reg2}[{imm}]"),
- "copy_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, InsertB) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::InsertB, 4, "insert.b ${reg1}[{imm}], ${reg2}"),
- "insert.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, InsertH) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::InsertH, 3, "insert.h ${reg1}[{imm}], ${reg2}"),
- "insert.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, InsertW) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::InsertW, 2, "insert.w ${reg1}[{imm}], ${reg2}"),
- "insert.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FillB) {
- DriverStr(RepeatVR(&mips::MipsAssembler::FillB, "fill.b ${reg1}, ${reg2}"), "fill.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FillH) {
- DriverStr(RepeatVR(&mips::MipsAssembler::FillH, "fill.h ${reg1}, ${reg2}"), "fill.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FillW) {
- DriverStr(RepeatVR(&mips::MipsAssembler::FillW, "fill.w ${reg1}, ${reg2}"), "fill.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, PcntB) {
- DriverStr(RepeatVV(&mips::MipsAssembler::PcntB, "pcnt.b ${reg1}, ${reg2}"), "pcnt.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, PcntH) {
- DriverStr(RepeatVV(&mips::MipsAssembler::PcntH, "pcnt.h ${reg1}, ${reg2}"), "pcnt.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, PcntW) {
- DriverStr(RepeatVV(&mips::MipsAssembler::PcntW, "pcnt.w ${reg1}, ${reg2}"), "pcnt.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, PcntD) {
- DriverStr(RepeatVV(&mips::MipsAssembler::PcntD, "pcnt.d ${reg1}, ${reg2}"), "pcnt.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdiB) {
- DriverStr(RepeatVIb(&mips::MipsAssembler::LdiB, -8, "ldi.b ${reg}, {imm}"), "ldi.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdiH) {
- DriverStr(RepeatVIb(&mips::MipsAssembler::LdiH, -10, "ldi.h ${reg}, {imm}"), "ldi.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdiW) {
- DriverStr(RepeatVIb(&mips::MipsAssembler::LdiW, -10, "ldi.w ${reg}, {imm}"), "ldi.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdiD) {
- DriverStr(RepeatVIb(&mips::MipsAssembler::LdiD, -10, "ldi.d ${reg}, {imm}"), "ldi.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdB) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::LdB, -10, "ld.b ${reg1}, {imm}(${reg2})"), "ld.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdH) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::LdH, -10, "ld.h ${reg1}, {imm}(${reg2})", 0, 2),
- "ld.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdW) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::LdW, -10, "ld.w ${reg1}, {imm}(${reg2})", 0, 4),
- "ld.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, LdD) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::LdD, -10, "ld.d ${reg1}, {imm}(${reg2})", 0, 8),
- "ld.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StB) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::StB, -10, "st.b ${reg1}, {imm}(${reg2})"), "st.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StH) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::StH, -10, "st.h ${reg1}, {imm}(${reg2})", 0, 2),
- "st.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StW) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::StW, -10, "st.w ${reg1}, {imm}(${reg2})", 0, 4),
- "st.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, StD) {
- DriverStr(RepeatVRIb(&mips::MipsAssembler::StD, -10, "st.d ${reg1}, {imm}(${reg2})", 0, 8),
- "st.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvlB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvlB, "ilvl.b ${reg1}, ${reg2}, ${reg3}"), "ilvl.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvlH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvlH, "ilvl.h ${reg1}, ${reg2}, ${reg3}"), "ilvl.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvlW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvlW, "ilvl.w ${reg1}, ${reg2}, ${reg3}"), "ilvl.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvlD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvlD, "ilvl.d ${reg1}, ${reg2}, ${reg3}"), "ilvl.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvrB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvrB, "ilvr.b ${reg1}, ${reg2}, ${reg3}"), "ilvr.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvrH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvrH, "ilvr.h ${reg1}, ${reg2}, ${reg3}"), "ilvr.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvrW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvrW, "ilvr.w ${reg1}, ${reg2}, ${reg3}"), "ilvr.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvrD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvrD, "ilvr.d ${reg1}, ${reg2}, ${reg3}"), "ilvr.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvevB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvevB, "ilvev.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvevH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvevH, "ilvev.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvevW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvevW, "ilvev.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvevD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvevD, "ilvev.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvodB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvodB, "ilvod.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvodH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvodH, "ilvod.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvodW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvodW, "ilvod.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, IlvodD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::IlvodD, "ilvod.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaddvB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MaddvB, "maddv.b ${reg1}, ${reg2}, ${reg3}"),
- "maddv.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaddvH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MaddvH, "maddv.h ${reg1}, ${reg2}, ${reg3}"),
- "maddv.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaddvW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MaddvW, "maddv.w ${reg1}, ${reg2}, ${reg3}"),
- "maddv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MaddvD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MaddvD, "maddv.d ${reg1}, ${reg2}, ${reg3}"),
- "maddv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_sH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_sH, "hadd_s.h ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_sW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_sW, "hadd_s.w ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_sD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_sD, "hadd_s.d ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_uH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_uH, "hadd_u.h ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_uW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_uW, "hadd_u.w ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, Hadd_uD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::Hadd_uD, "hadd_u.d ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MsubvB) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MsubvB, "msubv.b ${reg1}, ${reg2}, ${reg3}"),
- "msubv.b");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MsubvH) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MsubvH, "msubv.h ${reg1}, ${reg2}, ${reg3}"),
- "msubv.h");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MsubvW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MsubvW, "msubv.w ${reg1}, ${reg2}, ${reg3}"),
- "msubv.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, MsubvD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::MsubvD, "msubv.d ${reg1}, ${reg2}, ${reg3}"),
- "msubv.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmaddW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmaddW, "fmadd.w ${reg1}, ${reg2}, ${reg3}"),
- "fmadd.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmaddD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmaddD, "fmadd.d ${reg1}, ${reg2}, ${reg3}"),
- "fmadd.d");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmsubW) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmsubW, "fmsub.w ${reg1}, ${reg2}, ${reg3}"),
- "fmsub.w");
-}
-
-TEST_F(AssemblerMIPS32r6Test, FmsubD) {
- DriverStr(RepeatVVV(&mips::MipsAssembler::FmsubD, "fmsub.d ${reg1}, ${reg2}, ${reg3}"),
- "fmsub.d");
-}
-
-#undef __
-
-} // namespace art
diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc
deleted file mode 100644
index c0894d3..0000000
--- a/compiler/utils/mips/assembler_mips_test.cc
+++ /dev/null
@@ -1,3046 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "assembler_mips.h"
-
-#include <map>
-
-#include "base/stl_util.h"
-#include "utils/assembler_test.h"
-
-#define __ GetAssembler()->
-
-namespace art {
-
-struct MIPSCpuRegisterCompare {
- bool operator()(const mips::Register& a, const mips::Register& b) const {
- return a < b;
- }
-};
-
-class AssemblerMIPSTest : public AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t> {
- public:
- using Base = AssemblerTest<mips::MipsAssembler,
- mips::MipsLabel,
- mips::Register,
- mips::FRegister,
- uint32_t>;
-
- // These tests were taking too long, so we hide the DriverStr() from AssemblerTest<>
- // and reimplement it without the verification against `assembly_string`. b/73903608
- void DriverStr(const std::string& assembly_string ATTRIBUTE_UNUSED,
- const std::string& test_name ATTRIBUTE_UNUSED) {
- GetAssembler()->FinalizeCode();
- std::vector<uint8_t> data(GetAssembler()->CodeSize());
- MemoryRegion code(data.data(), data.size());
- GetAssembler()->FinalizeInstructions(code);
- }
-
- protected:
- // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
- std::string GetArchitectureString() override {
- return "mips";
- }
-
- std::string GetAssemblerParameters() override {
- return " --no-warn -32 -march=mips32r2";
- }
-
- std::string GetDisassembleParameters() override {
- return " -D -bbinary -mmips:isa32r2";
- }
-
- void SetUpHelpers() override {
- if (registers_.size() == 0) {
- registers_.push_back(new mips::Register(mips::ZERO));
- registers_.push_back(new mips::Register(mips::AT));
- registers_.push_back(new mips::Register(mips::V0));
- registers_.push_back(new mips::Register(mips::V1));
- registers_.push_back(new mips::Register(mips::A0));
- registers_.push_back(new mips::Register(mips::A1));
- registers_.push_back(new mips::Register(mips::A2));
- registers_.push_back(new mips::Register(mips::A3));
- registers_.push_back(new mips::Register(mips::T0));
- registers_.push_back(new mips::Register(mips::T1));
- registers_.push_back(new mips::Register(mips::T2));
- registers_.push_back(new mips::Register(mips::T3));
- registers_.push_back(new mips::Register(mips::T4));
- registers_.push_back(new mips::Register(mips::T5));
- registers_.push_back(new mips::Register(mips::T6));
- registers_.push_back(new mips::Register(mips::T7));
- registers_.push_back(new mips::Register(mips::S0));
- registers_.push_back(new mips::Register(mips::S1));
- registers_.push_back(new mips::Register(mips::S2));
- registers_.push_back(new mips::Register(mips::S3));
- registers_.push_back(new mips::Register(mips::S4));
- registers_.push_back(new mips::Register(mips::S5));
- registers_.push_back(new mips::Register(mips::S6));
- registers_.push_back(new mips::Register(mips::S7));
- registers_.push_back(new mips::Register(mips::T8));
- registers_.push_back(new mips::Register(mips::T9));
- registers_.push_back(new mips::Register(mips::K0));
- registers_.push_back(new mips::Register(mips::K1));
- registers_.push_back(new mips::Register(mips::GP));
- registers_.push_back(new mips::Register(mips::SP));
- registers_.push_back(new mips::Register(mips::FP));
- registers_.push_back(new mips::Register(mips::RA));
-
- secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
- secondary_register_names_.emplace(mips::Register(mips::AT), "at");
- secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
- secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
- secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
- secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
- secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
- secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
- secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
- secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
- secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
- secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
- secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
- secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
- secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
- secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
- secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
- secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
- secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
- secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
- secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
- secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
- secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
- secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
- secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
- secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
- secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
- secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
- secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
- secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
- secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
- secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
-
- fp_registers_.push_back(new mips::FRegister(mips::F0));
- fp_registers_.push_back(new mips::FRegister(mips::F1));
- fp_registers_.push_back(new mips::FRegister(mips::F2));
- fp_registers_.push_back(new mips::FRegister(mips::F3));
- fp_registers_.push_back(new mips::FRegister(mips::F4));
- fp_registers_.push_back(new mips::FRegister(mips::F5));
- fp_registers_.push_back(new mips::FRegister(mips::F6));
- fp_registers_.push_back(new mips::FRegister(mips::F7));
- fp_registers_.push_back(new mips::FRegister(mips::F8));
- fp_registers_.push_back(new mips::FRegister(mips::F9));
- fp_registers_.push_back(new mips::FRegister(mips::F10));
- fp_registers_.push_back(new mips::FRegister(mips::F11));
- fp_registers_.push_back(new mips::FRegister(mips::F12));
- fp_registers_.push_back(new mips::FRegister(mips::F13));
- fp_registers_.push_back(new mips::FRegister(mips::F14));
- fp_registers_.push_back(new mips::FRegister(mips::F15));
- fp_registers_.push_back(new mips::FRegister(mips::F16));
- fp_registers_.push_back(new mips::FRegister(mips::F17));
- fp_registers_.push_back(new mips::FRegister(mips::F18));
- fp_registers_.push_back(new mips::FRegister(mips::F19));
- fp_registers_.push_back(new mips::FRegister(mips::F20));
- fp_registers_.push_back(new mips::FRegister(mips::F21));
- fp_registers_.push_back(new mips::FRegister(mips::F22));
- fp_registers_.push_back(new mips::FRegister(mips::F23));
- fp_registers_.push_back(new mips::FRegister(mips::F24));
- fp_registers_.push_back(new mips::FRegister(mips::F25));
- fp_registers_.push_back(new mips::FRegister(mips::F26));
- fp_registers_.push_back(new mips::FRegister(mips::F27));
- fp_registers_.push_back(new mips::FRegister(mips::F28));
- fp_registers_.push_back(new mips::FRegister(mips::F29));
- fp_registers_.push_back(new mips::FRegister(mips::F30));
- fp_registers_.push_back(new mips::FRegister(mips::F31));
- }
- }
-
- void TearDown() override {
- AssemblerTest::TearDown();
- STLDeleteElements(®isters_);
- STLDeleteElements(&fp_registers_);
- }
-
- std::vector<mips::MipsLabel> GetAddresses() override {
- UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
- UNREACHABLE();
- }
-
- std::vector<mips::Register*> GetRegisters() override {
- return registers_;
- }
-
- std::vector<mips::FRegister*> GetFPRegisters() override {
- return fp_registers_;
- }
-
- uint32_t CreateImmediate(int64_t imm_value) override {
- return imm_value;
- }
-
- std::string GetSecondaryRegisterName(const mips::Register& reg) override {
- CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
- return secondary_register_names_[reg];
- }
-
- std::string RepeatInsn(size_t count, const std::string& insn) {
- std::string result;
- for (; count != 0u; --count) {
- result += insn;
- }
- return result;
- }
-
- void BranchHelper(void (mips::MipsAssembler::*f)(mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label1, label2;
- (Base::GetAssembler()->*f)(&label1, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label1);
- (Base::GetAssembler()->*f)(&label2, is_bare);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label2);
- (Base::GetAssembler()->*f)(&label1, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- instr_name + " 2f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- "2:\n" +
- instr_name + " 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondOneRegHelper(void (mips::MipsAssembler::*f)(mips::Register,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(mips::A0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(mips::A1, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a1, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register,
- mips::Register,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(mips::A2, mips::A3, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, $a1, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a2, $a3, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchFpuCondCodeHelper(void (mips::MipsAssembler::*f)(int,
- mips::MipsLabel*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- __ SetReorder(false);
- mips::MipsLabel label;
- (Base::GetAssembler()->*f)(0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- (Base::GetAssembler()->*f)(7, &label, is_bare);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $fcc0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $fcc7, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- private:
- std::vector<mips::Register*> registers_;
- std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
-
- std::vector<mips::FRegister*> fp_registers_;
-};
-
-
-TEST_F(AssemblerMIPSTest, Toolchain) {
- EXPECT_TRUE(CheckTools());
-}
-
-TEST_F(AssemblerMIPSTest, Addu) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Addu, "addu ${reg1}, ${reg2}, ${reg3}"), "Addu");
-}
-
-TEST_F(AssemblerMIPSTest, Addiu) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Addiu, -16, "addiu ${reg1}, ${reg2}, {imm}"), "Addiu");
-}
-
-TEST_F(AssemblerMIPSTest, Subu) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Subu, "subu ${reg1}, ${reg2}, ${reg3}"), "Subu");
-}
-
-TEST_F(AssemblerMIPSTest, MultR2) {
- DriverStr(RepeatRR(&mips::MipsAssembler::MultR2, "mult ${reg1}, ${reg2}"), "MultR2");
-}
-
-TEST_F(AssemblerMIPSTest, MultuR2) {
- DriverStr(RepeatRR(&mips::MipsAssembler::MultuR2, "multu ${reg1}, ${reg2}"), "MultuR2");
-}
-
-TEST_F(AssemblerMIPSTest, DivR2Basic) {
- DriverStr(RepeatRR(&mips::MipsAssembler::DivR2, "div $zero, ${reg1}, ${reg2}"), "DivR2Basic");
-}
-
-TEST_F(AssemblerMIPSTest, DivuR2Basic) {
- DriverStr(RepeatRR(&mips::MipsAssembler::DivuR2, "divu $zero, ${reg1}, ${reg2}"), "DivuR2Basic");
-}
-
-TEST_F(AssemblerMIPSTest, MulR2) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::MulR2, "mul ${reg1}, ${reg2}, ${reg3}"), "MulR2");
-}
-
-TEST_F(AssemblerMIPSTest, DivR2) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::DivR2, "div $zero, ${reg2}, ${reg3}\nmflo ${reg1}"),
- "DivR2");
-}
-
-TEST_F(AssemblerMIPSTest, ModR2) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::ModR2, "div $zero, ${reg2}, ${reg3}\nmfhi ${reg1}"),
- "ModR2");
-}
-
-TEST_F(AssemblerMIPSTest, DivuR2) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::DivuR2, "divu $zero, ${reg2}, ${reg3}\nmflo ${reg1}"),
- "DivuR2");
-}
-
-TEST_F(AssemblerMIPSTest, ModuR2) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::ModuR2, "divu $zero, ${reg2}, ${reg3}\nmfhi ${reg1}"),
- "ModuR2");
-}
-
-TEST_F(AssemblerMIPSTest, And) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::And, "and ${reg1}, ${reg2}, ${reg3}"), "And");
-}
-
-TEST_F(AssemblerMIPSTest, Andi) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Andi, 16, "andi ${reg1}, ${reg2}, {imm}"), "Andi");
-}
-
-TEST_F(AssemblerMIPSTest, Or) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Or, "or ${reg1}, ${reg2}, ${reg3}"), "Or");
-}
-
-TEST_F(AssemblerMIPSTest, Ori) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Ori, 16, "ori ${reg1}, ${reg2}, {imm}"), "Ori");
-}
-
-TEST_F(AssemblerMIPSTest, Xor) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Xor, "xor ${reg1}, ${reg2}, ${reg3}"), "Xor");
-}
-
-TEST_F(AssemblerMIPSTest, Xori) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Xori, 16, "xori ${reg1}, ${reg2}, {imm}"), "Xori");
-}
-
-TEST_F(AssemblerMIPSTest, Nor) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Nor, "nor ${reg1}, ${reg2}, ${reg3}"), "Nor");
-}
-
-//////////
-// MISC //
-//////////
-
-TEST_F(AssemblerMIPSTest, Movz) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Movz, "movz ${reg1}, ${reg2}, ${reg3}"), "Movz");
-}
-
-TEST_F(AssemblerMIPSTest, Movn) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Movn, "movn ${reg1}, ${reg2}, ${reg3}"), "Movn");
-}
-
-TEST_F(AssemblerMIPSTest, Seb) {
- DriverStr(RepeatRR(&mips::MipsAssembler::Seb, "seb ${reg1}, ${reg2}"), "Seb");
-}
-
-TEST_F(AssemblerMIPSTest, Seh) {
- DriverStr(RepeatRR(&mips::MipsAssembler::Seh, "seh ${reg1}, ${reg2}"), "Seh");
-}
-
-TEST_F(AssemblerMIPSTest, Sll) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sll, 5, "sll ${reg1}, ${reg2}, {imm}"), "Sll");
-}
-
-TEST_F(AssemblerMIPSTest, Srl) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Srl, 5, "srl ${reg1}, ${reg2}, {imm}"), "Srl");
-}
-
-TEST_F(AssemblerMIPSTest, Sra) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sra, 5, "sra ${reg1}, ${reg2}, {imm}"), "Sra");
-}
-
-TEST_F(AssemblerMIPSTest, Sllv) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Sllv, "sllv ${reg1}, ${reg2}, ${reg3}"), "Sllv");
-}
-
-TEST_F(AssemblerMIPSTest, Srlv) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Srlv, "srlv ${reg1}, ${reg2}, ${reg3}"), "Srlv");
-}
-
-TEST_F(AssemblerMIPSTest, Rotrv) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Rotrv, "rotrv ${reg1}, ${reg2}, ${reg3}"), "rotrv");
-}
-
-TEST_F(AssemblerMIPSTest, Srav) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Srav, "srav ${reg1}, ${reg2}, ${reg3}"), "Srav");
-}
-
-TEST_F(AssemblerMIPSTest, Ins) {
- std::vector<mips::Register*> regs = GetRegisters();
- WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
- std::string expected;
- for (mips::Register* reg1 : regs) {
- for (mips::Register* reg2 : regs) {
- for (int32_t pos = 0; pos < 32; pos++) {
- for (int32_t size = 1; pos + size <= 32; size++) {
- __ Ins(*reg1, *reg2, pos, size);
- std::ostringstream instr;
- instr << "ins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
- expected += instr.str();
- }
- }
- }
- }
- DriverStr(expected, "Ins");
-}
-
-TEST_F(AssemblerMIPSTest, Ext) {
- std::vector<mips::Register*> regs = GetRegisters();
- WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
- std::string expected;
- for (mips::Register* reg1 : regs) {
- for (mips::Register* reg2 : regs) {
- for (int32_t pos = 0; pos < 32; pos++) {
- for (int32_t size = 1; pos + size <= 32; size++) {
- __ Ext(*reg1, *reg2, pos, size);
- std::ostringstream instr;
- instr << "ext $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
- expected += instr.str();
- }
- }
- }
- }
- DriverStr(expected, "Ext");
-}
-
-TEST_F(AssemblerMIPSTest, ClzR2) {
- DriverStr(RepeatRR(&mips::MipsAssembler::ClzR2, "clz ${reg1}, ${reg2}"), "clzR2");
-}
-
-TEST_F(AssemblerMIPSTest, CloR2) {
- DriverStr(RepeatRR(&mips::MipsAssembler::CloR2, "clo ${reg1}, ${reg2}"), "cloR2");
-}
-
-TEST_F(AssemblerMIPSTest, Lb) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lb, -16, "lb ${reg1}, {imm}(${reg2})"), "Lb");
-}
-
-TEST_F(AssemblerMIPSTest, Lh) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lh, -16, "lh ${reg1}, {imm}(${reg2})"), "Lh");
-}
-
-TEST_F(AssemblerMIPSTest, Lwl) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lwl, -16, "lwl ${reg1}, {imm}(${reg2})"), "Lwl");
-}
-
-TEST_F(AssemblerMIPSTest, Lw) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lw, -16, "lw ${reg1}, {imm}(${reg2})"), "Lw");
-}
-
-TEST_F(AssemblerMIPSTest, Lwr) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lwr, -16, "lwr ${reg1}, {imm}(${reg2})"), "Lwr");
-}
-
-TEST_F(AssemblerMIPSTest, Lbu) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lbu, -16, "lbu ${reg1}, {imm}(${reg2})"), "Lbu");
-}
-
-TEST_F(AssemblerMIPSTest, Lhu) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Lhu, -16, "lhu ${reg1}, {imm}(${reg2})"), "Lhu");
-}
-
-TEST_F(AssemblerMIPSTest, Lui) {
- DriverStr(RepeatRIb(&mips::MipsAssembler::Lui, 16, "lui ${reg}, {imm}"), "Lui");
-}
-
-TEST_F(AssemblerMIPSTest, Mfhi) {
- DriverStr(RepeatR(&mips::MipsAssembler::Mfhi, "mfhi ${reg}"), "Mfhi");
-}
-
-TEST_F(AssemblerMIPSTest, Mflo) {
- DriverStr(RepeatR(&mips::MipsAssembler::Mflo, "mflo ${reg}"), "Mflo");
-}
-
-TEST_F(AssemblerMIPSTest, Sb) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sb, -16, "sb ${reg1}, {imm}(${reg2})"), "Sb");
-}
-
-TEST_F(AssemblerMIPSTest, Sh) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sh, -16, "sh ${reg1}, {imm}(${reg2})"), "Sh");
-}
-
-TEST_F(AssemblerMIPSTest, Swl) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Swl, -16, "swl ${reg1}, {imm}(${reg2})"), "Swl");
-}
-
-TEST_F(AssemblerMIPSTest, Sw) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sw, -16, "sw ${reg1}, {imm}(${reg2})"), "Sw");
-}
-
-TEST_F(AssemblerMIPSTest, Swr) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Swr, -16, "swr ${reg1}, {imm}(${reg2})"), "Swr");
-}
-
-TEST_F(AssemblerMIPSTest, LlR2) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::LlR2, -16, "ll ${reg1}, {imm}(${reg2})"), "LlR2");
-}
-
-TEST_F(AssemblerMIPSTest, ScR2) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::ScR2, -16, "sc ${reg1}, {imm}(${reg2})"), "ScR2");
-}
-
-TEST_F(AssemblerMIPSTest, Slt) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Slt, "slt ${reg1}, ${reg2}, ${reg3}"), "Slt");
-}
-
-TEST_F(AssemblerMIPSTest, Sltu) {
- DriverStr(RepeatRRR(&mips::MipsAssembler::Sltu, "sltu ${reg1}, ${reg2}, ${reg3}"), "Sltu");
-}
-
-TEST_F(AssemblerMIPSTest, Slti) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Slti, -16, "slti ${reg1}, ${reg2}, {imm}"), "Slti");
-}
-
-TEST_F(AssemblerMIPSTest, Sltiu) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Sltiu, -16, "sltiu ${reg1}, ${reg2}, {imm}"), "Sltiu");
-}
-
-TEST_F(AssemblerMIPSTest, AddS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::AddS, "add.s ${reg1}, ${reg2}, ${reg3}"), "AddS");
-}
-
-TEST_F(AssemblerMIPSTest, AddD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::AddD, "add.d ${reg1}, ${reg2}, ${reg3}"), "AddD");
-}
-
-TEST_F(AssemblerMIPSTest, SubS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SubS, "sub.s ${reg1}, ${reg2}, ${reg3}"), "SubS");
-}
-
-TEST_F(AssemblerMIPSTest, SubD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::SubD, "sub.d ${reg1}, ${reg2}, ${reg3}"), "SubD");
-}
-
-TEST_F(AssemblerMIPSTest, MulS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MulS, "mul.s ${reg1}, ${reg2}, ${reg3}"), "MulS");
-}
-
-TEST_F(AssemblerMIPSTest, MulD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::MulD, "mul.d ${reg1}, ${reg2}, ${reg3}"), "MulD");
-}
-
-TEST_F(AssemblerMIPSTest, DivS) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::DivS, "div.s ${reg1}, ${reg2}, ${reg3}"), "DivS");
-}
-
-TEST_F(AssemblerMIPSTest, DivD) {
- DriverStr(RepeatFFF(&mips::MipsAssembler::DivD, "div.d ${reg1}, ${reg2}, ${reg3}"), "DivD");
-}
-
-TEST_F(AssemblerMIPSTest, MovS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::MovS, "mov.s ${reg1}, ${reg2}"), "MovS");
-}
-
-TEST_F(AssemblerMIPSTest, MovD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::MovD, "mov.d ${reg1}, ${reg2}"), "MovD");
-}
-
-TEST_F(AssemblerMIPSTest, NegS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::NegS, "neg.s ${reg1}, ${reg2}"), "NegS");
-}
-
-TEST_F(AssemblerMIPSTest, NegD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::NegD, "neg.d ${reg1}, ${reg2}"), "NegD");
-}
-
-TEST_F(AssemblerMIPSTest, FloorWS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::FloorWS, "floor.w.s ${reg1}, ${reg2}"), "floor.w.s");
-}
-
-TEST_F(AssemblerMIPSTest, FloorWD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::FloorWD, "floor.w.d ${reg1}, ${reg2}"), "floor.w.d");
-}
-
-TEST_F(AssemblerMIPSTest, CunS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CunS, 3, "c.un.s $fcc{imm}, ${reg1}, ${reg2}"),
- "CunS");
-}
-
-TEST_F(AssemblerMIPSTest, CeqS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqS, 3, "c.eq.s $fcc{imm}, ${reg1}, ${reg2}"),
- "CeqS");
-}
-
-TEST_F(AssemblerMIPSTest, CueqS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqS, 3, "c.ueq.s $fcc{imm}, ${reg1}, ${reg2}"),
- "CueqS");
-}
-
-TEST_F(AssemblerMIPSTest, ColtS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtS, 3, "c.olt.s $fcc{imm}, ${reg1}, ${reg2}"),
- "ColtS");
-}
-
-TEST_F(AssemblerMIPSTest, CultS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CultS, 3, "c.ult.s $fcc{imm}, ${reg1}, ${reg2}"),
- "CultS");
-}
-
-TEST_F(AssemblerMIPSTest, ColeS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeS, 3, "c.ole.s $fcc{imm}, ${reg1}, ${reg2}"),
- "ColeS");
-}
-
-TEST_F(AssemblerMIPSTest, CuleS) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleS, 3, "c.ule.s $fcc{imm}, ${reg1}, ${reg2}"),
- "CuleS");
-}
-
-TEST_F(AssemblerMIPSTest, CunD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CunD, 3, "c.un.d $fcc{imm}, ${reg1}, ${reg2}"),
- "CunD");
-}
-
-TEST_F(AssemblerMIPSTest, CeqD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqD, 3, "c.eq.d $fcc{imm}, ${reg1}, ${reg2}"),
- "CeqD");
-}
-
-TEST_F(AssemblerMIPSTest, CueqD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqD, 3, "c.ueq.d $fcc{imm}, ${reg1}, ${reg2}"),
- "CueqD");
-}
-
-TEST_F(AssemblerMIPSTest, ColtD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtD, 3, "c.olt.d $fcc{imm}, ${reg1}, ${reg2}"),
- "ColtD");
-}
-
-TEST_F(AssemblerMIPSTest, CultD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CultD, 3, "c.ult.d $fcc{imm}, ${reg1}, ${reg2}"),
- "CultD");
-}
-
-TEST_F(AssemblerMIPSTest, ColeD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeD, 3, "c.ole.d $fcc{imm}, ${reg1}, ${reg2}"),
- "ColeD");
-}
-
-TEST_F(AssemblerMIPSTest, CuleD) {
- DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleD, 3, "c.ule.d $fcc{imm}, ${reg1}, ${reg2}"),
- "CuleD");
-}
-
-TEST_F(AssemblerMIPSTest, Movf) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Movf, 3, "movf ${reg1}, ${reg2}, $fcc{imm}"), "Movf");
-}
-
-TEST_F(AssemblerMIPSTest, Movt) {
- DriverStr(RepeatRRIb(&mips::MipsAssembler::Movt, 3, "movt ${reg1}, ${reg2}, $fcc{imm}"), "Movt");
-}
-
-TEST_F(AssemblerMIPSTest, MovfS) {
- DriverStr(RepeatFFIb(&mips::MipsAssembler::MovfS, 3, "movf.s ${reg1}, ${reg2}, $fcc{imm}"),
- "MovfS");
-}
-
-TEST_F(AssemblerMIPSTest, MovfD) {
- DriverStr(RepeatFFIb(&mips::MipsAssembler::MovfD, 3, "movf.d ${reg1}, ${reg2}, $fcc{imm}"),
- "MovfD");
-}
-
-TEST_F(AssemblerMIPSTest, MovtS) {
- DriverStr(RepeatFFIb(&mips::MipsAssembler::MovtS, 3, "movt.s ${reg1}, ${reg2}, $fcc{imm}"),
- "MovtS");
-}
-
-TEST_F(AssemblerMIPSTest, MovtD) {
- DriverStr(RepeatFFIb(&mips::MipsAssembler::MovtD, 3, "movt.d ${reg1}, ${reg2}, $fcc{imm}"),
- "MovtD");
-}
-
-TEST_F(AssemblerMIPSTest, MovzS) {
- DriverStr(RepeatFFR(&mips::MipsAssembler::MovzS, "movz.s ${reg1}, ${reg2}, ${reg3}"), "MovzS");
-}
-
-TEST_F(AssemblerMIPSTest, MovzD) {
- DriverStr(RepeatFFR(&mips::MipsAssembler::MovzD, "movz.d ${reg1}, ${reg2}, ${reg3}"), "MovzD");
-}
-
-TEST_F(AssemblerMIPSTest, MovnS) {
- DriverStr(RepeatFFR(&mips::MipsAssembler::MovnS, "movn.s ${reg1}, ${reg2}, ${reg3}"), "MovnS");
-}
-
-TEST_F(AssemblerMIPSTest, MovnD) {
- DriverStr(RepeatFFR(&mips::MipsAssembler::MovnD, "movn.d ${reg1}, ${reg2}, ${reg3}"), "MovnD");
-}
-
-TEST_F(AssemblerMIPSTest, CvtSW) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsw, "cvt.s.w ${reg1}, ${reg2}"), "CvtSW");
-}
-
-TEST_F(AssemblerMIPSTest, CvtDW) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtdw, "cvt.d.w ${reg1}, ${reg2}"), "CvtDW");
-}
-
-TEST_F(AssemblerMIPSTest, CvtSL) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsl, "cvt.s.l ${reg1}, ${reg2}"), "CvtSL");
-}
-
-TEST_F(AssemblerMIPSTest, CvtDL) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtdl, "cvt.d.l ${reg1}, ${reg2}"), "CvtDL");
-}
-
-TEST_F(AssemblerMIPSTest, CvtSD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsd, "cvt.s.d ${reg1}, ${reg2}"), "CvtSD");
-}
-
-TEST_F(AssemblerMIPSTest, CvtDS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::Cvtds, "cvt.d.s ${reg1}, ${reg2}"), "CvtDS");
-}
-
-TEST_F(AssemblerMIPSTest, TruncWS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::TruncWS, "trunc.w.s ${reg1}, ${reg2}"), "TruncWS");
-}
-
-TEST_F(AssemblerMIPSTest, TruncWD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::TruncWD, "trunc.w.d ${reg1}, ${reg2}"), "TruncWD");
-}
-
-TEST_F(AssemblerMIPSTest, TruncLS) {
- DriverStr(RepeatFF(&mips::MipsAssembler::TruncLS, "trunc.l.s ${reg1}, ${reg2}"), "TruncLS");
-}
-
-TEST_F(AssemblerMIPSTest, TruncLD) {
- DriverStr(RepeatFF(&mips::MipsAssembler::TruncLD, "trunc.l.d ${reg1}, ${reg2}"), "TruncLD");
-}
-
-TEST_F(AssemblerMIPSTest, Mfc1) {
- DriverStr(RepeatRF(&mips::MipsAssembler::Mfc1, "mfc1 ${reg1}, ${reg2}"), "Mfc1");
-}
-
-TEST_F(AssemblerMIPSTest, Mtc1) {
- DriverStr(RepeatRF(&mips::MipsAssembler::Mtc1, "mtc1 ${reg1}, ${reg2}"), "Mtc1");
-}
-
-TEST_F(AssemblerMIPSTest, Mfhc1) {
- DriverStr(RepeatRF(&mips::MipsAssembler::Mfhc1, "mfhc1 ${reg1}, ${reg2}"), "Mfhc1");
-}
-
-TEST_F(AssemblerMIPSTest, Mthc1) {
- DriverStr(RepeatRF(&mips::MipsAssembler::Mthc1, "mthc1 ${reg1}, ${reg2}"), "Mthc1");
-}
-
-TEST_F(AssemblerMIPSTest, Lwc1) {
- DriverStr(RepeatFRIb(&mips::MipsAssembler::Lwc1, -16, "lwc1 ${reg1}, {imm}(${reg2})"), "Lwc1");
-}
-
-TEST_F(AssemblerMIPSTest, Ldc1) {
- DriverStr(RepeatFRIb(&mips::MipsAssembler::Ldc1, -16, "ldc1 ${reg1}, {imm}(${reg2})"), "Ldc1");
-}
-
-TEST_F(AssemblerMIPSTest, Swc1) {
- DriverStr(RepeatFRIb(&mips::MipsAssembler::Swc1, -16, "swc1 ${reg1}, {imm}(${reg2})"), "Swc1");
-}
-
-TEST_F(AssemblerMIPSTest, Sdc1) {
- DriverStr(RepeatFRIb(&mips::MipsAssembler::Sdc1, -16, "sdc1 ${reg1}, {imm}(${reg2})"), "Sdc1");
-}
-
-TEST_F(AssemblerMIPSTest, Move) {
- DriverStr(RepeatRR(&mips::MipsAssembler::Move, "or ${reg1}, ${reg2}, $zero"), "Move");
-}
-
-TEST_F(AssemblerMIPSTest, Clear) {
- DriverStr(RepeatR(&mips::MipsAssembler::Clear, "or ${reg}, $zero, $zero"), "Clear");
-}
-
-TEST_F(AssemblerMIPSTest, Not) {
- DriverStr(RepeatRR(&mips::MipsAssembler::Not, "nor ${reg1}, ${reg2}, $zero"), "Not");
-}
-
-TEST_F(AssemblerMIPSTest, Addiu32) {
- __ Addiu32(mips::A1, mips::A2, -0x8000);
- __ Addiu32(mips::A1, mips::A2, +0);
- __ Addiu32(mips::A1, mips::A2, +0x7FFF);
- __ Addiu32(mips::A1, mips::A2, -0x10000);
- __ Addiu32(mips::A1, mips::A2, -0x8001);
- __ Addiu32(mips::A1, mips::A2, +0x8000);
- __ Addiu32(mips::A1, mips::A2, +0xFFFE);
- __ Addiu32(mips::A1, mips::A2, -0x10001);
- __ Addiu32(mips::A1, mips::A2, +0xFFFF);
- __ Addiu32(mips::A1, mips::A2, +0x10000);
- __ Addiu32(mips::A1, mips::A2, +0x10001);
- __ Addiu32(mips::A1, mips::A2, +0x12345678);
-
- const char* expected =
- "addiu $a1, $a2, -0x8000\n"
- "addiu $a1, $a2, 0\n"
- "addiu $a1, $a2, 0x7FFF\n"
- "addiu $at, $a2, -0x8000\n"
- "addiu $a1, $at, -0x8000\n"
- "addiu $at, $a2, -0x8000\n"
- "addiu $a1, $at, -1\n"
- "addiu $at, $a2, 0x7FFF\n"
- "addiu $a1, $at, 1\n"
- "addiu $at, $a2, 0x7FFF\n"
- "addiu $a1, $at, 0x7FFF\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0xFFFF\n"
- "addu $a1, $a2, $at\n"
- "ori $at, $zero, 0xFFFF\n"
- "addu $a1, $a2, $at\n"
- "lui $at, 1\n"
- "addu $a1, $a2, $at\n"
- "lui $at, 1\n"
- "ori $at, $at, 1\n"
- "addu $a1, $a2, $at\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $a1, $a2, $at\n";
- DriverStr(expected, "Addiu32");
-}
-
-TEST_F(AssemblerMIPSTest, LoadFromOffset) {
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FF8);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFB);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFC);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFF);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0xFFF0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8008);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8001);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x8000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0xFFF0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE8);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE8);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FF0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE9);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE9);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FF0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x12345678);
-
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FF8);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFB);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFC);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFF);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0xFFF0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8008);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8001);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0xFFF0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE8);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE8);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FF0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE9);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE9);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FF0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x12345678);
-
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FF8);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFB);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFC);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFF);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0xFFF0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8008);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8001);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x8000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0xFFF0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE8);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE8);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FF0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE9);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE9);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FF0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x12345678);
-
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FF8);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFB);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFC);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFF);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0xFFF0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8008);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8001);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0xFFF0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE8);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE8);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FF0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE9);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE9);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FF0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x12345678);
-
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8000);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FF8);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFB);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFC);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFF);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0xFFF0);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8008);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8001);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x8000);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0xFFF0);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE8);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE8);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FF0);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE9);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE9);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FF0);
- __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x12345678);
-
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FF8);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFB);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFC);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFF);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0xFFF0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8008);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8001);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x8000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0xFFF0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE8);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF8);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF1);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF1);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF8);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE8);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FF0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE9);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE9);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FF0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x12345678);
-
- const char* expected =
- "lb $a3, -0x8000($a1)\n"
- "lb $a3, 0($a1)\n"
- "lb $a3, 0x7FF8($a1)\n"
- "lb $a3, 0x7FFB($a1)\n"
- "lb $a3, 0x7FFC($a1)\n"
- "lb $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lb $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lb $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lb $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lb $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lb $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lb $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lb $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lb $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lb $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lb $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lb $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lb $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lb $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "lb $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "lb $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lb $a3, 0($at)\n"
-
- "lbu $a3, -0x8000($a1)\n"
- "lbu $a3, 0($a1)\n"
- "lbu $a3, 0x7FF8($a1)\n"
- "lbu $a3, 0x7FFB($a1)\n"
- "lbu $a3, 0x7FFC($a1)\n"
- "lbu $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lbu $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lbu $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lbu $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lbu $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lbu $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lbu $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lbu $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lbu $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lbu $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lbu $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lbu $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lbu $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lbu $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "lbu $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "lbu $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lbu $a3, 0($at)\n"
-
- "lh $a3, -0x8000($a1)\n"
- "lh $a3, 0($a1)\n"
- "lh $a3, 0x7FF8($a1)\n"
- "lh $a3, 0x7FFB($a1)\n"
- "lh $a3, 0x7FFC($a1)\n"
- "lh $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lh $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lh $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lh $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lh $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lh $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lh $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lh $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lh $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lh $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lh $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lh $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lh $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lh $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "lh $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "lh $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lh $a3, 0($at)\n"
-
- "lhu $a3, -0x8000($a1)\n"
- "lhu $a3, 0($a1)\n"
- "lhu $a3, 0x7FF8($a1)\n"
- "lhu $a3, 0x7FFB($a1)\n"
- "lhu $a3, 0x7FFC($a1)\n"
- "lhu $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lhu $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lhu $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lhu $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lhu $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lhu $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lhu $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lhu $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lhu $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lhu $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lhu $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lhu $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lhu $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lhu $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "lhu $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "lhu $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lhu $a3, 0($at)\n"
-
- "lw $a3, -0x8000($a1)\n"
- "lw $a3, 0($a1)\n"
- "lw $a3, 0x7FF8($a1)\n"
- "lw $a3, 0x7FFB($a1)\n"
- "lw $a3, 0x7FFC($a1)\n"
- "lw $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lw $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lw $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "lw $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lw $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lw $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lw $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "lw $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "lw $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "lw $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lw $a3, 0($at)\n"
-
- "lw $a0, -0x8000($a2)\n"
- "lw $a1, -0x7FFC($a2)\n"
- "lw $a0, 0($a2)\n"
- "lw $a1, 4($a2)\n"
- "lw $a0, 0x7FF8($a2)\n"
- "lw $a1, 0x7FFC($a2)\n"
- "lw $a0, 0x7FFB($a2)\n"
- "lw $a1, 0x7FFF($a2)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "lw $a0, 4($at)\n"
- "lw $a1, 8($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "lw $a0, 7($at)\n"
- "lw $a1, 11($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "lw $a0, -0x7FF8($at)\n"
- "lw $a1, -0x7FF4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "lw $a0, -0x10($at)\n"
- "lw $a1, -0xC($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "lw $a0, -9($at)\n"
- "lw $a1, -5($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "lw $a0, 8($at)\n"
- "lw $a1, 12($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "lw $a0, 0x7FF8($at)\n"
- "lw $a1, 0x7FFC($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a0, -0x7FF8($at)\n"
- "lw $a1, -0x7FF4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a0, -8($at)\n"
- "lw $a1, -4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lw $a0, -1($at)\n"
- "lw $a1, 3($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a0, 1($at)\n"
- "lw $a1, 5($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a0, 8($at)\n"
- "lw $a1, 12($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lw $a0, 0x7FF8($at)\n"
- "lw $a1, 0x7FFC($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 0($at)\n"
- "lw $a1, 4($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 7($at)\n"
- "lw $a1, 11($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 1($at)\n"
- "lw $a1, 5($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 0($at)\n"
- "lw $a1, 4($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 0($at)\n"
- "lw $a1, 4($at)\n";
- DriverStr(expected, "LoadFromOffset");
-}
-
-TEST_F(AssemblerMIPSTest, LoadSFromOffset) {
- __ LoadSFromOffset(mips::F2, mips::A0, -0x8000);
- __ LoadSFromOffset(mips::F2, mips::A0, +0);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x7FF8);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFB);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFC);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFF);
- __ LoadSFromOffset(mips::F2, mips::A0, -0xFFF0);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x8008);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x8001);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x8000);
- __ LoadSFromOffset(mips::F2, mips::A0, +0xFFF0);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x17FE8);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF8);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF1);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF1);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF8);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x17FE8);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x17FF0);
- __ LoadSFromOffset(mips::F2, mips::A0, -0x17FE9);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x17FE9);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x17FF0);
- __ LoadSFromOffset(mips::F2, mips::A0, +0x12345678);
-
- const char* expected =
- "lwc1 $f2, -0x8000($a0)\n"
- "lwc1 $f2, 0($a0)\n"
- "lwc1 $f2, 0x7FF8($a0)\n"
- "lwc1 $f2, 0x7FFB($a0)\n"
- "lwc1 $f2, 0x7FFC($a0)\n"
- "lwc1 $f2, 0x7FFF($a0)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "lwc1 $f2, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "lwc1 $f2, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "lwc1 $f2, -9($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f2, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f2, 0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lwc1 $f2, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lwc1 $f2, -8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lwc1 $f2, -1($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lwc1 $f2, 1($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lwc1 $f2, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lwc1 $f2, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f2, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f2, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f2, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f2, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f2, 0($at)\n";
- DriverStr(expected, "LoadSFromOffset");
-}
-
-TEST_F(AssemblerMIPSTest, LoadDFromOffset) {
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8000);
- __ LoadDFromOffset(mips::F0, mips::A0, +0);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FF8);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFB);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFC);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFF);
- __ LoadDFromOffset(mips::F0, mips::A0, -0xFFF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8008);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x8001);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x8000);
- __ LoadDFromOffset(mips::F0, mips::A0, +0xFFF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF1);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF1);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF8);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE8);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FF0);
- __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE9);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE9);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x17FF0);
- __ LoadDFromOffset(mips::F0, mips::A0, +0x12345678);
-
- const char* expected =
- "ldc1 $f0, -0x8000($a0)\n"
- "ldc1 $f0, 0($a0)\n"
- "ldc1 $f0, 0x7FF8($a0)\n"
- "lwc1 $f0, 0x7FFB($a0)\n"
- "lwc1 $f1, 0x7FFF($a0)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f0, 4($at)\n"
- "lwc1 $f1, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "lwc1 $f0, 7($at)\n"
- "lwc1 $f1, 11($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "ldc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "ldc1 $f0, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "lwc1 $f0, -9($at)\n"
- "lwc1 $f1, -5($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ldc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "ldc1 $f0, 0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "ldc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "ldc1 $f0, -8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "lwc1 $f0, -1($at)\n"
- "lwc1 $f1, 3($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "lwc1 $f0, 1($at)\n"
- "lwc1 $f1, 5($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "ldc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "ldc1 $f0, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "ldc1 $f0, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f0, 7($at)\n"
- "lwc1 $f1, 11($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f0, 1($at)\n"
- "lwc1 $f1, 5($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a0\n"
- "ldc1 $f0, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "ldc1 $f0, 0($at)\n";
- DriverStr(expected, "LoadDFromOffset");
-}
-
-TEST_F(AssemblerMIPSTest, StoreToOffset) {
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8000);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FF8);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFB);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFC);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFF);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0xFFF0);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8008);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8001);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x8000);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0xFFF0);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE8);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF8);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF1);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF1);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF8);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE8);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FF0);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE9);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE9);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FF0);
- __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x12345678);
-
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FF8);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFB);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFC);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFF);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0xFFF0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8008);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8001);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x8000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0xFFF0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE8);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF8);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF1);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF1);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF8);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE8);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FF0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE9);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE9);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FF0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x12345678);
-
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8000);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FF8);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFB);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFC);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFF);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0xFFF0);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8008);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8001);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x8000);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0xFFF0);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE8);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF8);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF1);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF1);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF8);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE8);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FF0);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE9);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE9);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FF0);
- __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x12345678);
-
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FF8);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFB);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFC);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFF);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0xFFF0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8008);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8001);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x8000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0xFFF0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE8);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF8);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF1);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF1);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF8);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE8);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FF0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE9);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE9);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FF0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x12345678);
-
- const char* expected =
- "sb $a3, -0x8000($a1)\n"
- "sb $a3, 0($a1)\n"
- "sb $a3, 0x7FF8($a1)\n"
- "sb $a3, 0x7FFB($a1)\n"
- "sb $a3, 0x7FFC($a1)\n"
- "sb $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sb $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sb $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sb $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sb $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sb $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sb $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sb $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sb $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sb $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sb $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sb $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sb $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sb $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "sb $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "sb $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "sb $a3, 0($at)\n"
-
- "sh $a3, -0x8000($a1)\n"
- "sh $a3, 0($a1)\n"
- "sh $a3, 0x7FF8($a1)\n"
- "sh $a3, 0x7FFB($a1)\n"
- "sh $a3, 0x7FFC($a1)\n"
- "sh $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sh $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sh $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sh $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sh $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sh $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sh $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sh $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sh $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sh $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sh $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sh $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sh $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sh $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "sh $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "sh $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "sh $a3, 0($at)\n"
-
- "sw $a3, -0x8000($a1)\n"
- "sw $a3, 0($a1)\n"
- "sw $a3, 0x7FF8($a1)\n"
- "sw $a3, 0x7FFB($a1)\n"
- "sw $a3, 0x7FFC($a1)\n"
- "sw $a3, 0x7FFF($a1)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sw $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sw $a3, -0x10($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "sw $a3, -9($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sw $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "sw $a3, 0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a3, -0x7FF8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a3, -8($at)\n"
- "addiu $at, $a1, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a3, -1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a3, 1($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a3, 8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a3, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sw $a3, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a1\n"
- "sw $a3, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a1\n"
- "sw $a3, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a1\n"
- "sw $a3, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "sw $a3, 0($at)\n"
-
- "sw $a0, -0x8000($a2)\n"
- "sw $a1, -0x7FFC($a2)\n"
- "sw $a0, 0($a2)\n"
- "sw $a1, 4($a2)\n"
- "sw $a0, 0x7FF8($a2)\n"
- "sw $a1, 0x7FFC($a2)\n"
- "sw $a0, 0x7FFB($a2)\n"
- "sw $a1, 0x7FFF($a2)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "sw $a0, 4($at)\n"
- "sw $a1, 8($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "sw $a0, 7($at)\n"
- "sw $a1, 11($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "sw $a0, -0x7FF8($at)\n"
- "sw $a1, -0x7FF4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "sw $a0, -0x10($at)\n"
- "sw $a1, -0xC($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "sw $a0, -9($at)\n"
- "sw $a1, -5($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "sw $a0, 8($at)\n"
- "sw $a1, 12($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "sw $a0, 0x7FF8($at)\n"
- "sw $a1, 0x7FFC($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a0, -0x7FF8($at)\n"
- "sw $a1, -0x7FF4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a0, -8($at)\n"
- "sw $a1, -4($at)\n"
- "addiu $at, $a2, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sw $a0, -1($at)\n"
- "sw $a1, 3($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a0, 1($at)\n"
- "sw $a1, 5($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a0, 8($at)\n"
- "sw $a1, 12($at)\n"
- "addiu $at, $a2, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sw $a0, 0x7FF8($at)\n"
- "sw $a1, 0x7FFC($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 0($at)\n"
- "sw $a1, 4($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 7($at)\n"
- "sw $a1, 11($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 1($at)\n"
- "sw $a1, 5($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 0($at)\n"
- "sw $a1, 4($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 0($at)\n"
- "sw $a1, 4($at)\n";
- DriverStr(expected, "StoreToOffset");
-}
-
-TEST_F(AssemblerMIPSTest, StoreSToOffset) {
- __ StoreSToOffset(mips::F2, mips::A0, -0x8000);
- __ StoreSToOffset(mips::F2, mips::A0, +0);
- __ StoreSToOffset(mips::F2, mips::A0, +0x7FF8);
- __ StoreSToOffset(mips::F2, mips::A0, +0x7FFB);
- __ StoreSToOffset(mips::F2, mips::A0, +0x7FFC);
- __ StoreSToOffset(mips::F2, mips::A0, +0x7FFF);
- __ StoreSToOffset(mips::F2, mips::A0, -0xFFF0);
- __ StoreSToOffset(mips::F2, mips::A0, -0x8008);
- __ StoreSToOffset(mips::F2, mips::A0, -0x8001);
- __ StoreSToOffset(mips::F2, mips::A0, +0x8000);
- __ StoreSToOffset(mips::F2, mips::A0, +0xFFF0);
- __ StoreSToOffset(mips::F2, mips::A0, -0x17FE8);
- __ StoreSToOffset(mips::F2, mips::A0, -0x0FFF8);
- __ StoreSToOffset(mips::F2, mips::A0, -0x0FFF1);
- __ StoreSToOffset(mips::F2, mips::A0, +0x0FFF1);
- __ StoreSToOffset(mips::F2, mips::A0, +0x0FFF8);
- __ StoreSToOffset(mips::F2, mips::A0, +0x17FE8);
- __ StoreSToOffset(mips::F2, mips::A0, -0x17FF0);
- __ StoreSToOffset(mips::F2, mips::A0, -0x17FE9);
- __ StoreSToOffset(mips::F2, mips::A0, +0x17FE9);
- __ StoreSToOffset(mips::F2, mips::A0, +0x17FF0);
- __ StoreSToOffset(mips::F2, mips::A0, +0x12345678);
-
- const char* expected =
- "swc1 $f2, -0x8000($a0)\n"
- "swc1 $f2, 0($a0)\n"
- "swc1 $f2, 0x7FF8($a0)\n"
- "swc1 $f2, 0x7FFB($a0)\n"
- "swc1 $f2, 0x7FFC($a0)\n"
- "swc1 $f2, 0x7FFF($a0)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "swc1 $f2, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "swc1 $f2, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "swc1 $f2, -9($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "swc1 $f2, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "swc1 $f2, 0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "swc1 $f2, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "swc1 $f2, -8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "swc1 $f2, -1($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "swc1 $f2, 1($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "swc1 $f2, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "swc1 $f2, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "swc1 $f2, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "swc1 $f2, 7($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a0\n"
- "swc1 $f2, 1($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a0\n"
- "swc1 $f2, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "swc1 $f2, 0($at)\n";
- DriverStr(expected, "StoreSToOffset");
-}
-
-TEST_F(AssemblerMIPSTest, StoreDToOffset) {
- __ StoreDToOffset(mips::F0, mips::A0, -0x8000);
- __ StoreDToOffset(mips::F0, mips::A0, +0);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FF8);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFB);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFC);
- __ StoreDToOffset(mips::F0, mips::A0, +0x7FFF);
- __ StoreDToOffset(mips::F0, mips::A0, -0xFFF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x8008);
- __ StoreDToOffset(mips::F0, mips::A0, -0x8001);
- __ StoreDToOffset(mips::F0, mips::A0, +0x8000);
- __ StoreDToOffset(mips::F0, mips::A0, +0xFFF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FE8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF1);
- __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF1);
- __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF8);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FE8);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FF0);
- __ StoreDToOffset(mips::F0, mips::A0, -0x17FE9);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FE9);
- __ StoreDToOffset(mips::F0, mips::A0, +0x17FF0);
- __ StoreDToOffset(mips::F0, mips::A0, +0x12345678);
-
- const char* expected =
- "sdc1 $f0, -0x8000($a0)\n"
- "sdc1 $f0, 0($a0)\n"
- "sdc1 $f0, 0x7FF8($a0)\n"
- "swc1 $f0, 0x7FFB($a0)\n"
- "swc1 $f1, 0x7FFF($a0)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "swc1 $f0, 4($at)\n"
- "swc1 $f1, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "swc1 $f0, 7($at)\n"
- "swc1 $f1, 11($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "sdc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "sdc1 $f0, -0x10($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "swc1 $f0, -9($at)\n"
- "swc1 $f1, -5($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "sdc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "sdc1 $f0, 0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sdc1 $f0, -0x7FF8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "sdc1 $f0, -8($at)\n"
- "addiu $at, $a0, -0x7FF8\n"
- "addiu $at, $at, -0x7FF8\n"
- "swc1 $f0, -1($at)\n"
- "swc1 $f1, 3($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "swc1 $f0, 1($at)\n"
- "swc1 $f1, 5($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sdc1 $f0, 8($at)\n"
- "addiu $at, $a0, 0x7FF8\n"
- "addiu $at, $at, 0x7FF8\n"
- "sdc1 $f0, 0x7FF8($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "sdc1 $f0, 0($at)\n"
- "lui $at, 0xFFFE\n"
- "ori $at, $at, 0x8010\n"
- "addu $at, $at, $a0\n"
- "swc1 $f0, 7($at)\n"
- "swc1 $f1, 11($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FE8\n"
- "addu $at, $at, $a0\n"
- "swc1 $f0, 1($at)\n"
- "swc1 $f1, 5($at)\n"
- "lui $at, 0x1\n"
- "ori $at, $at, 0x7FF0\n"
- "addu $at, $at, $a0\n"
- "sdc1 $f0, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "sdc1 $f0, 0($at)\n";
- DriverStr(expected, "StoreDToOffset");
-}
-
-TEST_F(AssemblerMIPSTest, StoreConstToOffset) {
- __ StoreConstToOffset(mips::kStoreByte, 0xFF, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreHalfword, 0xFFFF, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreDoubleword, 0x123456789ABCDEF0, mips::A1, +0, mips::T8);
-
- __ StoreConstToOffset(mips::kStoreByte, 0, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreHalfword, 0, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreWord, 0, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreDoubleword, 0, mips::A1, +0, mips::T8);
-
- __ StoreConstToOffset(mips::kStoreDoubleword, 0x1234567812345678, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreDoubleword, 0x1234567800000000, mips::A1, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreDoubleword, 0x0000000012345678, mips::A1, +0, mips::T8);
-
- __ StoreConstToOffset(mips::kStoreWord, 0, mips::T8, +0, mips::T8);
- __ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::T8, +0, mips::T8);
-
- __ StoreConstToOffset(mips::kStoreWord, 0, mips::A1, -0xFFF0, mips::T8);
- __ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::A1, +0xFFF0, mips::T8);
-
- __ StoreConstToOffset(mips::kStoreWord, 0, mips::T8, -0xFFF0, mips::T8);
- __ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::T8, +0xFFF0, mips::T8);
-
- const char* expected =
- "ori $t8, $zero, 0xFF\n"
- "sb $t8, 0($a1)\n"
- "ori $t8, $zero, 0xFFFF\n"
- "sh $t8, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 0($a1)\n"
- "lui $t8, 0x9ABC\n"
- "ori $t8, $t8, 0xDEF0\n"
- "sw $t8, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 4($a1)\n"
-
- "sb $zero, 0($a1)\n"
- "sh $zero, 0($a1)\n"
- "sw $zero, 0($a1)\n"
- "sw $zero, 0($a1)\n"
- "sw $zero, 4($a1)\n"
-
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 0($a1)\n"
- "sw $t8, 4($a1)\n"
- "sw $zero, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 4($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 0($a1)\n"
- "sw $zero, 4($a1)\n"
-
- "sw $zero, 0($t8)\n"
- "lui $at, 0x1234\n"
- "ori $at, $at, 0x5678\n"
- "sw $at, 0($t8)\n"
-
- "addiu $at, $a1, -0x7FF8\n"
- "sw $zero, -0x7FF8($at)\n"
- "addiu $at, $a1, 0x7FF8\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 0x7FF8($at)\n"
-
- "addiu $at, $t8, -0x7FF8\n"
- "sw $zero, -0x7FF8($at)\n"
- "addiu $at, $t8, 0x7FF8\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sw $t8, 0x7FF8($at)\n";
- DriverStr(expected, "StoreConstToOffset");
-}
-
-//////////////
-// BRANCHES //
-//////////////
-
-TEST_F(AssemblerMIPSTest, B) {
- BranchHelper(&mips::MipsAssembler::B, "B");
-}
-
-TEST_F(AssemblerMIPSTest, Bal) {
- BranchHelper(&mips::MipsAssembler::Bal, "Bal");
-}
-
-TEST_F(AssemblerMIPSTest, Beq) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq");
-}
-
-TEST_F(AssemblerMIPSTest, Bne) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne");
-}
-
-TEST_F(AssemblerMIPSTest, Beqz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqz");
-}
-
-TEST_F(AssemblerMIPSTest, Bnez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnez");
-}
-
-TEST_F(AssemblerMIPSTest, Bltz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz");
-}
-
-TEST_F(AssemblerMIPSTest, Bgez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez");
-}
-
-TEST_F(AssemblerMIPSTest, Blez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez");
-}
-
-TEST_F(AssemblerMIPSTest, Bgtz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz");
-}
-
-TEST_F(AssemblerMIPSTest, Blt) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Blt");
-}
-
-TEST_F(AssemblerMIPSTest, Bge) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bge");
-}
-
-TEST_F(AssemblerMIPSTest, Bltu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltu");
-}
-
-TEST_F(AssemblerMIPSTest, Bgeu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeu");
-}
-
-TEST_F(AssemblerMIPSTest, Bc1f) {
- BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1f, "Bc1f");
-}
-
-TEST_F(AssemblerMIPSTest, Bc1t) {
- BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1t, "Bc1t");
-}
-
-TEST_F(AssemblerMIPSTest, BareB) {
- BranchHelper(&mips::MipsAssembler::B, "B", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBal) {
- BranchHelper(&mips::MipsAssembler::Bal, "Bal", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBeq) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBne) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBeqz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBnez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBltz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBgez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBlez) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBgtz) {
- BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBlt) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Blt", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBge) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bge", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBltu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltu", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBgeu) {
- BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeu", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBc1f) {
- BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1f, "Bc1f", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, BareBc1t) {
- BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1t, "Bc1t", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPSTest, ImpossibleReordering) {
- mips::MipsLabel label1, label2;
- __ SetReorder(true);
-
- __ B(&label1); // No preceding or target instruction for the delay slot.
-
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bind(&label1);
- __ B(&label1); // The preceding label prevents moving Addu into the delay slot.
- __ B(&label1); // No preceding or target instruction for the delay slot.
-
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Beqz(mips::T0, &label1); // T0 dependency.
-
- __ Or(mips::T1, mips::T2, mips::T3);
- __ Bne(mips::T2, mips::T1, &label1); // T1 dependency.
-
- __ And(mips::T0, mips::T1, mips::T2);
- __ Blt(mips::T1, mips::T0, &label1); // T0 dependency.
-
- __ Xor(mips::AT, mips::T0, mips::T1);
- __ Bge(mips::T1, mips::T0, &label1); // AT dependency.
-
- __ Subu(mips::T0, mips::T1, mips::AT);
- __ Bltu(mips::T1, mips::T0, &label1); // AT dependency.
-
- __ ColtS(1, mips::F2, mips::F4);
- __ Bc1t(1, &label1); // cc1 dependency.
-
- __ Move(mips::T0, mips::RA);
- __ Bal(&label1); // RA dependency.
-
- __ Lw(mips::RA, mips::T0, 0);
- __ Bal(&label1); // RA dependency.
-
- __ LlR2(mips::T9, mips::T0, 0);
- __ Jalr(mips::T9); // T9 dependency.
-
- __ Sw(mips::RA, mips::T0, 0);
- __ Jalr(mips::T9); // RA dependency.
-
- __ Lw(mips::T1, mips::T0, 0);
- __ Jalr(mips::T1, mips::T9); // T1 dependency.
-
- __ ScR2(mips::T9, mips::T0, 0);
- __ Jr(mips::T9); // T9 dependency.
-
- __ Bind(&label2);
-
- __ Bnez(mips::T0, &label2); // No preceding instruction for the delay slot.
-
- __ Bgeu(mips::T1, mips::T0, &label2); // No preceding instruction for the delay slot.
-
- __ Bc1f(2, &label2); // No preceding instruction for the delay slot.
-
- __ Bal(&label2); // No preceding instruction for the delay slot.
-
- __ Jalr(mips::T9); // No preceding instruction for the delay slot.
-
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ CodePosition(); // Drops the delay slot candidate (the last instruction).
- __ Beq(mips::T1, mips::T2, &label2); // No preceding or target instruction for the delay slot.
-
- std::string expected =
- ".set noreorder\n"
- "b 1f\n"
- "nop\n"
-
- "addu $t0, $t1, $t2\n"
- "1:\n"
- "b 1b\n"
- "nop\n"
- "b 1b\n"
- "nop\n"
-
- "addu $t0, $t1, $t2\n"
- "beqz $t0, 1b\n"
- "nop\n"
-
- "or $t1, $t2, $t3\n"
- "bne $t2, $t1, 1b\n"
- "nop\n"
-
- "and $t0, $t1, $t2\n"
- "slt $at, $t1, $t0\n"
- "bnez $at, 1b\n"
- "nop\n"
-
- "xor $at, $t0, $t1\n"
- "slt $at, $t1, $t0\n"
- "beqz $at, 1b\n"
- "nop\n"
-
- "subu $t0, $t1, $at\n"
- "sltu $at, $t1, $t0\n"
- "bnez $at, 1b\n"
- "nop\n"
-
- "c.olt.s $fcc1, $f2, $f4\n"
- "bc1t $fcc1, 1b\n"
- "nop\n"
-
- "or $t0, $ra, $zero\n"
- "bal 1b\n"
- "nop\n"
-
- "lw $ra, 0($t0)\n"
- "bal 1b\n"
- "nop\n"
-
- "ll $t9, 0($t0)\n"
- "jalr $t9\n"
- "nop\n"
-
- "sw $ra, 0($t0)\n"
- "jalr $t9\n"
- "nop\n"
-
- "lw $t1, 0($t0)\n"
- "jalr $t1, $t9\n"
- "nop\n"
-
- "sc $t9, 0($t0)\n"
- "jalr $zero, $t9\n"
- "nop\n"
-
- "2:\n"
-
- "bnez $t0, 2b\n"
- "nop\n"
-
- "sltu $at, $t1, $t0\n"
- "beqz $at, 2b\n"
- "nop\n"
-
- "bc1f $fcc2, 2b\n"
- "nop\n"
-
- "bal 2b\n"
- "nop\n"
-
- "jalr $t9\n"
- "nop\n"
-
- "addu $t0, $t1, $t2\n"
- "beq $t1, $t2, 2b\n"
- "nop\n";
- DriverStr(expected, "ImpossibleReordering");
-}
-
-TEST_F(AssemblerMIPSTest, Reordering) {
- mips::MipsLabel label1, label2;
- __ SetReorder(true);
-
- __ Bind(&label1);
- __ Bind(&label2);
-
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Beqz(mips::T1, &label1);
-
- __ Or(mips::T1, mips::T2, mips::T3);
- __ Bne(mips::T2, mips::T3, &label1);
-
- __ And(mips::T0, mips::T1, mips::T2);
- __ Blt(mips::T1, mips::T2, &label1);
-
- __ Xor(mips::T2, mips::T0, mips::T1);
- __ Bge(mips::T1, mips::T0, &label1);
-
- __ Subu(mips::T2, mips::T1, mips::T0);
- __ Bltu(mips::T1, mips::T0, &label1);
-
- __ ColtS(0, mips::F2, mips::F4);
- __ Bc1t(1, &label1);
-
- __ Move(mips::T0, mips::T1);
- __ Bal(&label1);
-
- __ LlR2(mips::T1, mips::T0, 0);
- __ Jalr(mips::T9);
-
- __ ScR2(mips::T1, mips::T0, 0);
- __ Jr(mips::T9);
-
- std::string expected =
- ".set noreorder\n"
- "1:\n"
-
- "beqz $t1, 1b\n"
- "addu $t0, $t1, $t2\n"
-
- "bne $t2, $t3, 1b\n"
- "or $t1, $t2, $t3\n"
-
- "slt $at, $t1, $t2\n"
- "bnez $at, 1b\n"
- "and $t0, $t1, $t2\n"
-
- "slt $at, $t1, $t0\n"
- "beqz $at, 1b\n"
- "xor $t2, $t0, $t1\n"
-
- "sltu $at, $t1, $t0\n"
- "bnez $at, 1b\n"
- "subu $t2, $t1, $t0\n"
-
- "bc1t $fcc1, 1b\n"
- "c.olt.s $fcc0, $f2, $f4\n"
-
- "bal 1b\n"
- "or $t0, $t1, $zero\n"
-
- "jalr $t9\n"
- "ll $t1, 0($t0)\n"
-
- "jalr $zero, $t9\n"
- "sc $t1, 0($t0)\n";
- DriverStr(expected, "Reordering");
-}
-
-TEST_F(AssemblerMIPSTest, AbsorbTargetInstruction) {
- mips::MipsLabel label1, label2, label3, label4, label5, label6;
- mips::MipsLabel label7, label8, label9, label10, label11, label12, label13;
- __ SetReorder(true);
-
- __ B(&label1);
- __ Bind(&label1);
- __ Addu(mips::T0, mips::T1, mips::T2);
-
- __ Bind(&label2);
- __ Xor(mips::T0, mips::T1, mips::T2);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bind(&label3); // Prevents reordering ADDU above with B below.
- __ B(&label2);
-
- __ B(&label4);
- __ Bind(&label4);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ CodePosition(); // Prevents absorbing ADDU above.
-
- __ B(&label5);
- __ Bind(&label5);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ Bind(&label6);
- __ CodePosition(); // Even across Bind(), CodePosition() prevents absorbing the ADDU above.
-
- __ Nop();
- __ B(&label7);
- __ Bind(&label7);
- __ Lw(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
-
- __ Nop();
- __ B(&label8);
- __ Bind(&label8);
- __ Sw(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
-
- __ Nop();
- __ B(&label9);
- __ Bind(&label9);
- __ Addiu(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
-
- __ Nop();
- __ B(&label10);
- __ Bind(&label10);
- __ Lw(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
-
- __ Nop();
- __ B(&label11);
- __ Bind(&label11);
- __ Sw(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
-
- __ Nop();
- __ B(&label12);
- __ Bind(&label12);
- __ Addiu(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
-
- __ Nop();
- __ B(&label13);
- __ Bind(&label13);
- __ Andi(mips::V0, mips::A0, 0x5678); // Not one of patchable instructions, absorbed.
-
- std::string expected =
- ".set noreorder\n"
- "b 1f\n"
- "addu $t0, $t1, $t2\n"
- "addu $t0, $t1, $t2\n"
- "1:\n"
-
- "xor $t0, $t1, $t2\n"
- "2:\n"
- "addu $t0, $t1, $t2\n"
- "b 2b\n"
- "xor $t0, $t1, $t2\n"
-
- "b 4f\n"
- "nop\n"
- "4:\n"
- "addu $t0, $t1, $t2\n"
-
- "b 5f\n"
- "nop\n"
- "5:\n"
- "addu $t0, $t1, $t2\n"
-
- "nop\n"
- "b 7f\n"
- "nop\n"
- "7:\n"
- "lw $v0, 0x5678($a0)\n"
-
- "nop\n"
- "b 8f\n"
- "nop\n"
- "8:\n"
- "sw $v0, 0x5678($a0)\n"
-
- "nop\n"
- "b 9f\n"
- "nop\n"
- "9:\n"
- "addiu $v0, $a0, 0x5678\n"
-
- "nop\n"
- "b 10f\n"
- "lw $v0, 0x5680($a0)\n"
- "lw $v0, 0x5680($a0)\n"
- "10:\n"
-
- "nop\n"
- "b 11f\n"
- "sw $v0, 0x5680($a0)\n"
- "sw $v0, 0x5680($a0)\n"
- "11:\n"
-
- "nop\n"
- "b 12f\n"
- "addiu $v0, $a0, 0x5680\n"
- "addiu $v0, $a0, 0x5680\n"
- "12:\n"
-
- "nop\n"
- "b 13f\n"
- "andi $v0, $a0, 0x5678\n"
- "andi $v0, $a0, 0x5678\n"
- "13:\n";
- DriverStr(expected, "AbsorbTargetInstruction");
-}
-
-TEST_F(AssemblerMIPSTest, SetReorder) {
- mips::MipsLabel label1, label2, label3, label4, label5, label6;
-
- __ SetReorder(true);
- __ Bind(&label1);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ B(&label1);
- __ B(&label5);
- __ B(&label6);
-
- __ SetReorder(false);
- __ Bind(&label2);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ B(&label2);
- __ B(&label5);
- __ B(&label6);
-
- __ SetReorder(true);
- __ Bind(&label3);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ B(&label3);
- __ B(&label5);
- __ B(&label6);
-
- __ SetReorder(false);
- __ Bind(&label4);
- __ Addu(mips::T0, mips::T1, mips::T2);
- __ B(&label4);
- __ B(&label5);
- __ B(&label6);
-
- __ SetReorder(true);
- __ Bind(&label5);
- __ Subu(mips::T0, mips::T1, mips::T2);
-
- __ SetReorder(false);
- __ Bind(&label6);
- __ Xor(mips::T0, mips::T1, mips::T2);
-
- std::string expected =
- ".set noreorder\n"
- "1:\n"
- "b 1b\n"
- "addu $t0, $t1, $t2\n"
- "b 55f\n"
- "subu $t0, $t1, $t2\n"
- "b 6f\n"
- "nop\n"
-
- "2:\n"
- "addu $t0, $t1, $t2\n"
- "b 2b\n"
- "nop\n"
- "b 5f\n"
- "nop\n"
- "b 6f\n"
- "nop\n"
-
- "3:\n"
- "b 3b\n"
- "addu $t0, $t1, $t2\n"
- "b 55f\n"
- "subu $t0, $t1, $t2\n"
- "b 6f\n"
- "nop\n"
-
- "4:\n"
- "addu $t0, $t1, $t2\n"
- "b 4b\n"
- "nop\n"
- "b 5f\n"
- "nop\n"
- "b 6f\n"
- "nop\n"
-
- "5:\n"
- "subu $t0, $t1, $t2\n"
- "55:\n"
- "6:\n"
- "xor $t0, $t1, $t2\n";
- DriverStr(expected, "SetReorder");
-}
-
-TEST_F(AssemblerMIPSTest, ReorderPatchedInstruction) {
- __ SetReorder(true);
- mips::MipsLabel label1, label2;
- mips::MipsLabel patcher_label1, patcher_label2, patcher_label3, patcher_label4, patcher_label5;
- __ Lw(mips::V0, mips::A0, 0x5678, &patcher_label1);
- __ Beq(mips::A0, mips::A1, &label1);
- constexpr uint32_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label1);
- __ Sw(mips::V0, mips::A0, 0x5678, &patcher_label2);
- __ Bltz(mips::V1, &label2);
- constexpr uint32_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label2);
- __ Addiu(mips::V0, mips::A0, 0x5678, &patcher_label3);
- __ B(&label1);
- __ Lw(mips::V0, mips::A0, 0x5678, &patcher_label4);
- __ Jalr(mips::T9);
- __ Sw(mips::V0, mips::A0, 0x5678, &patcher_label5);
- __ Blt(mips::V0, mips::V1, &label2);
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
-
- std::string expected =
- ".set noreorder\n"
- "beq $a0, $a1, 1f\n"
- "lw $v0, 0x5678($a0)\n" +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n"
- "bltz $v1, 2f\n"
- "sw $v0, 0x5678($a0)\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- "2:\n"
- "b 1b\n"
- "addiu $v0, $a0, 0x5678\n"
- "jalr $t9\n"
- "lw $v0, 0x5678($a0)\n"
- "slt $at, $v0, $v1\n"
- "bnez $at, 2b\n"
- "sw $v0, 0x5678($a0)\n"
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, "ReorderPatchedInstruction");
- EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 1 * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + 3) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label3), (kAdduCount1 + kAdduCount2 + 5) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label4), (kAdduCount1 + kAdduCount2 + 7) * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label5), (kAdduCount1 + kAdduCount2 + 10) * 4u);
-}
-
-TEST_F(AssemblerMIPSTest, LongBranchReorder) {
- mips::MipsLabel label, patcher_label1, patcher_label2;
- __ SetReorder(true);
- __ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label1);
- __ B(&label);
- constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
- constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label2);
- __ B(&label);
-
- // Account for 5 extra instructions: ori, addu, lw, jalr, addiu.
- uint32_t offset_forward = (kAdduCount1 + 5) * sizeof(uint32_t);
- // Account for 5 extra instructions: subu, addiu, sw, nal, lui.
- uint32_t offset_back = static_cast<uint32_t>(-(kAdduCount1 + 5) * sizeof(uint32_t));
-
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "addiu $t0, $t1, 0x5678\n"
- "addiu $sp, $sp, -16\n"
- "sw $ra, 0($sp)\n"
- "bltzal $zero, .+4\n"
- "lui $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "ori $at, $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "addu $at, $at, $ra\n"
- "lw $ra, 0($sp)\n"
- "jalr $zero, $at\n"
- "addiu $sp, $sp, 16\n" <<
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
- "addiu $t0, $t1, 0x5678\n"
- "addiu $sp, $sp, -16\n"
- "sw $ra, 0($sp)\n"
- "bltzal $zero, .+4\n"
- "lui $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "ori $at, $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "addu $at, $at, $ra\n"
- "lw $ra, 0($sp)\n"
- "jalr $zero, $at\n"
- "addiu $sp, $sp, 16\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBranchReorder");
- EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 0 * 4u);
- EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + kAdduCount2 + 10) * 4u);
-}
-
-///////////////////////
-// Loading Constants //
-///////////////////////
-
-TEST_F(AssemblerMIPSTest, LoadConst32) {
- // IsUint<16>(value)
- __ LoadConst32(mips::V0, 0);
- __ LoadConst32(mips::V0, 65535);
- // IsInt<16>(value)
- __ LoadConst32(mips::V0, -1);
- __ LoadConst32(mips::V0, -32768);
- // Everything else
- __ LoadConst32(mips::V0, 65536);
- __ LoadConst32(mips::V0, 65537);
- __ LoadConst32(mips::V0, 2147483647);
- __ LoadConst32(mips::V0, -32769);
- __ LoadConst32(mips::V0, -65536);
- __ LoadConst32(mips::V0, -65537);
- __ LoadConst32(mips::V0, -2147483647);
- __ LoadConst32(mips::V0, -2147483648);
-
- const char* expected =
- // IsUint<16>(value)
- "ori $v0, $zero, 0\n" // __ LoadConst32(mips::V0, 0);
- "ori $v0, $zero, 65535\n" // __ LoadConst32(mips::V0, 65535);
- // IsInt<16>(value)
- "addiu $v0, $zero, -1\n" // __ LoadConst32(mips::V0, -1);
- "addiu $v0, $zero, -32768\n" // __ LoadConst32(mips::V0, -32768);
- // Everything else
- "lui $v0, 1\n" // __ LoadConst32(mips::V0, 65536);
- "lui $v0, 1\n" // __ LoadConst32(mips::V0, 65537);
- "ori $v0, 1\n" // "
- "lui $v0, 32767\n" // __ LoadConst32(mips::V0, 2147483647);
- "ori $v0, 65535\n" // "
- "lui $v0, 65535\n" // __ LoadConst32(mips::V0, -32769);
- "ori $v0, 32767\n" // "
- "lui $v0, 65535\n" // __ LoadConst32(mips::V0, -65536);
- "lui $v0, 65534\n" // __ LoadConst32(mips::V0, -65537);
- "ori $v0, 65535\n" // "
- "lui $v0, 32768\n" // __ LoadConst32(mips::V0, -2147483647);
- "ori $v0, 1\n" // "
- "lui $v0, 32768\n"; // __ LoadConst32(mips::V0, -2147483648);
- DriverStr(expected, "LoadConst32");
-}
-
-TEST_F(AssemblerMIPSTest, LoadFarthestNearLabelAddress) {
- mips::MipsLabel label;
- __ BindPcRelBaseLabel();
- __ LoadLabelAddress(mips::V0, mips::V1, &label);
- constexpr size_t kAddiuCount = 0x1FDE;
- for (size_t i = 0; i != kAddiuCount; ++i) {
- __ Addiu(mips::A0, mips::A1, 0);
- }
- __ Bind(&label);
-
- std::string expected =
- "1:\n"
- "addiu $v0, $v1, %lo(2f - 1b)\n" +
- RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
- "2:\n";
- DriverStr(expected, "LoadFarthestNearLabelAddress");
-}
-
-TEST_F(AssemblerMIPSTest, LoadNearestFarLabelAddress) {
- mips::MipsLabel label;
- __ BindPcRelBaseLabel();
- __ LoadLabelAddress(mips::V0, mips::V1, &label);
- constexpr size_t kAdduCount = 0x1FDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- "1:\n"
- "lui $at, %hi(2f - 1b)\n"
- "ori $at, $at, %lo(2f - 1b)\n"
- "addu $v0, $at, $v1\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n";
- DriverStr(expected, "LoadNearestFarLabelAddress");
-}
-
-TEST_F(AssemblerMIPSTest, LoadFarthestNearLabelAddressUsingNal) {
- mips::MipsLabel label;
- __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
- constexpr size_t kAddiuCount = 0x1FDE;
- for (size_t i = 0; i != kAddiuCount; ++i) {
- __ Addiu(mips::A0, mips::A1, 0);
- }
- __ Bind(&label);
-
- std::string expected =
- ".set noreorder\n"
- "bltzal $zero, .+4\n"
- "addiu $v0, $ra, %lo(2f - 1f)\n"
- "1:\n" +
- RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
- "2:\n";
- DriverStr(expected, "LoadFarthestNearLabelAddressUsingNal");
-}
-
-TEST_F(AssemblerMIPSTest, LoadNearestFarLabelAddressUsingNal) {
- mips::MipsLabel label;
- __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
- constexpr size_t kAdduCount = 0x1FDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- ".set noreorder\n"
- "bltzal $zero, .+4\n"
- "lui $at, %hi(2f - 1f)\n"
- "1:\n"
- "ori $at, $at, %lo(2f - 1b)\n"
- "addu $v0, $at, $ra\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n";
- DriverStr(expected, "LoadNearestFarLabelAddressUsingNal");
-}
-
-TEST_F(AssemblerMIPSTest, LoadFarthestNearLiteral) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ BindPcRelBaseLabel();
- __ LoadLiteral(mips::V0, mips::V1, literal);
- constexpr size_t kAddiuCount = 0x1FDE;
- for (size_t i = 0; i != kAddiuCount; ++i) {
- __ Addiu(mips::A0, mips::A1, 0);
- }
-
- std::string expected =
- "1:\n"
- "lw $v0, %lo(2f - 1b)($v1)\n" +
- RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadFarthestNearLiteral");
-}
-
-TEST_F(AssemblerMIPSTest, LoadNearestFarLiteral) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ BindPcRelBaseLabel();
- __ LoadLiteral(mips::V0, mips::V1, literal);
- constexpr size_t kAdduCount = 0x1FDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
-
- std::string expected =
- "1:\n"
- "lui $at, %hi(2f - 1b)\n"
- "addu $at, $at, $v1\n"
- "lw $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadNearestFarLiteral");
-}
-
-TEST_F(AssemblerMIPSTest, LoadFarthestNearLiteralUsingNal) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips::V0, mips::ZERO, literal);
- constexpr size_t kAddiuCount = 0x1FDE;
- for (size_t i = 0; i != kAddiuCount; ++i) {
- __ Addiu(mips::A0, mips::A1, 0);
- }
-
- std::string expected =
- ".set noreorder\n"
- "bltzal $zero, .+4\n"
- "lw $v0, %lo(2f - 1f)($ra)\n"
- "1:\n" +
- RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadFarthestNearLiteralUsingNal");
-}
-
-TEST_F(AssemblerMIPSTest, LoadNearestFarLiteralUsingNal) {
- mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips::V0, mips::ZERO, literal);
- constexpr size_t kAdduCount = 0x1FDF;
- for (size_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
- }
-
- std::string expected =
- ".set noreorder\n"
- "bltzal $zero, .+4\n"
- "lui $at, %hi(2f - 1f)\n"
- "1:\n"
- "addu $at, $at, $ra\n"
- "lw $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadNearestFarLiteralUsingNal");
-}
-
-#undef __
-
-} // namespace art
diff --git a/compiler/utils/mips/constants_mips.h b/compiler/utils/mips/constants_mips.h
deleted file mode 100644
index 07d8b7d..0000000
--- a/compiler/utils/mips/constants_mips.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS_CONSTANTS_MIPS_H_
-#define ART_COMPILER_UTILS_MIPS_CONSTANTS_MIPS_H_
-
-#include <iosfwd>
-
-#include <android-base/logging.h>
-
-#include "arch/mips/registers_mips.h"
-#include "base/globals.h"
-#include "base/macros.h"
-
-namespace art {
-namespace mips {
-
-// Values for double-precision floating point registers.
-enum DRegister {
- D0 = 0,
- D1 = 1,
- D2 = 2,
- D3 = 3,
- D4 = 4,
- D5 = 5,
- D6 = 6,
- D7 = 7,
- D8 = 8,
- D9 = 9,
- D10 = 10,
- D11 = 11,
- D12 = 12,
- D13 = 13,
- D14 = 14,
- D15 = 15,
- kNumberOfDRegisters = 16,
- kNumberOfOverlappingDRegisters = 16,
- kNoDRegister = -1,
-};
-std::ostream& operator<<(std::ostream& os, const DRegister& rhs);
-
-// Constants used for the decoding or encoding of the individual fields of instructions.
-enum InstructionFields {
- kOpcodeShift = 26,
- kOpcodeBits = 6,
- kRsShift = 21,
- kRsBits = 5,
- kRtShift = 16,
- kRtBits = 5,
- kRdShift = 11,
- kRdBits = 5,
- kShamtShift = 6,
- kShamtBits = 5,
- kFunctShift = 0,
- kFunctBits = 6,
-
- kFmtShift = 21,
- kFmtBits = 5,
- kFtShift = 16,
- kFtBits = 5,
- kFsShift = 11,
- kFsBits = 5,
- kFdShift = 6,
- kFdBits = 5,
-
- kMsaOperationShift = 23,
- kMsaELMOperationShift = 22,
- kMsa2ROperationShift = 18,
- kMsa2RFOperationShift = 17,
- kDfShift = 21,
- kDfMShift = 16,
- kDf2RShift = 16,
- kDfNShift = 16,
- kWtShift = 16,
- kWtBits = 5,
- kWsShift = 11,
- kWsBits = 5,
- kWdShift = 6,
- kWdBits = 5,
- kS10Shift = 16,
- kI10Shift = 11,
- kS10MinorShift = 2,
-
- kBranchOffsetMask = 0x0000ffff,
- kJumpOffsetMask = 0x03ffffff,
-
- kMsaMajorOpcode = 0x1e,
- kMsaDfMByteMask = 0x70,
- kMsaDfMHalfwordMask = 0x60,
- kMsaDfMWordMask = 0x40,
- kMsaDfMDoublewordMask = 0x00,
- kMsaDfNByteMask = 0x00,
- kMsaDfNHalfwordMask = 0x20,
- kMsaDfNWordMask = 0x30,
- kMsaDfNDoublewordMask = 0x38,
- kMsaS10Mask = 0x3ff,
-};
-
-enum ScaleFactor {
- TIMES_1 = 0,
- TIMES_2 = 1,
- TIMES_4 = 2,
- TIMES_8 = 3
-};
-
-class Instr {
- public:
- static const uint32_t kBreakPointInstruction = 0x0000000D;
-
- bool IsBreakPoint() {
- return ((*reinterpret_cast<const uint32_t*>(this)) & 0xFC0000CF) == kBreakPointInstruction;
- }
-
- // Instructions are read out of a code stream. The only way to get a
- // reference to an instruction is to convert a pointer. There is no way
- // to allocate or create instances of class Instr.
- // Use the At(pc) function to create references to Instr.
- static Instr* At(uintptr_t pc) { return reinterpret_cast<Instr*>(pc); }
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
-};
-
-} // namespace mips
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS_CONSTANTS_MIPS_H_
diff --git a/compiler/utils/mips/managed_register_mips.cc b/compiler/utils/mips/managed_register_mips.cc
deleted file mode 100644
index 9b3ed79..0000000
--- a/compiler/utils/mips/managed_register_mips.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include "managed_register_mips.h"
-
-#include "base/globals.h"
-
-namespace art {
-namespace mips {
-
-bool MipsManagedRegister::Overlaps(const MipsManagedRegister& other) const {
- if (IsNoRegister() || other.IsNoRegister()) return false;
- CHECK(IsValidManagedRegister());
- CHECK(other.IsValidManagedRegister());
- if (Equals(other)) return true;
- if (IsRegisterPair()) {
- Register low = AsRegisterPairLow();
- Register high = AsRegisterPairHigh();
- return MipsManagedRegister::FromCoreRegister(low).Overlaps(other) ||
- MipsManagedRegister::FromCoreRegister(high).Overlaps(other);
- }
- if (IsOverlappingDRegister()) {
- if (other.IsDRegister()) return Equals(other);
- if (other.IsFRegister()) {
- FRegister low = AsOverlappingDRegisterLow();
- FRegister high = AsOverlappingDRegisterHigh();
- FRegister other_freg = other.AsFRegister();
- return (low == other_freg) || (high == other_freg);
- }
- return false;
- }
- if (other.IsRegisterPair() || other.IsOverlappingDRegister()) {
- return other.Overlaps(*this);
- }
- return false;
-}
-
-
-int MipsManagedRegister::AllocIdLow() const {
- CHECK(IsOverlappingDRegister() || IsRegisterPair());
- const int r = RegId() - (kNumberOfCoreRegIds + kNumberOfFRegIds);
- int low;
- if (r < kNumberOfOverlappingDRegIds) {
- CHECK(IsOverlappingDRegister());
- low = (r * 2) + kNumberOfCoreRegIds; // Return an FRegister.
- } else {
- CHECK(IsRegisterPair());
- low = (r - kNumberOfDRegIds) * 2 + 2; // Return a Register.
- if (low >= 24) {
- // we got a pair higher than S6_S7, must be the dalvik special case
- low = 5;
- }
- }
- return low;
-}
-
-
-int MipsManagedRegister::AllocIdHigh() const {
- return AllocIdLow() + 1;
-}
-
-
-void MipsManagedRegister::Print(std::ostream& os) const {
- if (!IsValidManagedRegister()) {
- os << "No Register";
- } else if (IsCoreRegister()) {
- os << "Core: " << static_cast<int>(AsCoreRegister());
- } else if (IsRegisterPair()) {
- os << "Pair: " << AsRegisterPairLow() << ", " << AsRegisterPairHigh();
- } else if (IsFRegister()) {
- os << "FRegister: " << static_cast<int>(AsFRegister());
- } else if (IsDRegister()) {
- os << "DRegister: " << static_cast<int>(AsDRegister());
- } else {
- os << "??: " << RegId();
- }
-}
-
-std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg) {
- reg.Print(os);
- return os;
-}
-
-std::ostream& operator<<(std::ostream& os, const RegisterPair& reg) {
- os << MipsManagedRegister::FromRegisterPair(reg);
- return os;
-}
-
-} // namespace mips
-} // namespace art
diff --git a/compiler/utils/mips/managed_register_mips.h b/compiler/utils/mips/managed_register_mips.h
deleted file mode 100644
index 18d5821..0000000
--- a/compiler/utils/mips/managed_register_mips.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
-#define ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
-
-#include "constants_mips.h"
-#include "utils/managed_register.h"
-
-namespace art {
-namespace mips {
-
-// Values for register pairs.
-enum RegisterPair {
- V0_V1 = 0,
- A0_A1 = 1,
- A2_A3 = 2,
- T0_T1 = 3,
- T2_T3 = 4,
- T4_T5 = 5,
- T6_T7 = 6,
- S0_S1 = 7,
- S2_S3 = 8,
- S4_S5 = 9,
- S6_S7 = 10,
- A1_A2 = 11, // Dalvik style passing
- kNumberOfRegisterPairs = 12,
- kNoRegisterPair = -1,
-};
-
-std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
-
-const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
-const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
-
-const int kNumberOfFRegIds = kNumberOfFRegisters;
-const int kNumberOfFAllocIds = kNumberOfFRegisters;
-
-const int kNumberOfDRegIds = kNumberOfDRegisters;
-const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
-const int kNumberOfDAllocIds = kNumberOfDRegisters;
-
-const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
-
-const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfFRegIds +
- kNumberOfDRegIds + kNumberOfPairRegIds;
-const int kNumberOfAllocIds =
- kNumberOfCoreAllocIds + kNumberOfFAllocIds + kNumberOfDAllocIds;
-
-// Register ids map:
-// [0..R[ core registers (enum Register)
-// [R..F[ single precision FP registers (enum FRegister)
-// [F..D[ double precision FP registers (enum DRegister)
-// [D..P[ core register pairs (enum RegisterPair)
-// where
-// R = kNumberOfCoreRegIds
-// F = R + kNumberOfFRegIds
-// D = F + kNumberOfDRegIds
-// P = D + kNumberOfRegisterPairs
-
-// Allocation ids map:
-// [0..R[ core registers (enum Register)
-// [R..F[ single precision FP registers (enum FRegister)
-// where
-// R = kNumberOfCoreRegIds
-// F = R + kNumberOfFRegIds
-
-
-// An instance of class 'ManagedRegister' represents a single core register (enum
-// Register), a single precision FP register (enum FRegister), a double precision
-// FP register (enum DRegister), or a pair of core registers (enum RegisterPair).
-// 'ManagedRegister::NoRegister()' provides an invalid register.
-// There is a one-to-one mapping between ManagedRegister and register id.
-class MipsManagedRegister : public ManagedRegister {
- public:
- constexpr Register AsCoreRegister() const {
- CHECK(IsCoreRegister());
- return static_cast<Register>(id_);
- }
-
- constexpr FRegister AsFRegister() const {
- CHECK(IsFRegister());
- return static_cast<FRegister>(id_ - kNumberOfCoreRegIds);
- }
-
- constexpr DRegister AsDRegister() const {
- CHECK(IsDRegister());
- return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds);
- }
-
- constexpr FRegister AsOverlappingDRegisterLow() const {
- CHECK(IsOverlappingDRegister());
- DRegister d_reg = AsDRegister();
- return static_cast<FRegister>(d_reg * 2);
- }
-
- constexpr FRegister AsOverlappingDRegisterHigh() const {
- CHECK(IsOverlappingDRegister());
- DRegister d_reg = AsDRegister();
- return static_cast<FRegister>(d_reg * 2 + 1);
- }
-
- constexpr Register AsRegisterPairLow() const {
- CHECK(IsRegisterPair());
- // Appropriate mapping of register ids allows to use AllocIdLow().
- return FromRegId(AllocIdLow()).AsCoreRegister();
- }
-
- constexpr Register AsRegisterPairHigh() const {
- CHECK(IsRegisterPair());
- // Appropriate mapping of register ids allows to use AllocIdHigh().
- return FromRegId(AllocIdHigh()).AsCoreRegister();
- }
-
- constexpr bool IsCoreRegister() const {
- CHECK(IsValidManagedRegister());
- return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
- }
-
- constexpr bool IsFRegister() const {
- CHECK(IsValidManagedRegister());
- const int test = id_ - kNumberOfCoreRegIds;
- return (0 <= test) && (test < kNumberOfFRegIds);
- }
-
- constexpr bool IsDRegister() const {
- CHECK(IsValidManagedRegister());
- const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
- return (0 <= test) && (test < kNumberOfDRegIds);
- }
-
- // Returns true if this DRegister overlaps FRegisters.
- constexpr bool IsOverlappingDRegister() const {
- CHECK(IsValidManagedRegister());
- const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
- return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
- }
-
- constexpr bool IsRegisterPair() const {
- CHECK(IsValidManagedRegister());
- const int test =
- id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds);
- return (0 <= test) && (test < kNumberOfPairRegIds);
- }
-
- void Print(std::ostream& os) const;
-
- // Returns true if the two managed-registers ('this' and 'other') overlap.
- // Either managed-register may be the NoRegister. If both are the NoRegister
- // then false is returned.
- bool Overlaps(const MipsManagedRegister& other) const;
-
- static constexpr MipsManagedRegister FromCoreRegister(Register r) {
- CHECK_NE(r, kNoRegister);
- return FromRegId(r);
- }
-
- static constexpr MipsManagedRegister FromFRegister(FRegister r) {
- CHECK_NE(r, kNoFRegister);
- return FromRegId(r + kNumberOfCoreRegIds);
- }
-
- static constexpr MipsManagedRegister FromDRegister(DRegister r) {
- CHECK_NE(r, kNoDRegister);
- return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds);
- }
-
- static constexpr MipsManagedRegister FromRegisterPair(RegisterPair r) {
- CHECK_NE(r, kNoRegisterPair);
- return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds));
- }
-
- private:
- constexpr bool IsValidManagedRegister() const {
- return (0 <= id_) && (id_ < kNumberOfRegIds);
- }
-
- constexpr int RegId() const {
- CHECK(!IsNoRegister());
- return id_;
- }
-
- int AllocId() const {
- CHECK(IsValidManagedRegister() && !IsOverlappingDRegister() && !IsRegisterPair());
- CHECK_LT(id_, kNumberOfAllocIds);
- return id_;
- }
-
- int AllocIdLow() const;
- int AllocIdHigh() const;
-
- friend class ManagedRegister;
-
- explicit constexpr MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
-
- static constexpr MipsManagedRegister FromRegId(int reg_id) {
- MipsManagedRegister reg(reg_id);
- CHECK(reg.IsValidManagedRegister());
- return reg;
- }
-};
-
-std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg);
-
-} // namespace mips
-
-constexpr inline mips::MipsManagedRegister ManagedRegister::AsMips() const {
- mips::MipsManagedRegister reg(id_);
- CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
- return reg;
-}
-
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
deleted file mode 100644
index 07d3716..0000000
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ /dev/null
@@ -1,4112 +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 "assembler_mips64.h"
-
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/memory_region.h"
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "entrypoints/quick/quick_entrypoints_enum.h"
-#include "thread.h"
-
-namespace art {
-namespace mips64 {
-
-static_assert(static_cast<size_t>(kMips64PointerSize) == kMips64DoublewordSize,
- "Unexpected Mips64 pointer size.");
-static_assert(kMips64PointerSize == PointerSize::k64, "Unexpected Mips64 pointer size.");
-
-
-void Mips64Assembler::FinalizeCode() {
- for (auto& exception_block : exception_blocks_) {
- EmitExceptionPoll(&exception_block);
- }
- ReserveJumpTableSpace();
- EmitLiterals();
- PromoteBranches();
-}
-
-void Mips64Assembler::FinalizeInstructions(const MemoryRegion& region) {
- EmitBranches();
- EmitJumpTables();
- Assembler::FinalizeInstructions(region);
- PatchCFI();
-}
-
-void Mips64Assembler::PatchCFI() {
- if (cfi().NumberOfDelayedAdvancePCs() == 0u) {
- return;
- }
-
- using DelayedAdvancePC = DebugFrameOpCodeWriterForAssembler::DelayedAdvancePC;
- const auto data = cfi().ReleaseStreamAndPrepareForDelayedAdvancePC();
- const std::vector<uint8_t>& old_stream = data.first;
- const std::vector<DelayedAdvancePC>& advances = data.second;
-
- // Refill our data buffer with patched opcodes.
- cfi().ReserveCFIStream(old_stream.size() + advances.size() + 16);
- size_t stream_pos = 0;
- for (const DelayedAdvancePC& advance : advances) {
- DCHECK_GE(advance.stream_pos, stream_pos);
- // Copy old data up to the point where advance was issued.
- cfi().AppendRawData(old_stream, stream_pos, advance.stream_pos);
- stream_pos = advance.stream_pos;
- // Insert the advance command with its final offset.
- size_t final_pc = GetAdjustedPosition(advance.pc);
- cfi().AdvancePC(final_pc);
- }
- // Copy the final segment if any.
- cfi().AppendRawData(old_stream, stream_pos, old_stream.size());
-}
-
-void Mips64Assembler::EmitBranches() {
- CHECK(!overwriting_);
- // Switch from appending instructions at the end of the buffer to overwriting
- // existing instructions (branch placeholders) in the buffer.
- overwriting_ = true;
- for (auto& branch : branches_) {
- EmitBranch(&branch);
- }
- overwriting_ = false;
-}
-
-void Mips64Assembler::Emit(uint32_t value) {
- if (overwriting_) {
- // Branches to labels are emitted into their placeholders here.
- buffer_.Store<uint32_t>(overwrite_location_, value);
- overwrite_location_ += sizeof(uint32_t);
- } else {
- // Other instructions are simply appended at the end here.
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- buffer_.Emit<uint32_t>(value);
- }
-}
-
-void Mips64Assembler::EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd,
- int shamt, int funct) {
- CHECK_NE(rs, kNoGpuRegister);
- CHECK_NE(rt, kNoGpuRegister);
- CHECK_NE(rd, kNoGpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- static_cast<uint32_t>(rt) << kRtShift |
- static_cast<uint32_t>(rd) << kRdShift |
- shamt << kShamtShift |
- funct;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitRsd(int opcode, GpuRegister rs, GpuRegister rd,
- int shamt, int funct) {
- CHECK_NE(rs, kNoGpuRegister);
- CHECK_NE(rd, kNoGpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- static_cast<uint32_t>(ZERO) << kRtShift |
- static_cast<uint32_t>(rd) << kRdShift |
- shamt << kShamtShift |
- funct;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitRtd(int opcode, GpuRegister rt, GpuRegister rd,
- int shamt, int funct) {
- CHECK_NE(rt, kNoGpuRegister);
- CHECK_NE(rd, kNoGpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(ZERO) << kRsShift |
- static_cast<uint32_t>(rt) << kRtShift |
- static_cast<uint32_t>(rd) << kRdShift |
- shamt << kShamtShift |
- funct;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm) {
- CHECK_NE(rs, kNoGpuRegister);
- CHECK_NE(rt, kNoGpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- static_cast<uint32_t>(rt) << kRtShift |
- imm;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitI21(int opcode, GpuRegister rs, uint32_t imm21) {
- CHECK_NE(rs, kNoGpuRegister);
- CHECK(IsUint<21>(imm21)) << imm21;
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- static_cast<uint32_t>(rs) << kRsShift |
- imm21;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitI26(int opcode, uint32_t imm26) {
- CHECK(IsUint<26>(imm26)) << imm26;
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | imm26;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd,
- int funct) {
- CHECK_NE(ft, kNoFpuRegister);
- CHECK_NE(fs, kNoFpuRegister);
- CHECK_NE(fd, kNoFpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- fmt << kFmtShift |
- static_cast<uint32_t>(ft) << kFtShift |
- static_cast<uint32_t>(fs) << kFsShift |
- static_cast<uint32_t>(fd) << kFdShift |
- funct;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitFI(int opcode, int fmt, FpuRegister ft, uint16_t imm) {
- CHECK_NE(ft, kNoFpuRegister);
- uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift |
- fmt << kFmtShift |
- static_cast<uint32_t>(ft) << kFtShift |
- imm;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsa3R(int operation,
- int df,
- VectorRegister wt,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(wt, kNoVectorRegister);
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df << kDfShift |
- static_cast<uint32_t>(wt) << kWtShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsaBIT(int operation,
- int df_m,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df_m << kDfMShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsaELM(int operation,
- int df_n,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaELMOperationShift |
- df_n << kDfNShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsaMI10(int s10,
- GpuRegister rs,
- VectorRegister wd,
- int minor_opcode,
- int df) {
- CHECK_NE(rs, kNoGpuRegister);
- CHECK_NE(wd, kNoVectorRegister);
- CHECK(IsUint<10>(s10)) << s10;
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- s10 << kS10Shift |
- static_cast<uint32_t>(rs) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode << kS10MinorShift |
- df;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsaI10(int operation,
- int df,
- int i10,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(wd, kNoVectorRegister);
- CHECK(IsUint<10>(i10)) << i10;
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsaOperationShift |
- df << kDfShift |
- i10 << kI10Shift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsa2R(int operation,
- int df,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsa2ROperationShift |
- df << kDf2RShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::EmitMsa2RF(int operation,
- int df,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode) {
- CHECK_NE(ws, kNoVectorRegister);
- CHECK_NE(wd, kNoVectorRegister);
- uint32_t encoding = static_cast<uint32_t>(kMsaMajorOpcode) << kOpcodeShift |
- operation << kMsa2RFOperationShift |
- df << kDf2RShift |
- static_cast<uint32_t>(ws) << kWsShift |
- static_cast<uint32_t>(wd) << kWdShift |
- minor_opcode;
- Emit(encoding);
-}
-
-void Mips64Assembler::Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x21);
-}
-
-void Mips64Assembler::Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x9, rs, rt, imm16);
-}
-
-void Mips64Assembler::Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x2d);
-}
-
-void Mips64Assembler::Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x19, rs, rt, imm16);
-}
-
-void Mips64Assembler::Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x23);
-}
-
-void Mips64Assembler::Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x2f);
-}
-
-void Mips64Assembler::MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x18);
-}
-
-void Mips64Assembler::MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x18);
-}
-
-void Mips64Assembler::DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x1a);
-}
-
-void Mips64Assembler::ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x1a);
-}
-
-void Mips64Assembler::DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x1b);
-}
-
-void Mips64Assembler::ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x1b);
-}
-
-void Mips64Assembler::Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x1c);
-}
-
-void Mips64Assembler::Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x1c);
-}
-
-void Mips64Assembler::Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x1e);
-}
-
-void Mips64Assembler::Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x1e);
-}
-
-void Mips64Assembler::Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 2, 0x1f);
-}
-
-void Mips64Assembler::Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 3, 0x1f);
-}
-
-void Mips64Assembler::And(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x24);
-}
-
-void Mips64Assembler::Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xc, rs, rt, imm16);
-}
-
-void Mips64Assembler::Or(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x25);
-}
-
-void Mips64Assembler::Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xd, rs, rt, imm16);
-}
-
-void Mips64Assembler::Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x26);
-}
-
-void Mips64Assembler::Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xe, rs, rt, imm16);
-}
-
-void Mips64Assembler::Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x27);
-}
-
-void Mips64Assembler::Bitswap(GpuRegister rd, GpuRegister rt) {
- EmitRtd(0x1f, rt, rd, 0x0, 0x20);
-}
-
-void Mips64Assembler::Dbitswap(GpuRegister rd, GpuRegister rt) {
- EmitRtd(0x1f, rt, rd, 0x0, 0x24);
-}
-
-void Mips64Assembler::Seb(GpuRegister rd, GpuRegister rt) {
- EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x10, 0x20);
-}
-
-void Mips64Assembler::Seh(GpuRegister rd, GpuRegister rt) {
- EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x18, 0x20);
-}
-
-void Mips64Assembler::Dsbh(GpuRegister rd, GpuRegister rt) {
- EmitRtd(0x1f, rt, rd, 0x2, 0x24);
-}
-
-void Mips64Assembler::Dshd(GpuRegister rd, GpuRegister rt) {
- EmitRtd(0x1f, rt, rd, 0x5, 0x24);
-}
-
-void Mips64Assembler::Dext(GpuRegister rt, GpuRegister rs, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(IsUint<5>(size - 1)) << size;
- EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size - 1), pos, 0x3);
-}
-
-void Mips64Assembler::Ins(GpuRegister rd, GpuRegister rt, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(IsUint<5>(size - 1)) << size;
- CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
- EmitR(0x1f, rt, rd, static_cast<GpuRegister>(pos + size - 1), pos, 0x04);
-}
-
-void Mips64Assembler::Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(2 <= size && size <= 64) << size;
- CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
- EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos, 0x5);
-}
-
-void Mips64Assembler::Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size) {
- CHECK(IsUint<5>(pos - 32)) << pos;
- CHECK(IsUint<5>(size - 1)) << size;
- CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
- EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 33), pos - 32, 0x6);
-}
-
-void Mips64Assembler::Dins(GpuRegister rt, GpuRegister rs, int pos, int size) {
- CHECK(IsUint<5>(pos)) << pos;
- CHECK(IsUint<5>(size - 1)) << size;
- CHECK(IsUint<5>(pos + size - 1)) << pos << " + " << size;
- EmitR(0x1f, rs, rt, static_cast<GpuRegister>(pos + size - 1), pos, 0x7);
-}
-
-void Mips64Assembler::DblIns(GpuRegister rt, GpuRegister rs, int pos, int size) {
- if (pos >= 32) {
- Dinsu(rt, rs, pos, size);
- } else if ((static_cast<int64_t>(pos) + size - 1) >= 32) {
- Dinsm(rt, rs, pos, size);
- } else {
- Dins(rt, rs, pos, size);
- }
-}
-
-void Mips64Assembler::Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
- CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
- int sa = saPlusOne - 1;
- EmitR(0x0, rs, rt, rd, sa, 0x05);
-}
-
-void Mips64Assembler::Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne) {
- CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
- int sa = saPlusOne - 1;
- EmitR(0x0, rs, rt, rd, sa, 0x15);
-}
-
-void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) {
- EmitRtd(0x1f, rt, rd, 2, 0x20);
-}
-
-void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) {
- CHECK(IsInt<9>(imm9));
- EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26);
-}
-
-void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) {
- CHECK(IsInt<9>(imm9));
- EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27);
-}
-
-void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) {
- CHECK(IsInt<9>(imm9));
- EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36);
-}
-
-void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) {
- CHECK(IsInt<9>(imm9));
- EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37);
-}
-
-void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00);
-}
-
-void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02);
-}
-
-void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02);
-}
-
-void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03);
-}
-
-void Mips64Assembler::Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x04);
-}
-
-void Mips64Assembler::Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 1, 0x06);
-}
-
-void Mips64Assembler::Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x06);
-}
-
-void Mips64Assembler::Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x07);
-}
-
-void Mips64Assembler::Dsll(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x38);
-}
-
-void Mips64Assembler::Dsrl(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3a);
-}
-
-void Mips64Assembler::Drotr(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3a);
-}
-
-void Mips64Assembler::Dsra(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3b);
-}
-
-void Mips64Assembler::Dsll32(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3c);
-}
-
-void Mips64Assembler::Dsrl32(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3e);
-}
-
-void Mips64Assembler::Drotr32(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x3e);
-}
-
-void Mips64Assembler::Dsra32(GpuRegister rd, GpuRegister rt, int shamt) {
- EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x3f);
-}
-
-void Mips64Assembler::Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x14);
-}
-
-void Mips64Assembler::Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x16);
-}
-
-void Mips64Assembler::Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 1, 0x16);
-}
-
-void Mips64Assembler::Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs) {
- EmitR(0, rs, rt, rd, 0, 0x17);
-}
-
-void Mips64Assembler::Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x20, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x21, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x23, rs, rt, imm16);
-}
-
-void Mips64Assembler::Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x37, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x24, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x25, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x27, rs, rt, imm16);
-}
-
-void Mips64Assembler::Lwpc(GpuRegister rs, uint32_t imm19) {
- CHECK(IsUint<19>(imm19)) << imm19;
- EmitI21(0x3B, rs, (0x01 << 19) | imm19);
-}
-
-void Mips64Assembler::Lwupc(GpuRegister rs, uint32_t imm19) {
- CHECK(IsUint<19>(imm19)) << imm19;
- EmitI21(0x3B, rs, (0x02 << 19) | imm19);
-}
-
-void Mips64Assembler::Ldpc(GpuRegister rs, uint32_t imm18) {
- CHECK(IsUint<18>(imm18)) << imm18;
- EmitI21(0x3B, rs, (0x06 << 18) | imm18);
-}
-
-void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) {
- EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16);
-}
-
-void Mips64Assembler::Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xf, rs, rt, imm16);
-}
-
-void Mips64Assembler::Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- EmitI(0x1d, rs, rt, imm16);
-}
-
-void Mips64Assembler::Dahi(GpuRegister rs, uint16_t imm16) {
- EmitI(1, rs, static_cast<GpuRegister>(6), imm16);
-}
-
-void Mips64Assembler::Dati(GpuRegister rs, uint16_t imm16) {
- EmitI(1, rs, static_cast<GpuRegister>(0x1e), imm16);
-}
-
-void Mips64Assembler::Sync(uint32_t stype) {
- EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
- static_cast<GpuRegister>(0), stype & 0x1f, 0xf);
-}
-
-void Mips64Assembler::Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x28, rs, rt, imm16);
-}
-
-void Mips64Assembler::Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x29, rs, rt, imm16);
-}
-
-void Mips64Assembler::Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x2b, rs, rt, imm16);
-}
-
-void Mips64Assembler::Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0x3f, rs, rt, imm16);
-}
-
-void Mips64Assembler::Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x2a);
-}
-
-void Mips64Assembler::Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x2b);
-}
-
-void Mips64Assembler::Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xa, rs, rt, imm16);
-}
-
-void Mips64Assembler::Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
- EmitI(0xb, rs, rt, imm16);
-}
-
-void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x35);
-}
-
-void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) {
- EmitR(0, rs, rt, rd, 0, 0x37);
-}
-
-void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) {
- EmitRsd(0, rs, rd, 0x01, 0x10);
-}
-
-void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) {
- EmitRsd(0, rs, rd, 0x01, 0x11);
-}
-
-void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) {
- EmitRsd(0, rs, rd, 0x01, 0x12);
-}
-
-void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) {
- EmitRsd(0, rs, rd, 0x01, 0x13);
-}
-
-void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) {
- EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09);
-}
-
-void Mips64Assembler::Jalr(GpuRegister rs) {
- Jalr(RA, rs);
-}
-
-void Mips64Assembler::Jr(GpuRegister rs) {
- Jalr(ZERO, rs);
-}
-
-void Mips64Assembler::Auipc(GpuRegister rs, uint16_t imm16) {
- EmitI(0x3B, rs, static_cast<GpuRegister>(0x1E), imm16);
-}
-
-void Mips64Assembler::Addiupc(GpuRegister rs, uint32_t imm19) {
- CHECK(IsUint<19>(imm19)) << imm19;
- EmitI21(0x3B, rs, imm19);
-}
-
-void Mips64Assembler::Bc(uint32_t imm26) {
- EmitI26(0x32, imm26);
-}
-
-void Mips64Assembler::Balc(uint32_t imm26) {
- EmitI26(0x3A, imm26);
-}
-
-void Mips64Assembler::Jic(GpuRegister rt, uint16_t imm16) {
- EmitI(0x36, static_cast<GpuRegister>(0), rt, imm16);
-}
-
-void Mips64Assembler::Jialc(GpuRegister rt, uint16_t imm16) {
- EmitI(0x3E, static_cast<GpuRegister>(0), rt, imm16);
-}
-
-void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x17, rs, rt, imm16);
-}
-
-void Mips64Assembler::Bltzc(GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rt, ZERO);
- EmitI(0x17, rt, rt, imm16);
-}
-
-void Mips64Assembler::Bgtzc(GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rt, ZERO);
- EmitI(0x17, static_cast<GpuRegister>(0), rt, imm16);
-}
-
-void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x16, rs, rt, imm16);
-}
-
-void Mips64Assembler::Bgezc(GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rt, ZERO);
- EmitI(0x16, rt, rt, imm16);
-}
-
-void Mips64Assembler::Blezc(GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rt, ZERO);
- EmitI(0x16, static_cast<GpuRegister>(0), rt, imm16);
-}
-
-void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x7, rs, rt, imm16);
-}
-
-void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x6, rs, rt, imm16);
-}
-
-void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x8, std::min(rs, rt), std::max(rs, rt), imm16);
-}
-
-void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- CHECK_NE(rs, ZERO);
- CHECK_NE(rt, ZERO);
- CHECK_NE(rs, rt);
- EmitI(0x18, std::min(rs, rt), std::max(rs, rt), imm16);
-}
-
-void Mips64Assembler::Beqzc(GpuRegister rs, uint32_t imm21) {
- CHECK_NE(rs, ZERO);
- EmitI21(0x36, rs, imm21);
-}
-
-void Mips64Assembler::Bnezc(GpuRegister rs, uint32_t imm21) {
- CHECK_NE(rs, ZERO);
- EmitI21(0x3E, rs, imm21);
-}
-
-void Mips64Assembler::Bc1eqz(FpuRegister ft, uint16_t imm16) {
- EmitFI(0x11, 0x9, ft, imm16);
-}
-
-void Mips64Assembler::Bc1nez(FpuRegister ft, uint16_t imm16) {
- EmitFI(0x11, 0xD, ft, imm16);
-}
-
-void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- EmitI(0x4, rs, rt, imm16);
-}
-
-void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16) {
- EmitI(0x5, rs, rt, imm16);
-}
-
-void Mips64Assembler::Beqz(GpuRegister rt, uint16_t imm16) {
- Beq(rt, ZERO, imm16);
-}
-
-void Mips64Assembler::Bnez(GpuRegister rt, uint16_t imm16) {
- Bne(rt, ZERO, imm16);
-}
-
-void Mips64Assembler::Bltz(GpuRegister rt, uint16_t imm16) {
- EmitI(0x1, rt, static_cast<GpuRegister>(0), imm16);
-}
-
-void Mips64Assembler::Bgez(GpuRegister rt, uint16_t imm16) {
- EmitI(0x1, rt, static_cast<GpuRegister>(0x1), imm16);
-}
-
-void Mips64Assembler::Blez(GpuRegister rt, uint16_t imm16) {
- EmitI(0x6, rt, static_cast<GpuRegister>(0), imm16);
-}
-
-void Mips64Assembler::Bgtz(GpuRegister rt, uint16_t imm16) {
- EmitI(0x7, rt, static_cast<GpuRegister>(0), imm16);
-}
-
-void Mips64Assembler::EmitBcondR6(BranchCondition cond,
- GpuRegister rs,
- GpuRegister rt,
- uint32_t imm16_21) {
- switch (cond) {
- case kCondLT:
- Bltc(rs, rt, imm16_21);
- break;
- case kCondGE:
- Bgec(rs, rt, imm16_21);
- break;
- case kCondLE:
- Bgec(rt, rs, imm16_21);
- break;
- case kCondGT:
- Bltc(rt, rs, imm16_21);
- break;
- case kCondLTZ:
- CHECK_EQ(rt, ZERO);
- Bltzc(rs, imm16_21);
- break;
- case kCondGEZ:
- CHECK_EQ(rt, ZERO);
- Bgezc(rs, imm16_21);
- break;
- case kCondLEZ:
- CHECK_EQ(rt, ZERO);
- Blezc(rs, imm16_21);
- break;
- case kCondGTZ:
- CHECK_EQ(rt, ZERO);
- Bgtzc(rs, imm16_21);
- break;
- case kCondEQ:
- Beqc(rs, rt, imm16_21);
- break;
- case kCondNE:
- Bnec(rs, rt, imm16_21);
- break;
- case kCondEQZ:
- CHECK_EQ(rt, ZERO);
- Beqzc(rs, imm16_21);
- break;
- case kCondNEZ:
- CHECK_EQ(rt, ZERO);
- Bnezc(rs, imm16_21);
- break;
- case kCondLTU:
- Bltuc(rs, rt, imm16_21);
- break;
- case kCondGEU:
- Bgeuc(rs, rt, imm16_21);
- break;
- case kCondF:
- CHECK_EQ(rt, ZERO);
- Bc1eqz(static_cast<FpuRegister>(rs), imm16_21);
- break;
- case kCondT:
- CHECK_EQ(rt, ZERO);
- Bc1nez(static_cast<FpuRegister>(rs), imm16_21);
- break;
- case kUncond:
- LOG(FATAL) << "Unexpected branch condition " << cond;
- UNREACHABLE();
- }
-}
-
-void Mips64Assembler::EmitBcondR2(BranchCondition cond,
- GpuRegister rs,
- GpuRegister rt,
- uint16_t imm16) {
- switch (cond) {
- case kCondLTZ:
- CHECK_EQ(rt, ZERO);
- Bltz(rs, imm16);
- break;
- case kCondGEZ:
- CHECK_EQ(rt, ZERO);
- Bgez(rs, imm16);
- break;
- case kCondLEZ:
- CHECK_EQ(rt, ZERO);
- Blez(rs, imm16);
- break;
- case kCondGTZ:
- CHECK_EQ(rt, ZERO);
- Bgtz(rs, imm16);
- break;
- case kCondEQ:
- Beq(rs, rt, imm16);
- break;
- case kCondNE:
- Bne(rs, rt, imm16);
- break;
- case kCondEQZ:
- CHECK_EQ(rt, ZERO);
- Beqz(rs, imm16);
- break;
- case kCondNEZ:
- CHECK_EQ(rt, ZERO);
- Bnez(rs, imm16);
- break;
- case kCondF:
- case kCondT:
- case kCondLT:
- case kCondGE:
- case kCondLE:
- case kCondGT:
- case kCondLTU:
- case kCondGEU:
- case kUncond:
- LOG(FATAL) << "Unexpected branch condition " << cond;
- UNREACHABLE();
- }
-}
-
-void Mips64Assembler::AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
-}
-
-void Mips64Assembler::SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
-}
-
-void Mips64Assembler::MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
-}
-
-void Mips64Assembler::DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
-}
-
-void Mips64Assembler::AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x0);
-}
-
-void Mips64Assembler::SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x1);
-}
-
-void Mips64Assembler::MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x2);
-}
-
-void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
-}
-
-void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4);
-}
-
-void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4);
-}
-
-void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5);
-}
-
-void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5);
-}
-
-void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6);
-}
-
-void Mips64Assembler::MovD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x6);
-}
-
-void Mips64Assembler::NegS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x7);
-}
-
-void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7);
-}
-
-void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8);
-}
-
-void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8);
-}
-
-void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc);
-}
-
-void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc);
-}
-
-void Mips64Assembler::TruncLS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x9);
-}
-
-void Mips64Assembler::TruncLD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x9);
-}
-
-void Mips64Assembler::TruncWS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xd);
-}
-
-void Mips64Assembler::TruncWD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xd);
-}
-
-void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa);
-}
-
-void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa);
-}
-
-void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe);
-}
-
-void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe);
-}
-
-void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb);
-}
-
-void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb);
-}
-
-void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf);
-}
-
-void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf);
-}
-
-void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
-}
-
-void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
-}
-
-void Mips64Assembler::SeleqzS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x14);
-}
-
-void Mips64Assembler::SeleqzD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x14);
-}
-
-void Mips64Assembler::SelnezS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x17);
-}
-
-void Mips64Assembler::SelnezD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x17);
-}
-
-void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a);
-}
-
-void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a);
-}
-
-void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b);
-}
-
-void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b);
-}
-
-void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
-}
-
-void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
-}
-
-void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
-}
-
-void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
-}
-
-void Mips64Assembler::CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x01);
-}
-
-void Mips64Assembler::CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x02);
-}
-
-void Mips64Assembler::CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x03);
-}
-
-void Mips64Assembler::CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x04);
-}
-
-void Mips64Assembler::CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x05);
-}
-
-void Mips64Assembler::CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x06);
-}
-
-void Mips64Assembler::CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x07);
-}
-
-void Mips64Assembler::CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x11);
-}
-
-void Mips64Assembler::CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x12);
-}
-
-void Mips64Assembler::CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x14, ft, fs, fd, 0x13);
-}
-
-void Mips64Assembler::CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x01);
-}
-
-void Mips64Assembler::CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x02);
-}
-
-void Mips64Assembler::CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x03);
-}
-
-void Mips64Assembler::CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x04);
-}
-
-void Mips64Assembler::CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x05);
-}
-
-void Mips64Assembler::CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x06);
-}
-
-void Mips64Assembler::CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x07);
-}
-
-void Mips64Assembler::CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x11);
-}
-
-void Mips64Assembler::CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x12);
-}
-
-void Mips64Assembler::CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft) {
- EmitFR(0x11, 0x15, ft, fs, fd, 0x13);
-}
-
-void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20);
-}
-
-void Mips64Assembler::Cvtdw(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x21);
-}
-
-void Mips64Assembler::Cvtsd(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x20);
-}
-
-void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21);
-}
-
-void Mips64Assembler::Cvtsl(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x20);
-}
-
-void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) {
- EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21);
-}
-
-void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Mfhc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x03, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Mtc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x04, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Mthc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x07, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Dmfc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x01, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Dmtc1(GpuRegister rt, FpuRegister fs) {
- EmitFR(0x11, 0x05, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0);
-}
-
-void Mips64Assembler::Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
- EmitI(0x31, rs, static_cast<GpuRegister>(ft), imm16);
-}
-
-void Mips64Assembler::Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
- EmitI(0x35, rs, static_cast<GpuRegister>(ft), imm16);
-}
-
-void Mips64Assembler::Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
- EmitI(0x39, rs, static_cast<GpuRegister>(ft), imm16);
-}
-
-void Mips64Assembler::Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16) {
- EmitI(0x3d, rs, static_cast<GpuRegister>(ft), imm16);
-}
-
-void Mips64Assembler::Break() {
- EmitR(0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
- static_cast<GpuRegister>(0), 0, 0xD);
-}
-
-void Mips64Assembler::Nop() {
- EmitR(0x0, static_cast<GpuRegister>(0), static_cast<GpuRegister>(0),
- static_cast<GpuRegister>(0), 0, 0x0);
-}
-
-void Mips64Assembler::Move(GpuRegister rd, GpuRegister rs) {
- Or(rd, rs, ZERO);
-}
-
-void Mips64Assembler::Clear(GpuRegister rd) {
- Move(rd, ZERO);
-}
-
-void Mips64Assembler::Not(GpuRegister rd, GpuRegister rs) {
- Nor(rd, rs, ZERO);
-}
-
-void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11);
-}
-
-void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10);
-}
-
-void Mips64Assembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe);
-}
-
-void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
-}
-
-void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(shamt3)) << shamt3;
- EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(shamt4)) << shamt4;
- EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
- CHECK(HasMsa());
- CHECK(IsUint<5>(shamt5)) << shamt5;
- EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
- CHECK(HasMsa());
- CHECK(IsUint<6>(shamt6)) << shamt6;
- EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
-}
-
-void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
-}
-
-void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
-}
-
-void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
-}
-
-void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
-}
-
-void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
- CHECK(HasMsa());
- CHECK(IsUint<1>(n1)) << n1;
- EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
-}
-
-void Mips64Assembler::Copy_sB(GpuRegister rd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_sH(GpuRegister rd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_sW(GpuRegister rd, VectorRegister ws, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_sD(GpuRegister rd, VectorRegister ws, int n1) {
- CHECK(HasMsa());
- CHECK(IsUint<1>(n1)) << n1;
- EmitMsaELM(0x2, n1 | kMsaDfNDoublewordMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_uB(GpuRegister rd, VectorRegister ws, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_uH(GpuRegister rd, VectorRegister ws, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::Copy_uW(GpuRegister rd, VectorRegister ws, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- EmitMsaELM(0x3, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19);
-}
-
-void Mips64Assembler::InsertB(VectorRegister wd, GpuRegister rs, int n4) {
- CHECK(HasMsa());
- CHECK(IsUint<4>(n4)) << n4;
- EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19);
-}
-
-void Mips64Assembler::InsertH(VectorRegister wd, GpuRegister rs, int n3) {
- CHECK(HasMsa());
- CHECK(IsUint<3>(n3)) << n3;
- EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19);
-}
-
-void Mips64Assembler::InsertW(VectorRegister wd, GpuRegister rs, int n2) {
- CHECK(HasMsa());
- CHECK(IsUint<2>(n2)) << n2;
- EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19);
-}
-
-void Mips64Assembler::InsertD(VectorRegister wd, GpuRegister rs, int n1) {
- CHECK(HasMsa());
- CHECK(IsUint<1>(n1)) << n1;
- EmitMsaELM(0x4, n1 | kMsaDfNDoublewordMask, static_cast<VectorRegister>(rs), wd, 0x19);
-}
-
-void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
- CHECK(HasMsa());
- EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
-}
-
-void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
- CHECK(HasMsa());
- EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
-}
-
-void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
- CHECK(HasMsa());
- EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
-}
-
-void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
- CHECK(HasMsa());
- EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
-}
-
-void Mips64Assembler::LdiB(VectorRegister wd, int imm8) {
- CHECK(HasMsa());
- CHECK(IsInt<8>(imm8)) << imm8;
- EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7);
-}
-
-void Mips64Assembler::LdiH(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7);
-}
-
-void Mips64Assembler::LdiW(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7);
-}
-
-void Mips64Assembler::LdiD(VectorRegister wd, int imm10) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(imm10)) << imm10;
- EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7);
-}
-
-void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(offset)) << offset;
- EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
-}
-
-void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<11>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64HalfwordSize);
- EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
-}
-
-void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<12>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64WordSize);
- EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
-}
-
-void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<13>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64DoublewordSize);
- EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
-}
-
-void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<10>(offset)) << offset;
- EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
-}
-
-void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<11>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64HalfwordSize);
- EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
-}
-
-void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<12>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64WordSize);
- EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
-}
-
-void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
- CHECK(HasMsa());
- CHECK(IsInt<13>(offset)) << offset;
- CHECK_ALIGNED(offset, kMips64DoublewordSize);
- EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
-}
-
-void Mips64Assembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14);
-}
-
-void Mips64Assembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12);
-}
-
-void Mips64Assembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b);
-}
-
-void Mips64Assembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
- CHECK(HasMsa());
- EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15);
-}
-
-void Mips64Assembler::PcntB(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2R(0xc1, 0x0, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::PcntH(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2R(0xc1, 0x1, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::PcntW(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2R(0xc1, 0x2, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::PcntD(VectorRegister wd, VectorRegister ws) {
- CHECK(HasMsa());
- EmitMsa2R(0xc1, 0x3, ws, wd, 0x1e);
-}
-
-void Mips64Assembler::ReplicateFPToVectorRegister(VectorRegister dst,
- FpuRegister src,
- bool is_double) {
- // Float or double in FPU register Fx can be considered as 0th element in vector register Wx.
- if (is_double) {
- SplatiD(dst, static_cast<VectorRegister>(src), 0);
- } else {
- SplatiW(dst, static_cast<VectorRegister>(src), 0);
- }
-}
-
-void Mips64Assembler::LoadConst32(GpuRegister rd, int32_t value) {
- TemplateLoadConst32(this, rd, value);
-}
-
-// This function is only used for testing purposes.
-void Mips64Assembler::RecordLoadConst64Path(int value ATTRIBUTE_UNUSED) {
-}
-
-void Mips64Assembler::LoadConst64(GpuRegister rd, int64_t value) {
- TemplateLoadConst64(this, rd, value);
-}
-
-void Mips64Assembler::Addiu32(GpuRegister rt, GpuRegister rs, int32_t value) {
- if (IsInt<16>(value)) {
- Addiu(rt, rs, value);
- } else {
- int16_t high = High16Bits(value);
- int16_t low = Low16Bits(value);
- high += (low < 0) ? 1 : 0; // Account for sign extension in addiu.
- Aui(rt, rs, high);
- if (low != 0) {
- Addiu(rt, rt, low);
- }
- }
-}
-
-// TODO: don't use rtmp, use daui, dahi, dati.
-void Mips64Assembler::Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp) {
- CHECK_NE(rs, rtmp);
- if (IsInt<16>(value)) {
- Daddiu(rt, rs, value);
- } else {
- LoadConst64(rtmp, value);
- Daddu(rt, rs, rtmp);
- }
-}
-
-void Mips64Assembler::Branch::InitShortOrLong(Mips64Assembler::Branch::OffsetBits offset_size,
- Mips64Assembler::Branch::Type short_type,
- Mips64Assembler::Branch::Type long_type) {
- type_ = (offset_size <= branch_info_[short_type].offset_size) ? short_type : long_type;
-}
-
-void Mips64Assembler::Branch::InitializeType(Type initial_type, bool is_r6) {
- OffsetBits offset_size_needed = GetOffsetSizeNeeded(location_, target_);
- if (is_r6) {
- // R6
- switch (initial_type) {
- case kLabel:
- case kLiteral:
- case kLiteralUnsigned:
- case kLiteralLong:
- CHECK(!IsResolved());
- type_ = initial_type;
- break;
- case kCall:
- InitShortOrLong(offset_size_needed, kCall, kLongCall);
- break;
- case kCondBranch:
- switch (condition_) {
- case kUncond:
- InitShortOrLong(offset_size_needed, kUncondBranch, kLongUncondBranch);
- break;
- case kCondEQZ:
- case kCondNEZ:
- // Special case for beqzc/bnezc with longer offset than in other b<cond>c instructions.
- type_ = (offset_size_needed <= kOffset23) ? kCondBranch : kLongCondBranch;
- break;
- default:
- InitShortOrLong(offset_size_needed, kCondBranch, kLongCondBranch);
- break;
- }
- break;
- case kBareCall:
- type_ = kBareCall;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- case kBareCondBranch:
- type_ = (condition_ == kUncond) ? kBareUncondBranch : kBareCondBranch;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- break;
- default:
- LOG(FATAL) << "Unexpected branch type " << initial_type;
- UNREACHABLE();
- }
- } else {
- // R2
- CHECK_EQ(initial_type, kBareCondBranch);
- switch (condition_) {
- case kCondLTZ:
- case kCondGEZ:
- case kCondLEZ:
- case kCondGTZ:
- case kCondEQ:
- case kCondNE:
- case kCondEQZ:
- case kCondNEZ:
- break;
- default:
- LOG(FATAL) << "Unexpected R2 branch condition " << condition_;
- UNREACHABLE();
- }
- type_ = kR2BareCondBranch;
- CHECK_LE(offset_size_needed, GetOffsetSize());
- }
- old_type_ = type_;
-}
-
-bool Mips64Assembler::Branch::IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs) {
- switch (condition) {
- case kCondLT:
- case kCondGT:
- case kCondNE:
- case kCondLTU:
- return lhs == rhs;
- default:
- return false;
- }
-}
-
-bool Mips64Assembler::Branch::IsUncond(BranchCondition condition,
- GpuRegister lhs,
- GpuRegister rhs) {
- switch (condition) {
- case kUncond:
- return true;
- case kCondGE:
- case kCondLE:
- case kCondEQ:
- case kCondGEU:
- return lhs == rhs;
- default:
- return false;
- }
-}
-
-Mips64Assembler::Branch::Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare)
- : old_location_(location),
- location_(location),
- target_(target),
- lhs_reg_(ZERO),
- rhs_reg_(ZERO),
- condition_(kUncond) {
- InitializeType(
- (is_call ? (is_bare ? kBareCall : kCall) : (is_bare ? kBareCondBranch : kCondBranch)),
- /* is_r6= */ true);
-}
-
-Mips64Assembler::Branch::Branch(bool is_r6,
- uint32_t location,
- uint32_t target,
- Mips64Assembler::BranchCondition condition,
- GpuRegister lhs_reg,
- GpuRegister rhs_reg,
- bool is_bare)
- : old_location_(location),
- location_(location),
- target_(target),
- lhs_reg_(lhs_reg),
- rhs_reg_(rhs_reg),
- condition_(condition) {
- CHECK_NE(condition, kUncond);
- switch (condition) {
- case kCondEQ:
- case kCondNE:
- case kCondLT:
- case kCondGE:
- case kCondLE:
- case kCondGT:
- case kCondLTU:
- case kCondGEU:
- CHECK_NE(lhs_reg, ZERO);
- CHECK_NE(rhs_reg, ZERO);
- break;
- case kCondLTZ:
- case kCondGEZ:
- case kCondLEZ:
- case kCondGTZ:
- case kCondEQZ:
- case kCondNEZ:
- CHECK_NE(lhs_reg, ZERO);
- CHECK_EQ(rhs_reg, ZERO);
- break;
- case kCondF:
- case kCondT:
- CHECK_EQ(rhs_reg, ZERO);
- break;
- case kUncond:
- UNREACHABLE();
- }
- CHECK(!IsNop(condition, lhs_reg, rhs_reg));
- if (IsUncond(condition, lhs_reg, rhs_reg)) {
- // Branch condition is always true, make the branch unconditional.
- condition_ = kUncond;
- }
- InitializeType((is_bare ? kBareCondBranch : kCondBranch), is_r6);
-}
-
-Mips64Assembler::Branch::Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type)
- : old_location_(location),
- location_(location),
- target_(kUnresolved),
- lhs_reg_(dest_reg),
- rhs_reg_(ZERO),
- condition_(kUncond) {
- CHECK_NE(dest_reg, ZERO);
- InitializeType(label_or_literal_type, /* is_r6= */ true);
-}
-
-Mips64Assembler::BranchCondition Mips64Assembler::Branch::OppositeCondition(
- Mips64Assembler::BranchCondition cond) {
- switch (cond) {
- case kCondLT:
- return kCondGE;
- case kCondGE:
- return kCondLT;
- case kCondLE:
- return kCondGT;
- case kCondGT:
- return kCondLE;
- case kCondLTZ:
- return kCondGEZ;
- case kCondGEZ:
- return kCondLTZ;
- case kCondLEZ:
- return kCondGTZ;
- case kCondGTZ:
- return kCondLEZ;
- case kCondEQ:
- return kCondNE;
- case kCondNE:
- return kCondEQ;
- case kCondEQZ:
- return kCondNEZ;
- case kCondNEZ:
- return kCondEQZ;
- case kCondLTU:
- return kCondGEU;
- case kCondGEU:
- return kCondLTU;
- case kCondF:
- return kCondT;
- case kCondT:
- return kCondF;
- case kUncond:
- LOG(FATAL) << "Unexpected branch condition " << cond;
- }
- UNREACHABLE();
-}
-
-Mips64Assembler::Branch::Type Mips64Assembler::Branch::GetType() const {
- return type_;
-}
-
-Mips64Assembler::BranchCondition Mips64Assembler::Branch::GetCondition() const {
- return condition_;
-}
-
-GpuRegister Mips64Assembler::Branch::GetLeftRegister() const {
- return lhs_reg_;
-}
-
-GpuRegister Mips64Assembler::Branch::GetRightRegister() const {
- return rhs_reg_;
-}
-
-uint32_t Mips64Assembler::Branch::GetTarget() const {
- return target_;
-}
-
-uint32_t Mips64Assembler::Branch::GetLocation() const {
- return location_;
-}
-
-uint32_t Mips64Assembler::Branch::GetOldLocation() const {
- return old_location_;
-}
-
-uint32_t Mips64Assembler::Branch::GetLength() const {
- return branch_info_[type_].length;
-}
-
-uint32_t Mips64Assembler::Branch::GetOldLength() const {
- return branch_info_[old_type_].length;
-}
-
-uint32_t Mips64Assembler::Branch::GetSize() const {
- return GetLength() * sizeof(uint32_t);
-}
-
-uint32_t Mips64Assembler::Branch::GetOldSize() const {
- return GetOldLength() * sizeof(uint32_t);
-}
-
-uint32_t Mips64Assembler::Branch::GetEndLocation() const {
- return GetLocation() + GetSize();
-}
-
-uint32_t Mips64Assembler::Branch::GetOldEndLocation() const {
- return GetOldLocation() + GetOldSize();
-}
-
-bool Mips64Assembler::Branch::IsBare() const {
- switch (type_) {
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- case kBareUncondBranch:
- case kBareCondBranch:
- case kBareCall:
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- case kR2BareCondBranch:
- return true;
- default:
- return false;
- }
-}
-
-bool Mips64Assembler::Branch::IsLong() const {
- switch (type_) {
- // R6 short branches (can be promoted to long).
- case kUncondBranch:
- case kCondBranch:
- case kCall:
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- case kBareUncondBranch:
- case kBareCondBranch:
- case kBareCall:
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- case kR2BareCondBranch:
- // Near label.
- case kLabel:
- // Near literals.
- case kLiteral:
- case kLiteralUnsigned:
- case kLiteralLong:
- return false;
- // Long branches.
- case kLongUncondBranch:
- case kLongCondBranch:
- case kLongCall:
- // Far label.
- case kFarLabel:
- // Far literals.
- case kFarLiteral:
- case kFarLiteralUnsigned:
- case kFarLiteralLong:
- return true;
- }
- UNREACHABLE();
-}
-
-bool Mips64Assembler::Branch::IsResolved() const {
- return target_ != kUnresolved;
-}
-
-Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSize() const {
- bool r6_cond_branch = (type_ == kCondBranch || type_ == kBareCondBranch);
- OffsetBits offset_size =
- (r6_cond_branch && (condition_ == kCondEQZ || condition_ == kCondNEZ))
- ? kOffset23
- : branch_info_[type_].offset_size;
- return offset_size;
-}
-
-Mips64Assembler::Branch::OffsetBits Mips64Assembler::Branch::GetOffsetSizeNeeded(uint32_t location,
- uint32_t target) {
- // For unresolved targets assume the shortest encoding
- // (later it will be made longer if needed).
- if (target == kUnresolved)
- return kOffset16;
- int64_t distance = static_cast<int64_t>(target) - location;
- // To simplify calculations in composite branches consisting of multiple instructions
- // bump up the distance by a value larger than the max byte size of a composite branch.
- distance += (distance >= 0) ? kMaxBranchSize : -kMaxBranchSize;
- if (IsInt<kOffset16>(distance))
- return kOffset16;
- else if (IsInt<kOffset18>(distance))
- return kOffset18;
- else if (IsInt<kOffset21>(distance))
- return kOffset21;
- else if (IsInt<kOffset23>(distance))
- return kOffset23;
- else if (IsInt<kOffset28>(distance))
- return kOffset28;
- return kOffset32;
-}
-
-void Mips64Assembler::Branch::Resolve(uint32_t target) {
- target_ = target;
-}
-
-void Mips64Assembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
- if (location_ > expand_location) {
- location_ += delta;
- }
- if (!IsResolved()) {
- return; // Don't know the target yet.
- }
- if (target_ > expand_location) {
- target_ += delta;
- }
-}
-
-void Mips64Assembler::Branch::PromoteToLong() {
- CHECK(!IsBare()); // Bare branches do not promote.
- switch (type_) {
- // R6 short branches (can be promoted to long).
- case kUncondBranch:
- type_ = kLongUncondBranch;
- break;
- case kCondBranch:
- type_ = kLongCondBranch;
- break;
- case kCall:
- type_ = kLongCall;
- break;
- // Near label.
- case kLabel:
- type_ = kFarLabel;
- break;
- // Near literals.
- case kLiteral:
- type_ = kFarLiteral;
- break;
- case kLiteralUnsigned:
- type_ = kFarLiteralUnsigned;
- break;
- case kLiteralLong:
- type_ = kFarLiteralLong;
- break;
- default:
- // Note: 'type_' is already long.
- break;
- }
- CHECK(IsLong());
-}
-
-uint32_t Mips64Assembler::Branch::PromoteIfNeeded(uint32_t max_short_distance) {
- // If the branch is still unresolved or already long, nothing to do.
- if (IsLong() || !IsResolved()) {
- return 0;
- }
- // Promote the short branch to long if the offset size is too small
- // to hold the distance between location_ and target_.
- if (GetOffsetSizeNeeded(location_, target_) > GetOffsetSize()) {
- PromoteToLong();
- uint32_t old_size = GetOldSize();
- uint32_t new_size = GetSize();
- CHECK_GT(new_size, old_size);
- return new_size - old_size;
- }
- // The following logic is for debugging/testing purposes.
- // Promote some short branches to long when it's not really required.
- if (UNLIKELY(max_short_distance != std::numeric_limits<uint32_t>::max() && !IsBare())) {
- int64_t distance = static_cast<int64_t>(target_) - location_;
- distance = (distance >= 0) ? distance : -distance;
- if (distance >= max_short_distance) {
- PromoteToLong();
- uint32_t old_size = GetOldSize();
- uint32_t new_size = GetSize();
- CHECK_GT(new_size, old_size);
- return new_size - old_size;
- }
- }
- return 0;
-}
-
-uint32_t Mips64Assembler::Branch::GetOffsetLocation() const {
- return location_ + branch_info_[type_].instr_offset * sizeof(uint32_t);
-}
-
-uint32_t Mips64Assembler::Branch::GetOffset() const {
- CHECK(IsResolved());
- uint32_t ofs_mask = 0xFFFFFFFF >> (32 - GetOffsetSize());
- // Calculate the byte distance between instructions and also account for
- // different PC-relative origins.
- uint32_t offset_location = GetOffsetLocation();
- if (type_ == kLiteralLong) {
- // Special case for the ldpc instruction, whose address (PC) is rounded down to
- // a multiple of 8 before adding the offset.
- // Note, branch promotion has already taken care of aligning `target_` to an
- // address that's a multiple of 8.
- offset_location = RoundDown(offset_location, sizeof(uint64_t));
- }
- uint32_t offset = target_ - offset_location - branch_info_[type_].pc_org * sizeof(uint32_t);
- // Prepare the offset for encoding into the instruction(s).
- offset = (offset & ofs_mask) >> branch_info_[type_].offset_shift;
- return offset;
-}
-
-Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) {
- CHECK_LT(branch_id, branches_.size());
- return &branches_[branch_id];
-}
-
-const Mips64Assembler::Branch* Mips64Assembler::GetBranch(uint32_t branch_id) const {
- CHECK_LT(branch_id, branches_.size());
- return &branches_[branch_id];
-}
-
-void Mips64Assembler::Bind(Mips64Label* label) {
- CHECK(!label->IsBound());
- uint32_t bound_pc = buffer_.Size();
-
- // Walk the list of branches referring to and preceding this label.
- // Store the previously unknown target addresses in them.
- while (label->IsLinked()) {
- uint32_t branch_id = label->Position();
- Branch* branch = GetBranch(branch_id);
- branch->Resolve(bound_pc);
-
- uint32_t branch_location = branch->GetLocation();
- // Extract the location of the previous branch in the list (walking the list backwards;
- // the previous branch ID was stored in the space reserved for this branch).
- uint32_t prev = buffer_.Load<uint32_t>(branch_location);
-
- // On to the previous branch in the list...
- label->position_ = prev;
- }
-
- // Now make the label object contain its own location (relative to the end of the preceding
- // branch, if any; it will be used by the branches referring to and following this label).
- label->prev_branch_id_plus_one_ = branches_.size();
- if (label->prev_branch_id_plus_one_) {
- uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
- const Branch* branch = GetBranch(branch_id);
- bound_pc -= branch->GetEndLocation();
- }
- label->BindTo(bound_pc);
-}
-
-uint32_t Mips64Assembler::GetLabelLocation(const Mips64Label* label) const {
- CHECK(label->IsBound());
- uint32_t target = label->Position();
- if (label->prev_branch_id_plus_one_) {
- // Get label location based on the branch preceding it.
- uint32_t branch_id = label->prev_branch_id_plus_one_ - 1;
- const Branch* branch = GetBranch(branch_id);
- target += branch->GetEndLocation();
- }
- return target;
-}
-
-uint32_t Mips64Assembler::GetAdjustedPosition(uint32_t old_position) {
- // We can reconstruct the adjustment by going through all the branches from the beginning
- // up to the old_position. Since we expect AdjustedPosition() to be called in a loop
- // with increasing old_position, we can use the data from last AdjustedPosition() to
- // continue where we left off and the whole loop should be O(m+n) where m is the number
- // of positions to adjust and n is the number of branches.
- if (old_position < last_old_position_) {
- last_position_adjustment_ = 0;
- last_old_position_ = 0;
- last_branch_id_ = 0;
- }
- while (last_branch_id_ != branches_.size()) {
- const Branch* branch = GetBranch(last_branch_id_);
- if (branch->GetLocation() >= old_position + last_position_adjustment_) {
- break;
- }
- last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
- ++last_branch_id_;
- }
- last_old_position_ = old_position;
- return old_position + last_position_adjustment_;
-}
-
-void Mips64Assembler::FinalizeLabeledBranch(Mips64Label* label) {
- uint32_t length = branches_.back().GetLength();
- if (!label->IsBound()) {
- // Branch forward (to a following label), distance is unknown.
- // The first branch forward will contain 0, serving as the terminator of
- // the list of forward-reaching branches.
- Emit(label->position_);
- length--;
- // Now make the label object point to this branch
- // (this forms a linked list of branches preceding this label).
- uint32_t branch_id = branches_.size() - 1;
- label->LinkTo(branch_id);
- }
- // Reserve space for the branch.
- for (; length != 0u; --length) {
- Nop();
- }
-}
-
-void Mips64Assembler::Buncond(Mips64Label* label, bool is_bare) {
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(buffer_.Size(), target, /* is_call= */ false, is_bare);
- FinalizeLabeledBranch(label);
-}
-
-void Mips64Assembler::Bcond(Mips64Label* label,
- bool is_r6,
- bool is_bare,
- BranchCondition condition,
- GpuRegister lhs,
- GpuRegister rhs) {
- // If lhs = rhs, this can be a NOP.
- if (Branch::IsNop(condition, lhs, rhs)) {
- return;
- }
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(is_r6, buffer_.Size(), target, condition, lhs, rhs, is_bare);
- FinalizeLabeledBranch(label);
-}
-
-void Mips64Assembler::Call(Mips64Label* label, bool is_bare) {
- uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
- branches_.emplace_back(buffer_.Size(), target, /* is_call= */ true, is_bare);
- FinalizeLabeledBranch(label);
-}
-
-void Mips64Assembler::LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label) {
- // Label address loads are treated as pseudo branches since they require very similar handling.
- DCHECK(!label->IsBound());
- branches_.emplace_back(buffer_.Size(), dest_reg, Branch::kLabel);
- FinalizeLabeledBranch(label);
-}
-
-Literal* Mips64Assembler::NewLiteral(size_t size, const uint8_t* data) {
- // We don't support byte and half-word literals.
- if (size == 4u) {
- literals_.emplace_back(size, data);
- return &literals_.back();
- } else {
- DCHECK_EQ(size, 8u);
- long_literals_.emplace_back(size, data);
- return &long_literals_.back();
- }
-}
-
-void Mips64Assembler::LoadLiteral(GpuRegister dest_reg,
- LoadOperandType load_type,
- Literal* literal) {
- // Literal loads are treated as pseudo branches since they require very similar handling.
- Branch::Type literal_type;
- switch (load_type) {
- case kLoadWord:
- DCHECK_EQ(literal->GetSize(), 4u);
- literal_type = Branch::kLiteral;
- break;
- case kLoadUnsignedWord:
- DCHECK_EQ(literal->GetSize(), 4u);
- literal_type = Branch::kLiteralUnsigned;
- break;
- case kLoadDoubleword:
- DCHECK_EQ(literal->GetSize(), 8u);
- literal_type = Branch::kLiteralLong;
- break;
- default:
- LOG(FATAL) << "Unexpected literal load type " << load_type;
- UNREACHABLE();
- }
- Mips64Label* label = literal->GetLabel();
- DCHECK(!label->IsBound());
- branches_.emplace_back(buffer_.Size(), dest_reg, literal_type);
- FinalizeLabeledBranch(label);
-}
-
-JumpTable* Mips64Assembler::CreateJumpTable(std::vector<Mips64Label*>&& labels) {
- jump_tables_.emplace_back(std::move(labels));
- JumpTable* table = &jump_tables_.back();
- DCHECK(!table->GetLabel()->IsBound());
- return table;
-}
-
-void Mips64Assembler::ReserveJumpTableSpace() {
- if (!jump_tables_.empty()) {
- for (JumpTable& table : jump_tables_) {
- Mips64Label* label = table.GetLabel();
- Bind(label);
-
- // Bulk ensure capacity, as this may be large.
- size_t orig_size = buffer_.Size();
- size_t required_capacity = orig_size + table.GetSize();
- if (required_capacity > buffer_.Capacity()) {
- buffer_.ExtendCapacity(required_capacity);
- }
-#ifndef NDEBUG
- buffer_.has_ensured_capacity_ = true;
-#endif
-
- // Fill the space with dummy data as the data is not final
- // until the branches have been promoted. And we shouldn't
- // be moving uninitialized data during branch promotion.
- for (size_t cnt = table.GetData().size(), i = 0; i < cnt; i++) {
- buffer_.Emit<uint32_t>(0x1abe1234u);
- }
-
-#ifndef NDEBUG
- buffer_.has_ensured_capacity_ = false;
-#endif
- }
- }
-}
-
-void Mips64Assembler::EmitJumpTables() {
- if (!jump_tables_.empty()) {
- CHECK(!overwriting_);
- // Switch from appending instructions at the end of the buffer to overwriting
- // existing instructions (here, jump tables) in the buffer.
- overwriting_ = true;
-
- for (JumpTable& table : jump_tables_) {
- Mips64Label* table_label = table.GetLabel();
- uint32_t start = GetLabelLocation(table_label);
- overwrite_location_ = start;
-
- for (Mips64Label* target : table.GetData()) {
- CHECK_EQ(buffer_.Load<uint32_t>(overwrite_location_), 0x1abe1234u);
- // The table will contain target addresses relative to the table start.
- uint32_t offset = GetLabelLocation(target) - start;
- Emit(offset);
- }
- }
-
- overwriting_ = false;
- }
-}
-
-void Mips64Assembler::EmitLiterals() {
- if (!literals_.empty()) {
- for (Literal& literal : literals_) {
- Mips64Label* label = literal.GetLabel();
- Bind(label);
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- DCHECK_EQ(literal.GetSize(), 4u);
- for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
- buffer_.Emit<uint8_t>(literal.GetData()[i]);
- }
- }
- }
- if (!long_literals_.empty()) {
- // Reserve 4 bytes for potential alignment. If after the branch promotion the 64-bit
- // literals don't end up 8-byte-aligned, they will be moved down 4 bytes.
- Emit(0); // NOP.
- for (Literal& literal : long_literals_) {
- Mips64Label* label = literal.GetLabel();
- Bind(label);
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- DCHECK_EQ(literal.GetSize(), 8u);
- for (size_t i = 0, size = literal.GetSize(); i != size; ++i) {
- buffer_.Emit<uint8_t>(literal.GetData()[i]);
- }
- }
- }
-}
-
-void Mips64Assembler::PromoteBranches() {
- // Promote short branches to long as necessary.
- bool changed;
- do {
- changed = false;
- for (auto& branch : branches_) {
- CHECK(branch.IsResolved());
- uint32_t delta = branch.PromoteIfNeeded();
- // If this branch has been promoted and needs to expand in size,
- // relocate all branches by the expansion size.
- if (delta) {
- changed = true;
- uint32_t expand_location = branch.GetLocation();
- for (auto& branch2 : branches_) {
- branch2.Relocate(expand_location, delta);
- }
- }
- }
- } while (changed);
-
- // Account for branch expansion by resizing the code buffer
- // and moving the code in it to its final location.
- size_t branch_count = branches_.size();
- if (branch_count > 0) {
- // Resize.
- Branch& last_branch = branches_[branch_count - 1];
- uint32_t size_delta = last_branch.GetEndLocation() - last_branch.GetOldEndLocation();
- uint32_t old_size = buffer_.Size();
- buffer_.Resize(old_size + size_delta);
- // Move the code residing between branch placeholders.
- uint32_t end = old_size;
- for (size_t i = branch_count; i > 0; ) {
- Branch& branch = branches_[--i];
- uint32_t size = end - branch.GetOldEndLocation();
- buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
- end = branch.GetOldLocation();
- }
- }
-
- // Align 64-bit literals by moving them down by 4 bytes if needed.
- // This will reduce the PC-relative distance, which should be safe for both near and far literals.
- if (!long_literals_.empty()) {
- uint32_t first_literal_location = GetLabelLocation(long_literals_.front().GetLabel());
- size_t lit_size = long_literals_.size() * sizeof(uint64_t);
- size_t buf_size = buffer_.Size();
- // 64-bit literals must be at the very end of the buffer.
- CHECK_EQ(first_literal_location + lit_size, buf_size);
- if (!IsAligned<sizeof(uint64_t)>(first_literal_location)) {
- buffer_.Move(first_literal_location - sizeof(uint32_t), first_literal_location, lit_size);
- // The 4 reserved bytes proved useless, reduce the buffer size.
- buffer_.Resize(buf_size - sizeof(uint32_t));
- // Reduce target addresses in literal and address loads by 4 bytes in order for correct
- // offsets from PC to be generated.
- for (auto& branch : branches_) {
- uint32_t target = branch.GetTarget();
- if (target >= first_literal_location) {
- branch.Resolve(target - sizeof(uint32_t));
- }
- }
- // If after this we ever call GetLabelLocation() to get the location of a 64-bit literal,
- // we need to adjust the location of the literal's label as well.
- for (Literal& literal : long_literals_) {
- // Bound label's position is negative, hence incrementing it instead of decrementing.
- literal.GetLabel()->position_ += sizeof(uint32_t);
- }
- }
- }
-}
-
-// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
-const Mips64Assembler::Branch::BranchInfo Mips64Assembler::Branch::branch_info_[] = {
- // R6 short branches (can be promoted to long).
- { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kUncondBranch
- { 2, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kCondBranch
- // Exception: kOffset23 for beqzc/bnezc
- { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kCall
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareUncondBranch
- { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kBareCondBranch
- // Exception: kOffset23 for beqzc/bnezc
- { 1, 0, 1, Mips64Assembler::Branch::kOffset28, 2 }, // kBareCall
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- { 1, 0, 1, Mips64Assembler::Branch::kOffset18, 2 }, // kR2BareCondBranch
- // Near label.
- { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLabel
- // Near literals.
- { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteral
- { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 2 }, // kLiteralUnsigned
- { 1, 0, 0, Mips64Assembler::Branch::kOffset21, 3 }, // kLiteralLong
- // Long branches.
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongUncondBranch
- { 3, 1, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCondBranch
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kLongCall
- // Far label.
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLabel
- // Far literals.
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteral
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralUnsigned
- { 2, 0, 0, Mips64Assembler::Branch::kOffset32, 0 }, // kFarLiteralLong
-};
-
-// Note: make sure branch_info_[] and EmitBranch() are kept synchronized.
-void Mips64Assembler::EmitBranch(Mips64Assembler::Branch* branch) {
- CHECK(overwriting_);
- overwrite_location_ = branch->GetLocation();
- uint32_t offset = branch->GetOffset();
- BranchCondition condition = branch->GetCondition();
- GpuRegister lhs = branch->GetLeftRegister();
- GpuRegister rhs = branch->GetRightRegister();
- switch (branch->GetType()) {
- // Short branches.
- case Branch::kUncondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bc(offset);
- break;
- case Branch::kCondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR6(condition, lhs, rhs, offset);
- Nop(); // TODO: improve by filling the forbidden/delay slot.
- break;
- case Branch::kCall:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Balc(offset);
- break;
- case Branch::kBareUncondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Bc(offset);
- break;
- case Branch::kBareCondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR6(condition, lhs, rhs, offset);
- break;
- case Branch::kBareCall:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Balc(offset);
- break;
- case Branch::kR2BareCondBranch:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- EmitBcondR2(condition, lhs, rhs, offset);
- break;
-
- // Near label.
- case Branch::kLabel:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Addiupc(lhs, offset);
- break;
- // Near literals.
- case Branch::kLiteral:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lwpc(lhs, offset);
- break;
- case Branch::kLiteralUnsigned:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Lwupc(lhs, offset);
- break;
- case Branch::kLiteralLong:
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Ldpc(lhs, offset);
- break;
-
- // Long branches.
- case Branch::kLongUncondBranch:
- offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jic(AT, Low16Bits(offset));
- break;
- case Branch::kLongCondBranch:
- EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
- offset += (offset & 0x8000) << 1; // Account for sign extension in jic.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jic(AT, Low16Bits(offset));
- break;
- case Branch::kLongCall:
- offset += (offset & 0x8000) << 1; // Account for sign extension in jialc.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Jialc(AT, Low16Bits(offset));
- break;
-
- // Far label.
- case Branch::kFarLabel:
- offset += (offset & 0x8000) << 1; // Account for sign extension in daddiu.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Daddiu(lhs, AT, Low16Bits(offset));
- break;
- // Far literals.
- case Branch::kFarLiteral:
- offset += (offset & 0x8000) << 1; // Account for sign extension in lw.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Lw(lhs, AT, Low16Bits(offset));
- break;
- case Branch::kFarLiteralUnsigned:
- offset += (offset & 0x8000) << 1; // Account for sign extension in lwu.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Lwu(lhs, AT, Low16Bits(offset));
- break;
- case Branch::kFarLiteralLong:
- offset += (offset & 0x8000) << 1; // Account for sign extension in ld.
- CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
- Auipc(AT, High16Bits(offset));
- Ld(lhs, AT, Low16Bits(offset));
- break;
- }
- CHECK_EQ(overwrite_location_, branch->GetEndLocation());
- CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
-}
-
-void Mips64Assembler::Bc(Mips64Label* label, bool is_bare) {
- Buncond(label, is_bare);
-}
-
-void Mips64Assembler::Balc(Mips64Label* label, bool is_bare) {
- Call(label, is_bare);
-}
-
-void Mips64Assembler::Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLT, rs, rt);
-}
-
-void Mips64Assembler::Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLTZ, rt);
-}
-
-void Mips64Assembler::Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGTZ, rt);
-}
-
-void Mips64Assembler::Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGE, rs, rt);
-}
-
-void Mips64Assembler::Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGEZ, rt);
-}
-
-void Mips64Assembler::Blezc(GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLEZ, rt);
-}
-
-void Mips64Assembler::Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondLTU, rs, rt);
-}
-
-void Mips64Assembler::Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondGEU, rs, rt);
-}
-
-void Mips64Assembler::Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondEQ, rs, rt);
-}
-
-void Mips64Assembler::Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondNE, rs, rt);
-}
-
-void Mips64Assembler::Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondEQZ, rs);
-}
-
-void Mips64Assembler::Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondNEZ, rs);
-}
-
-void Mips64Assembler::Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondF, static_cast<GpuRegister>(ft), ZERO);
-}
-
-void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare) {
- Bcond(label, /* is_r6= */ true, is_bare, kCondT, static_cast<GpuRegister>(ft), ZERO);
-}
-
-void Mips64Assembler::Bltz(GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondLTZ, rt);
-}
-
-void Mips64Assembler::Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondGTZ, rt);
-}
-
-void Mips64Assembler::Bgez(GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondGEZ, rt);
-}
-
-void Mips64Assembler::Blez(GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondLEZ, rt);
-}
-
-void Mips64Assembler::Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondEQ, rs, rt);
-}
-
-void Mips64Assembler::Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondNE, rs, rt);
-}
-
-void Mips64Assembler::Beqz(GpuRegister rs, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondEQZ, rs);
-}
-
-void Mips64Assembler::Bnez(GpuRegister rs, Mips64Label* label, bool is_bare) {
- CHECK(is_bare);
- Bcond(label, /* is_r6= */ false, is_bare, kCondNEZ, rs);
-}
-
-void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base,
- int32_t& offset,
- bool is_doubleword) {
- // This method is used to adjust the base register and offset pair
- // for a load/store when the offset doesn't fit into int16_t.
- // It is assumed that `base + offset` is sufficiently aligned for memory
- // operands that are machine word in size or smaller. For doubleword-sized
- // operands it's assumed that `base` is a multiple of 8, while `offset`
- // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
- // and spilled variables on the stack accessed relative to the stack
- // pointer register).
- // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
- CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
-
- bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset);
- bool two_accesses = is_doubleword && !doubleword_aligned;
-
- // IsInt<16> must be passed a signed value, hence the static cast below.
- if (IsInt<16>(offset) &&
- (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) {
- // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
- return;
- }
-
- // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
- uint32_t misalignment = offset & (kMips64DoublewordSize - 1);
-
- // First, see if `offset` can be represented as a sum of two 16-bit signed
- // offsets. This can save an instruction.
- // To simplify matters, only do this for a symmetric range of offsets from
- // about -64KB to about +64KB, allowing further addition of 4 when accessing
- // 64-bit variables with two 32-bit accesses.
- constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8.
- constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
-
- if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
- Daddiu(AT, base, kMinOffsetForSimpleAdjustment);
- offset -= kMinOffsetForSimpleAdjustment;
- } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
- Daddiu(AT, base, -kMinOffsetForSimpleAdjustment);
- offset += kMinOffsetForSimpleAdjustment;
- } else {
- // In more complex cases take advantage of the daui instruction, e.g.:
- // daui AT, base, offset_high
- // [dahi AT, 1] // When `offset` is close to +2GB.
- // lw reg_lo, offset_low(AT)
- // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load.
- // or when offset_low+4 overflows int16_t:
- // daui AT, base, offset_high
- // daddiu AT, AT, 8
- // lw reg_lo, (offset_low-8)(AT)
- // lw reg_hi, (offset_low-4)(AT)
- int16_t offset_low = Low16Bits(offset);
- int32_t offset_low32 = offset_low;
- int16_t offset_high = High16Bits(offset);
- bool increment_hi16 = offset_low < 0;
- bool overflow_hi16 = false;
-
- if (increment_hi16) {
- offset_high++;
- overflow_hi16 = (offset_high == -32768);
- }
- Daui(AT, base, offset_high);
-
- if (overflow_hi16) {
- Dahi(AT, 1);
- }
-
- if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) {
- // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
- Daddiu(AT, AT, kMips64DoublewordSize);
- offset_low32 -= kMips64DoublewordSize;
- }
-
- offset = offset_low32;
- }
- base = AT;
-
- CHECK(IsInt<16>(offset));
- if (two_accesses) {
- CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)));
- }
- CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1));
-}
-
-void Mips64Assembler::AdjustBaseOffsetAndElementSizeShift(GpuRegister& base,
- int32_t& offset,
- int& element_size_shift) {
- // This method is used to adjust the base register, offset and element_size_shift
- // for a vector load/store when the offset doesn't fit into allowed number of bits.
- // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum
- // offset is dependant on the size of the data format df (10-bit offsets for ld.b,
- // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d).
- // If element_size_shift is non-negative at entry, it won't be changed, but offset
- // will be checked for appropriate alignment. If negative at entry, it will be
- // adjusted based on offset for maximum fit.
- // It's assumed that `base` is a multiple of 8.
-
- CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
-
- if (element_size_shift >= 0) {
- CHECK_LE(element_size_shift, TIMES_8);
- CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
- } else if (IsAligned<kMips64DoublewordSize>(offset)) {
- element_size_shift = TIMES_8;
- } else if (IsAligned<kMips64WordSize>(offset)) {
- element_size_shift = TIMES_4;
- } else if (IsAligned<kMips64HalfwordSize>(offset)) {
- element_size_shift = TIMES_2;
- } else {
- element_size_shift = TIMES_1;
- }
-
- const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df
- // will take.
- int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits.
- low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits.
- if (low == offset) {
- return; // `offset` fits into ld.df/st.df.
- }
-
- // First, see if `offset` can be represented as a sum of two signed offsets.
- // This can save an instruction.
-
- // Max int16_t that's a multiple of element size.
- const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift);
- // Max ld.df/st.df offset that's a multiple of element size.
- const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift;
- const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset;
-
- if (IsInt<16>(offset)) {
- Daddiu(AT, base, offset);
- offset = 0;
- } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
- Daddiu(AT, base, kMaxDeltaForSimpleAdjustment);
- offset -= kMaxDeltaForSimpleAdjustment;
- } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
- Daddiu(AT, base, -kMaxDeltaForSimpleAdjustment);
- offset += kMaxDeltaForSimpleAdjustment;
- } else {
- // Let's treat `offset` as 64-bit to simplify handling of sign
- // extensions in the instructions that supply its smaller signed parts.
- //
- // 16-bit or smaller parts of `offset`:
- // |63 top 48|47 hi 32|31 upper 16|15 mid 13-10|12-9 low 0|
- //
- // Instructions that supply each part as a signed integer addend:
- // |dati |dahi |daui |daddiu |ld.df/st.df |
- //
- // `top` is always 0, so dati isn't used.
- // `hi` is 1 when `offset` is close to +2GB and 0 otherwise.
- uint64_t tmp = static_cast<uint64_t>(offset) - low; // Exclude `low` from the rest of `offset`
- // (accounts for sign of `low`).
- tmp += (tmp & (UINT64_C(1) << 15)) << 1; // Account for sign extension in daddiu.
- tmp += (tmp & (UINT64_C(1) << 31)) << 1; // Account for sign extension in daui.
- int16_t mid = Low16Bits(tmp);
- int16_t upper = High16Bits(tmp);
- int16_t hi = Low16Bits(High32Bits(tmp));
- Daui(AT, base, upper);
- if (hi != 0) {
- CHECK_EQ(hi, 1);
- Dahi(AT, hi);
- }
- if (mid != 0) {
- Daddiu(AT, AT, mid);
- }
- offset = low;
- }
- base = AT;
- CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift);
- CHECK(IsInt<10>(offset >> element_size_shift));
-}
-
-void Mips64Assembler::LoadFromOffset(LoadOperandType type,
- GpuRegister reg,
- GpuRegister base,
- int32_t offset) {
- LoadFromOffset<>(type, reg, base, offset);
-}
-
-void Mips64Assembler::LoadFpuFromOffset(LoadOperandType type,
- FpuRegister reg,
- GpuRegister base,
- int32_t offset) {
- LoadFpuFromOffset<>(type, reg, base, offset);
-}
-
-void Mips64Assembler::EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset,
- size_t size) {
- Mips64ManagedRegister dst = m_dst.AsMips64();
- if (dst.IsNoRegister()) {
- CHECK_EQ(0u, size) << dst;
- } else if (dst.IsGpuRegister()) {
- if (size == 4) {
- LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
- } else if (size == 8) {
- CHECK_EQ(8u, size) << dst;
- LoadFromOffset(kLoadDoubleword, dst.AsGpuRegister(), src_register, src_offset);
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
- }
- } else if (dst.IsFpuRegister()) {
- if (size == 4) {
- CHECK_EQ(4u, size) << dst;
- LoadFpuFromOffset(kLoadWord, dst.AsFpuRegister(), src_register, src_offset);
- } else if (size == 8) {
- CHECK_EQ(8u, size) << dst;
- LoadFpuFromOffset(kLoadDoubleword, dst.AsFpuRegister(), src_register, src_offset);
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Load() of size 4 and 8";
- }
- }
-}
-
-void Mips64Assembler::StoreToOffset(StoreOperandType type,
- GpuRegister reg,
- GpuRegister base,
- int32_t offset) {
- StoreToOffset<>(type, reg, base, offset);
-}
-
-void Mips64Assembler::StoreFpuToOffset(StoreOperandType type,
- FpuRegister reg,
- GpuRegister base,
- int32_t offset) {
- StoreFpuToOffset<>(type, reg, base, offset);
-}
-
-static dwarf::Reg DWARFReg(GpuRegister reg) {
- return dwarf::Reg::Mips64Core(static_cast<int>(reg));
-}
-
-constexpr size_t kFramePointerSize = 8;
-
-void Mips64Assembler::BuildFrame(size_t frame_size,
- ManagedRegister method_reg,
- ArrayRef<const ManagedRegister> callee_save_regs,
- const ManagedRegisterEntrySpills& entry_spills) {
- CHECK_ALIGNED(frame_size, kStackAlignment);
- DCHECK(!overwriting_);
-
- // Increase frame to required size.
- IncreaseFrameSize(frame_size);
-
- // Push callee saves and return address
- int stack_offset = frame_size - kFramePointerSize;
- StoreToOffset(kStoreDoubleword, RA, SP, stack_offset);
- cfi_.RelOffset(DWARFReg(RA), stack_offset);
- for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
- stack_offset -= kFramePointerSize;
- GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
- StoreToOffset(kStoreDoubleword, reg, SP, stack_offset);
- cfi_.RelOffset(DWARFReg(reg), stack_offset);
- }
-
- // Write out Method*.
- StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
-
- // Write out entry spills.
- int32_t offset = frame_size + kFramePointerSize;
- for (const ManagedRegisterSpill& spill : entry_spills) {
- Mips64ManagedRegister reg = spill.AsMips64();
- int32_t size = spill.getSize();
- if (reg.IsNoRegister()) {
- // only increment stack offset.
- offset += size;
- } else if (reg.IsFpuRegister()) {
- StoreFpuToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
- reg.AsFpuRegister(), SP, offset);
- offset += size;
- } else if (reg.IsGpuRegister()) {
- StoreToOffset((size == 4) ? kStoreWord : kStoreDoubleword,
- reg.AsGpuRegister(), SP, offset);
- offset += size;
- }
- }
-}
-
-void Mips64Assembler::RemoveFrame(size_t frame_size,
- ArrayRef<const ManagedRegister> callee_save_regs,
- bool may_suspend ATTRIBUTE_UNUSED) {
- CHECK_ALIGNED(frame_size, kStackAlignment);
- DCHECK(!overwriting_);
- cfi_.RememberState();
-
- // Pop callee saves and return address
- int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
- for (size_t i = 0; i < callee_save_regs.size(); ++i) {
- GpuRegister reg = callee_save_regs[i].AsMips64().AsGpuRegister();
- LoadFromOffset(kLoadDoubleword, reg, SP, stack_offset);
- cfi_.Restore(DWARFReg(reg));
- stack_offset += kFramePointerSize;
- }
- LoadFromOffset(kLoadDoubleword, RA, SP, stack_offset);
- cfi_.Restore(DWARFReg(RA));
-
- // Decrease frame to required size.
- DecreaseFrameSize(frame_size);
-
- // Then jump to the return address.
- Jr(RA);
- Nop();
-
- // The CFI should be restored for any code that follows the exit block.
- cfi_.RestoreState();
- cfi_.DefCFAOffset(frame_size);
-}
-
-void Mips64Assembler::IncreaseFrameSize(size_t adjust) {
- CHECK_ALIGNED(adjust, kFramePointerSize);
- DCHECK(!overwriting_);
- Daddiu64(SP, SP, static_cast<int32_t>(-adjust));
- cfi_.AdjustCFAOffset(adjust);
-}
-
-void Mips64Assembler::DecreaseFrameSize(size_t adjust) {
- CHECK_ALIGNED(adjust, kFramePointerSize);
- DCHECK(!overwriting_);
- Daddiu64(SP, SP, static_cast<int32_t>(adjust));
- cfi_.AdjustCFAOffset(-adjust);
-}
-
-void Mips64Assembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
- Mips64ManagedRegister src = msrc.AsMips64();
- if (src.IsNoRegister()) {
- CHECK_EQ(0u, size);
- } else if (src.IsGpuRegister()) {
- CHECK(size == 4 || size == 8) << size;
- if (size == 8) {
- StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
- } else if (size == 4) {
- StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
- }
- } else if (src.IsFpuRegister()) {
- CHECK(size == 4 || size == 8) << size;
- if (size == 8) {
- StoreFpuToOffset(kStoreDoubleword, src.AsFpuRegister(), SP, dest.Int32Value());
- } else if (size == 4) {
- StoreFpuToOffset(kStoreWord, src.AsFpuRegister(), SP, dest.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Store() of size 4 and 8";
- }
- }
-}
-
-void Mips64Assembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
- Mips64ManagedRegister src = msrc.AsMips64();
- CHECK(src.IsGpuRegister());
- StoreToOffset(kStoreWord, src.AsGpuRegister(), SP, dest.Int32Value());
-}
-
-void Mips64Assembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
- Mips64ManagedRegister src = msrc.AsMips64();
- CHECK(src.IsGpuRegister());
- StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
-}
-
-void Mips64Assembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
- ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadConst32(scratch.AsGpuRegister(), imm);
- StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
-}
-
-void Mips64Assembler::StoreStackOffsetToThread(ThreadOffset64 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- Daddiu64(scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
-}
-
-void Mips64Assembler::StoreStackPointerToThread(ThreadOffset64 thr_offs) {
- StoreToOffset(kStoreDoubleword, SP, S1, thr_offs.Int32Value());
-}
-
-void Mips64Assembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
- FrameOffset in_off, ManagedRegister mscratch) {
- Mips64ManagedRegister src = msrc.AsMips64();
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- StoreToOffset(kStoreDoubleword, src.AsGpuRegister(), SP, dest.Int32Value());
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, in_off.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value() + 8);
-}
-
-void Mips64Assembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
- return EmitLoad(mdest, SP, src.Int32Value(), size);
-}
-
-void Mips64Assembler::LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) {
- return EmitLoad(mdest, S1, src.Int32Value(), size);
-}
-
-void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
- Mips64ManagedRegister dest = mdest.AsMips64();
- CHECK(dest.IsGpuRegister());
- LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
-}
-
-void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
- bool unpoison_reference) {
- Mips64ManagedRegister dest = mdest.AsMips64();
- CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
- LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
- base.AsMips64().AsGpuRegister(), offs.Int32Value());
- if (unpoison_reference) {
- MaybeUnpoisonHeapReference(dest.AsGpuRegister());
- }
-}
-
-void Mips64Assembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
- Offset offs) {
- Mips64ManagedRegister dest = mdest.AsMips64();
- CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
- LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(),
- base.AsMips64().AsGpuRegister(), offs.Int32Value());
-}
-
-void Mips64Assembler::LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) {
- Mips64ManagedRegister dest = mdest.AsMips64();
- CHECK(dest.IsGpuRegister());
- LoadFromOffset(kLoadDoubleword, dest.AsGpuRegister(), S1, offs.Int32Value());
-}
-
-void Mips64Assembler::SignExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "No sign extension necessary for MIPS64";
-}
-
-void Mips64Assembler::ZeroExtend(ManagedRegister mreg ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "No zero extension necessary for MIPS64";
-}
-
-void Mips64Assembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
- Mips64ManagedRegister dest = mdest.AsMips64();
- Mips64ManagedRegister src = msrc.AsMips64();
- if (!dest.Equals(src)) {
- if (dest.IsGpuRegister()) {
- CHECK(src.IsGpuRegister()) << src;
- Move(dest.AsGpuRegister(), src.AsGpuRegister());
- } else if (dest.IsFpuRegister()) {
- CHECK(src.IsFpuRegister()) << src;
- if (size == 4) {
- MovS(dest.AsFpuRegister(), src.AsFpuRegister());
- } else if (size == 8) {
- MovD(dest.AsFpuRegister(), src.AsFpuRegister());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
- }
- }
- }
-}
-
-void Mips64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
- ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value());
-}
-
-void Mips64Assembler::CopyRawPtrFromThread(FrameOffset fr_offs,
- ThreadOffset64 thr_offs,
- ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), S1, thr_offs.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, fr_offs.Int32Value());
-}
-
-void Mips64Assembler::CopyRawPtrToThread(ThreadOffset64 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
- SP, fr_offs.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(),
- S1, thr_offs.Int32Value());
-}
-
-void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src,
- ManagedRegister mscratch, size_t size) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- CHECK(size == 4 || size == 8) << size;
- if (size == 4) {
- LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
- } else if (size == 8) {
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
- }
-}
-
-void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
- ManagedRegister mscratch, size_t size) {
- GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
- CHECK(size == 4 || size == 8) << size;
- if (size == 4) {
- LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(),
- src_offset.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
- } else if (size == 8) {
- LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(),
- src_offset.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
- }
-}
-
-void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
- ManagedRegister mscratch, size_t size) {
- GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
- CHECK(size == 4 || size == 8) << size;
- if (size == 4) {
- LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
- dest_offset.Int32Value());
- } else if (size == 8) {
- LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(),
- dest_offset.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
- }
-}
-
-void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
- FrameOffset src_base ATTRIBUTE_UNUSED,
- Offset src_offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
-}
-
-void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset,
- ManagedRegister src, Offset src_offset,
- ManagedRegister mscratch, size_t size) {
- GpuRegister scratch = mscratch.AsMips64().AsGpuRegister();
- CHECK(size == 4 || size == 8) << size;
- if (size == 4) {
- LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value());
- } else if (size == 8) {
- LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(),
- src_offset.Int32Value());
- StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(),
- dest_offset.Int32Value());
- } else {
- UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8";
- }
-}
-
-void Mips64Assembler::Copy(FrameOffset dest ATTRIBUTE_UNUSED,
- Offset dest_offset ATTRIBUTE_UNUSED,
- FrameOffset src ATTRIBUTE_UNUSED,
- Offset src_offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
-}
-
-void Mips64Assembler::MemoryBarrier(ManagedRegister mreg ATTRIBUTE_UNUSED) {
- // TODO: sync?
- UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
-}
-
-void Mips64Assembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
- FrameOffset handle_scope_offset,
- ManagedRegister min_reg,
- bool null_allowed) {
- Mips64ManagedRegister out_reg = mout_reg.AsMips64();
- Mips64ManagedRegister in_reg = min_reg.AsMips64();
- CHECK(in_reg.IsNoRegister() || in_reg.IsGpuRegister()) << in_reg;
- CHECK(out_reg.IsGpuRegister()) << out_reg;
- if (null_allowed) {
- Mips64Label null_arg;
- // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
- // the address in the handle scope holding the reference.
- // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
- if (in_reg.IsNoRegister()) {
- LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
- SP, handle_scope_offset.Int32Value());
- in_reg = out_reg;
- }
- if (!out_reg.Equals(in_reg)) {
- LoadConst32(out_reg.AsGpuRegister(), 0);
- }
- Beqzc(in_reg.AsGpuRegister(), &null_arg);
- Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
- Bind(&null_arg);
- } else {
- Daddiu64(out_reg.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
- }
-}
-
-void Mips64Assembler::CreateHandleScopeEntry(FrameOffset out_off,
- FrameOffset handle_scope_offset,
- ManagedRegister mscratch,
- bool null_allowed) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- if (null_allowed) {
- Mips64Label null_arg;
- LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
- handle_scope_offset.Int32Value());
- // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
- // the address in the handle scope holding the reference.
- // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
- Beqzc(scratch.AsGpuRegister(), &null_arg);
- Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
- Bind(&null_arg);
- } else {
- Daddiu64(scratch.AsGpuRegister(), SP, handle_scope_offset.Int32Value());
- }
- StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, out_off.Int32Value());
-}
-
-// Given a handle scope entry, load the associated reference.
-void Mips64Assembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
- ManagedRegister min_reg) {
- Mips64ManagedRegister out_reg = mout_reg.AsMips64();
- Mips64ManagedRegister in_reg = min_reg.AsMips64();
- CHECK(out_reg.IsGpuRegister()) << out_reg;
- CHECK(in_reg.IsGpuRegister()) << in_reg;
- Mips64Label null_arg;
- if (!out_reg.Equals(in_reg)) {
- LoadConst32(out_reg.AsGpuRegister(), 0);
- }
- Beqzc(in_reg.AsGpuRegister(), &null_arg);
- LoadFromOffset(kLoadDoubleword, out_reg.AsGpuRegister(),
- in_reg.AsGpuRegister(), 0);
- Bind(&null_arg);
-}
-
-void Mips64Assembler::VerifyObject(ManagedRegister src ATTRIBUTE_UNUSED,
- bool could_be_null ATTRIBUTE_UNUSED) {
- // TODO: not validating references
-}
-
-void Mips64Assembler::VerifyObject(FrameOffset src ATTRIBUTE_UNUSED,
- bool could_be_null ATTRIBUTE_UNUSED) {
- // TODO: not validating references
-}
-
-void Mips64Assembler::Jump(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
- Mips64ManagedRegister base = mbase.AsMips64();
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(base.IsGpuRegister()) << base;
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
- base.AsGpuRegister(), offset.Int32Value());
- Jr(scratch.AsGpuRegister());
- Nop();
-}
-
-void Mips64Assembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
- Mips64ManagedRegister base = mbase.AsMips64();
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(base.IsGpuRegister()) << base;
- CHECK(scratch.IsGpuRegister()) << scratch;
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
- base.AsGpuRegister(), offset.Int32Value());
- Jalr(scratch.AsGpuRegister());
- Nop();
- // TODO: place reference map on call
-}
-
-void Mips64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- CHECK(scratch.IsGpuRegister()) << scratch;
- // Call *(*(SP + base) + offset)
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
- SP, base.Int32Value());
- LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
- scratch.AsGpuRegister(), offset.Int32Value());
- Jalr(scratch.AsGpuRegister());
- Nop();
- // TODO: place reference map on call
-}
-
-void Mips64Assembler::CallFromThread(ThreadOffset64 offset ATTRIBUTE_UNUSED,
- ManagedRegister mscratch ATTRIBUTE_UNUSED) {
- UNIMPLEMENTED(FATAL) << "No MIPS64 implementation";
-}
-
-void Mips64Assembler::GetCurrentThread(ManagedRegister tr) {
- Move(tr.AsMips64().AsGpuRegister(), S1);
-}
-
-void Mips64Assembler::GetCurrentThread(FrameOffset offset,
- ManagedRegister mscratch ATTRIBUTE_UNUSED) {
- StoreToOffset(kStoreDoubleword, S1, SP, offset.Int32Value());
-}
-
-void Mips64Assembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
- Mips64ManagedRegister scratch = mscratch.AsMips64();
- exception_blocks_.emplace_back(scratch, stack_adjust);
- LoadFromOffset(kLoadDoubleword,
- scratch.AsGpuRegister(),
- S1,
- Thread::ExceptionOffset<kMips64PointerSize>().Int32Value());
- Bnezc(scratch.AsGpuRegister(), exception_blocks_.back().Entry());
-}
-
-void Mips64Assembler::EmitExceptionPoll(Mips64ExceptionSlowPath* exception) {
- Bind(exception->Entry());
- if (exception->stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSize(exception->stack_adjust_);
- }
- // Pass exception object as argument.
- // Don't care about preserving A0 as this call won't return.
- CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
- Move(A0, exception->scratch_.AsGpuRegister());
- // Set up call to Thread::Current()->pDeliverException
- LoadFromOffset(kLoadDoubleword,
- T9,
- S1,
- QUICK_ENTRYPOINT_OFFSET(kMips64PointerSize, pDeliverException).Int32Value());
- Jr(T9);
- Nop();
-
- // Call never returns
- Break();
-}
-
-} // namespace mips64
-} // namespace art
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
deleted file mode 100644
index 03eae91..0000000
--- a/compiler/utils/mips64/assembler_mips64.h
+++ /dev/null
@@ -1,1739 +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.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_
-#define ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_
-
-#include <deque>
-#include <utility>
-#include <vector>
-
-#include "arch/mips64/instruction_set_features_mips64.h"
-#include "base/arena_containers.h"
-#include "base/enums.h"
-#include "base/globals.h"
-#include "base/macros.h"
-#include "base/stl_util_identity.h"
-#include "constants_mips64.h"
-#include "heap_poisoning.h"
-#include "managed_register_mips64.h"
-#include "offsets.h"
-#include "utils/assembler.h"
-#include "utils/jni_macro_assembler.h"
-#include "utils/label.h"
-
-namespace art {
-namespace mips64 {
-
-enum LoadConst64Path {
- kLoadConst64PathZero = 0x0,
- kLoadConst64PathOri = 0x1,
- kLoadConst64PathDaddiu = 0x2,
- kLoadConst64PathLui = 0x4,
- kLoadConst64PathLuiOri = 0x8,
- kLoadConst64PathOriDahi = 0x10,
- kLoadConst64PathOriDati = 0x20,
- kLoadConst64PathLuiDahi = 0x40,
- kLoadConst64PathLuiDati = 0x80,
- kLoadConst64PathDaddiuDsrlX = 0x100,
- kLoadConst64PathOriDsllX = 0x200,
- kLoadConst64PathDaddiuDsllX = 0x400,
- kLoadConst64PathLuiOriDsllX = 0x800,
- kLoadConst64PathOriDsllXOri = 0x1000,
- kLoadConst64PathDaddiuDsllXOri = 0x2000,
- kLoadConst64PathDaddiuDahi = 0x4000,
- kLoadConst64PathDaddiuDati = 0x8000,
- kLoadConst64PathDinsu1 = 0x10000,
- kLoadConst64PathDinsu2 = 0x20000,
- kLoadConst64PathCatchAll = 0x40000,
- kLoadConst64PathAllPaths = 0x7ffff,
-};
-
-template <typename Asm>
-void TemplateLoadConst32(Asm* a, GpuRegister rd, int32_t value) {
- if (IsUint<16>(value)) {
- // Use OR with (unsigned) immediate to encode 16b unsigned int.
- a->Ori(rd, ZERO, value);
- } else if (IsInt<16>(value)) {
- // Use ADD with (signed) immediate to encode 16b signed int.
- a->Addiu(rd, ZERO, value);
- } else {
- // Set 16 most significant bits of value. The "lui" instruction
- // also clears the 16 least significant bits to zero.
- a->Lui(rd, value >> 16);
- if (value & 0xFFFF) {
- // If the 16 least significant bits are non-zero, set them
- // here.
- a->Ori(rd, rd, value);
- }
- }
-}
-
-static inline int InstrCountForLoadReplicatedConst32(int64_t value) {
- int32_t x = Low32Bits(value);
- int32_t y = High32Bits(value);
-
- if (x == y) {
- return (IsUint<16>(x) || IsInt<16>(x) || ((x & 0xFFFF) == 0)) ? 2 : 3;
- }
-
- return INT_MAX;
-}
-
-template <typename Asm, typename Rtype, typename Vtype>
-void TemplateLoadConst64(Asm* a, Rtype rd, Vtype value) {
- int bit31 = (value & UINT64_C(0x80000000)) != 0;
- int rep32_count = InstrCountForLoadReplicatedConst32(value);
-
- // Loads with 1 instruction.
- if (IsUint<16>(value)) {
- // 64-bit value can be loaded as an unsigned 16-bit number.
- a->RecordLoadConst64Path(kLoadConst64PathOri);
- a->Ori(rd, ZERO, value);
- } else if (IsInt<16>(value)) {
- // 64-bit value can be loaded as an signed 16-bit number.
- a->RecordLoadConst64Path(kLoadConst64PathDaddiu);
- a->Daddiu(rd, ZERO, value);
- } else if ((value & 0xFFFF) == 0 && IsInt<16>(value >> 16)) {
- // 64-bit value can be loaded as an signed 32-bit number which has all
- // of its 16 least significant bits set to zero.
- a->RecordLoadConst64Path(kLoadConst64PathLui);
- a->Lui(rd, value >> 16);
- } else if (IsInt<32>(value)) {
- // Loads with 2 instructions.
- // 64-bit value can be loaded as an signed 32-bit number which has some
- // or all of its 16 least significant bits set to one.
- a->RecordLoadConst64Path(kLoadConst64PathLuiOri);
- a->Lui(rd, value >> 16);
- a->Ori(rd, rd, value);
- } else if ((value & 0xFFFF0000) == 0 && IsInt<16>(value >> 32)) {
- // 64-bit value which consists of an unsigned 16-bit value in its
- // least significant 32-bits, and a signed 16-bit value in its
- // most significant 32-bits.
- a->RecordLoadConst64Path(kLoadConst64PathOriDahi);
- a->Ori(rd, ZERO, value);
- a->Dahi(rd, value >> 32);
- } else if ((value & UINT64_C(0xFFFFFFFF0000)) == 0) {
- // 64-bit value which consists of an unsigned 16-bit value in its
- // least significant 48-bits, and a signed 16-bit value in its
- // most significant 16-bits.
- a->RecordLoadConst64Path(kLoadConst64PathOriDati);
- a->Ori(rd, ZERO, value);
- a->Dati(rd, value >> 48);
- } else if ((value & 0xFFFF) == 0 &&
- (-32768 - bit31) <= (value >> 32) && (value >> 32) <= (32767 - bit31)) {
- // 16 LSBs (Least Significant Bits) all set to zero.
- // 48 MSBs (Most Significant Bits) hold a signed 32-bit value.
- a->RecordLoadConst64Path(kLoadConst64PathLuiDahi);
- a->Lui(rd, value >> 16);
- a->Dahi(rd, (value >> 32) + bit31);
- } else if ((value & 0xFFFF) == 0 && ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) {
- // 16 LSBs all set to zero.
- // 48 MSBs hold a signed value which can't be represented by signed
- // 32-bit number, and the middle 16 bits are all zero, or all one.
- a->RecordLoadConst64Path(kLoadConst64PathLuiDati);
- a->Lui(rd, value >> 16);
- a->Dati(rd, (value >> 48) + bit31);
- } else if (IsInt<16>(static_cast<int32_t>(value)) &&
- (-32768 - bit31) <= (value >> 32) && (value >> 32) <= (32767 - bit31)) {
- // 32 LSBs contain an unsigned 16-bit number.
- // 32 MSBs contain a signed 16-bit number.
- a->RecordLoadConst64Path(kLoadConst64PathDaddiuDahi);
- a->Daddiu(rd, ZERO, value);
- a->Dahi(rd, (value >> 32) + bit31);
- } else if (IsInt<16>(static_cast<int32_t>(value)) &&
- ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF)) {
- // 48 LSBs contain an unsigned 16-bit number.
- // 16 MSBs contain a signed 16-bit number.
- a->RecordLoadConst64Path(kLoadConst64PathDaddiuDati);
- a->Daddiu(rd, ZERO, value);
- a->Dati(rd, (value >> 48) + bit31);
- } else if (IsPowerOfTwo(value + UINT64_C(1))) {
- // 64-bit values which have their "n" MSBs set to one, and their
- // "64-n" LSBs set to zero. "n" must meet the restrictions 0 < n < 64.
- int shift_cnt = 64 - CTZ(value + UINT64_C(1));
- a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsrlX);
- a->Daddiu(rd, ZERO, -1);
- if (shift_cnt < 32) {
- a->Dsrl(rd, rd, shift_cnt);
- } else {
- a->Dsrl32(rd, rd, shift_cnt & 31);
- }
- } else {
- int shift_cnt = CTZ(value);
- int64_t tmp = value >> shift_cnt;
- a->RecordLoadConst64Path(kLoadConst64PathOriDsllX);
- if (IsUint<16>(tmp)) {
- // Value can be computed by loading a 16-bit unsigned value, and
- // then shifting left.
- a->Ori(rd, ZERO, tmp);
- if (shift_cnt < 32) {
- a->Dsll(rd, rd, shift_cnt);
- } else {
- a->Dsll32(rd, rd, shift_cnt & 31);
- }
- } else if (IsInt<16>(tmp)) {
- // Value can be computed by loading a 16-bit signed value, and
- // then shifting left.
- a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsllX);
- a->Daddiu(rd, ZERO, tmp);
- if (shift_cnt < 32) {
- a->Dsll(rd, rd, shift_cnt);
- } else {
- a->Dsll32(rd, rd, shift_cnt & 31);
- }
- } else if (rep32_count < 3) {
- // Value being loaded has 32 LSBs equal to the 32 MSBs, and the
- // value loaded into the 32 LSBs can be loaded with a single
- // MIPS instruction.
- a->LoadConst32(rd, value);
- a->Dinsu(rd, rd, 32, 32);
- a->RecordLoadConst64Path(kLoadConst64PathDinsu1);
- } else if (IsInt<32>(tmp)) {
- // Loads with 3 instructions.
- // Value can be computed by loading a 32-bit signed value, and
- // then shifting left.
- a->RecordLoadConst64Path(kLoadConst64PathLuiOriDsllX);
- a->Lui(rd, tmp >> 16);
- a->Ori(rd, rd, tmp);
- if (shift_cnt < 32) {
- a->Dsll(rd, rd, shift_cnt);
- } else {
- a->Dsll32(rd, rd, shift_cnt & 31);
- }
- } else {
- shift_cnt = 16 + CTZ(value >> 16);
- tmp = value >> shift_cnt;
- if (IsUint<16>(tmp)) {
- // Value can be computed by loading a 16-bit unsigned value,
- // shifting left, and "or"ing in another 16-bit unsigned value.
- a->RecordLoadConst64Path(kLoadConst64PathOriDsllXOri);
- a->Ori(rd, ZERO, tmp);
- if (shift_cnt < 32) {
- a->Dsll(rd, rd, shift_cnt);
- } else {
- a->Dsll32(rd, rd, shift_cnt & 31);
- }
- a->Ori(rd, rd, value);
- } else if (IsInt<16>(tmp)) {
- // Value can be computed by loading a 16-bit signed value,
- // shifting left, and "or"ing in a 16-bit unsigned value.
- a->RecordLoadConst64Path(kLoadConst64PathDaddiuDsllXOri);
- a->Daddiu(rd, ZERO, tmp);
- if (shift_cnt < 32) {
- a->Dsll(rd, rd, shift_cnt);
- } else {
- a->Dsll32(rd, rd, shift_cnt & 31);
- }
- a->Ori(rd, rd, value);
- } else if (rep32_count < 4) {
- // Value being loaded has 32 LSBs equal to the 32 MSBs, and the
- // value in the 32 LSBs requires 2 MIPS instructions to load.
- a->LoadConst32(rd, value);
- a->Dinsu(rd, rd, 32, 32);
- a->RecordLoadConst64Path(kLoadConst64PathDinsu2);
- } else {
- // Loads with 3-4 instructions.
- // Catch-all case to get any other 64-bit values which aren't
- // handled by special cases above.
- uint64_t tmp2 = value;
- a->RecordLoadConst64Path(kLoadConst64PathCatchAll);
- a->LoadConst32(rd, value);
- if (bit31) {
- tmp2 += UINT64_C(0x100000000);
- }
- if (((tmp2 >> 32) & 0xFFFF) != 0) {
- a->Dahi(rd, tmp2 >> 32);
- }
- if (tmp2 & UINT64_C(0x800000000000)) {
- tmp2 += UINT64_C(0x1000000000000);
- }
- if ((tmp2 >> 48) != 0) {
- a->Dati(rd, tmp2 >> 48);
- }
- }
- }
- }
-}
-
-static constexpr size_t kMips64HalfwordSize = 2;
-static constexpr size_t kMips64WordSize = 4;
-static constexpr size_t kMips64DoublewordSize = 8;
-
-enum LoadOperandType {
- kLoadSignedByte,
- kLoadUnsignedByte,
- kLoadSignedHalfword,
- kLoadUnsignedHalfword,
- kLoadWord,
- kLoadUnsignedWord,
- kLoadDoubleword,
- kLoadQuadword
-};
-
-enum StoreOperandType {
- kStoreByte,
- kStoreHalfword,
- kStoreWord,
- kStoreDoubleword,
- kStoreQuadword
-};
-
-// Used to test the values returned by ClassS/ClassD.
-enum FPClassMaskType {
- kSignalingNaN = 0x001,
- kQuietNaN = 0x002,
- kNegativeInfinity = 0x004,
- kNegativeNormal = 0x008,
- kNegativeSubnormal = 0x010,
- kNegativeZero = 0x020,
- kPositiveInfinity = 0x040,
- kPositiveNormal = 0x080,
- kPositiveSubnormal = 0x100,
- kPositiveZero = 0x200,
-};
-
-class Mips64Label : public Label {
- public:
- Mips64Label() : prev_branch_id_plus_one_(0) {}
-
- Mips64Label(Mips64Label&& src)
- : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {}
-
- private:
- uint32_t prev_branch_id_plus_one_; // To get distance from preceding branch, if any.
-
- friend class Mips64Assembler;
- DISALLOW_COPY_AND_ASSIGN(Mips64Label);
-};
-
-// Assembler literal is a value embedded in code, retrieved using a PC-relative load.
-class Literal {
- public:
- static constexpr size_t kMaxSize = 8;
-
- Literal(uint32_t size, const uint8_t* data)
- : label_(), size_(size) {
- DCHECK_LE(size, Literal::kMaxSize);
- memcpy(data_, data, size);
- }
-
- template <typename T>
- T GetValue() const {
- DCHECK_EQ(size_, sizeof(T));
- T value;
- memcpy(&value, data_, sizeof(T));
- return value;
- }
-
- uint32_t GetSize() const {
- return size_;
- }
-
- const uint8_t* GetData() const {
- return data_;
- }
-
- Mips64Label* GetLabel() {
- return &label_;
- }
-
- const Mips64Label* GetLabel() const {
- return &label_;
- }
-
- private:
- Mips64Label label_;
- const uint32_t size_;
- uint8_t data_[kMaxSize];
-
- DISALLOW_COPY_AND_ASSIGN(Literal);
-};
-
-// Jump table: table of labels emitted after the code and before the literals. Similar to literals.
-class JumpTable {
- public:
- explicit JumpTable(std::vector<Mips64Label*>&& labels)
- : label_(), labels_(std::move(labels)) {
- }
-
- size_t GetSize() const {
- return labels_.size() * sizeof(uint32_t);
- }
-
- const std::vector<Mips64Label*>& GetData() const {
- return labels_;
- }
-
- Mips64Label* GetLabel() {
- return &label_;
- }
-
- const Mips64Label* GetLabel() const {
- return &label_;
- }
-
- private:
- Mips64Label label_;
- std::vector<Mips64Label*> labels_;
-
- DISALLOW_COPY_AND_ASSIGN(JumpTable);
-};
-
-// Slowpath entered when Thread::Current()->_exception is non-null.
-class Mips64ExceptionSlowPath {
- public:
- explicit Mips64ExceptionSlowPath(Mips64ManagedRegister scratch, size_t stack_adjust)
- : scratch_(scratch), stack_adjust_(stack_adjust) {}
-
- Mips64ExceptionSlowPath(Mips64ExceptionSlowPath&& src)
- : scratch_(src.scratch_),
- stack_adjust_(src.stack_adjust_),
- exception_entry_(std::move(src.exception_entry_)) {}
-
- private:
- Mips64Label* Entry() { return &exception_entry_; }
- const Mips64ManagedRegister scratch_;
- const size_t stack_adjust_;
- Mips64Label exception_entry_;
-
- friend class Mips64Assembler;
- DISALLOW_COPY_AND_ASSIGN(Mips64ExceptionSlowPath);
-};
-
-class Mips64Assembler final : public Assembler, public JNIMacroAssembler<PointerSize::k64> {
- public:
- using JNIBase = JNIMacroAssembler<PointerSize::k64>;
-
- explicit Mips64Assembler(ArenaAllocator* allocator,
- const Mips64InstructionSetFeatures* instruction_set_features = nullptr)
- : Assembler(allocator),
- overwriting_(false),
- overwrite_location_(0),
- literals_(allocator->Adapter(kArenaAllocAssembler)),
- long_literals_(allocator->Adapter(kArenaAllocAssembler)),
- jump_tables_(allocator->Adapter(kArenaAllocAssembler)),
- last_position_adjustment_(0),
- last_old_position_(0),
- last_branch_id_(0),
- has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false) {
- cfi().DelayEmittingAdvancePCs();
- }
-
- virtual ~Mips64Assembler() {
- for (auto& branch : branches_) {
- CHECK(branch.IsResolved());
- }
- }
-
- size_t CodeSize() const override { return Assembler::CodeSize(); }
- DebugFrameOpCodeWriterForAssembler& cfi() override { return Assembler::cfi(); }
-
- // Emit Machine Instructions.
- void Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64
- void Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
-
- void MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void MuhR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Dmuh(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
- void Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64
-
- void And(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Or(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt);
-
- void Bitswap(GpuRegister rd, GpuRegister rt);
- void Dbitswap(GpuRegister rd, GpuRegister rt); // MIPS64
- void Seb(GpuRegister rd, GpuRegister rt);
- void Seh(GpuRegister rd, GpuRegister rt);
- void Dsbh(GpuRegister rd, GpuRegister rt); // MIPS64
- void Dshd(GpuRegister rd, GpuRegister rt); // MIPS64
- void Dext(GpuRegister rs, GpuRegister rt, int pos, int size); // MIPS64
- void Ins(GpuRegister rt, GpuRegister rs, int pos, int size);
- void Dins(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
- void Dinsm(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
- void Dinsu(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
- void DblIns(GpuRegister rt, GpuRegister rs, int pos, int size); // MIPS64
- void Lsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne);
- void Dlsa(GpuRegister rd, GpuRegister rs, GpuRegister rt, int saPlusOne); // MIPS64
- void Wsbh(GpuRegister rd, GpuRegister rt);
- void Sc(GpuRegister rt, GpuRegister base, int16_t imm9 = 0);
- void Scd(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); // MIPS64
- void Ll(GpuRegister rt, GpuRegister base, int16_t imm9 = 0);
- void Lld(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); // MIPS64
-
- void Sll(GpuRegister rd, GpuRegister rt, int shamt);
- void Srl(GpuRegister rd, GpuRegister rt, int shamt);
- void Rotr(GpuRegister rd, GpuRegister rt, int shamt);
- void Sra(GpuRegister rd, GpuRegister rt, int shamt);
- void Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs);
- void Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs);
- void Rotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs);
- void Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs);
- void Dsll(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsrl(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Drotr(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsra(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsll32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsrl32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Drotr32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsra32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64
- void Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64
- void Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64
- void Drotrv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64
- void Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64
-
- void Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64
- void Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64
- void Lwpc(GpuRegister rs, uint32_t imm19);
- void Lwupc(GpuRegister rs, uint32_t imm19); // MIPS64
- void Ldpc(GpuRegister rs, uint32_t imm18); // MIPS64
- void Lui(GpuRegister rt, uint16_t imm16);
- void Aui(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Daui(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64
- void Dahi(GpuRegister rs, uint16_t imm16); // MIPS64
- void Dati(GpuRegister rs, uint16_t imm16); // MIPS64
- void Sync(uint32_t stype);
-
- void Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64
-
- void Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
- void Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt);
- void Clz(GpuRegister rd, GpuRegister rs);
- void Clo(GpuRegister rd, GpuRegister rs);
- void Dclz(GpuRegister rd, GpuRegister rs); // MIPS64
- void Dclo(GpuRegister rd, GpuRegister rs); // MIPS64
-
- void Jalr(GpuRegister rd, GpuRegister rs);
- void Jalr(GpuRegister rs);
- void Jr(GpuRegister rs);
- void Auipc(GpuRegister rs, uint16_t imm16);
- void Addiupc(GpuRegister rs, uint32_t imm19);
- void Bc(uint32_t imm26);
- void Balc(uint32_t imm26);
- void Jic(GpuRegister rt, uint16_t imm16);
- void Jialc(GpuRegister rt, uint16_t imm16);
- void Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Bltzc(GpuRegister rt, uint16_t imm16);
- void Bgtzc(GpuRegister rt, uint16_t imm16);
- void Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Bgezc(GpuRegister rt, uint16_t imm16);
- void Blezc(GpuRegister rt, uint16_t imm16);
- void Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void Beqzc(GpuRegister rs, uint32_t imm21);
- void Bnezc(GpuRegister rs, uint32_t imm21);
- void Bc1eqz(FpuRegister ft, uint16_t imm16);
- void Bc1nez(FpuRegister ft, uint16_t imm16);
- void Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R2
- void Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R2
- void Beqz(GpuRegister rt, uint16_t imm16); // R2
- void Bnez(GpuRegister rt, uint16_t imm16); // R2
- void Bltz(GpuRegister rt, uint16_t imm16); // R2
- void Bgez(GpuRegister rt, uint16_t imm16); // R2
- void Blez(GpuRegister rt, uint16_t imm16); // R2
- void Bgtz(GpuRegister rt, uint16_t imm16); // R2
-
- void AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SqrtS(FpuRegister fd, FpuRegister fs);
- void SqrtD(FpuRegister fd, FpuRegister fs);
- void AbsS(FpuRegister fd, FpuRegister fs);
- void AbsD(FpuRegister fd, FpuRegister fs);
- void MovS(FpuRegister fd, FpuRegister fs);
- void MovD(FpuRegister fd, FpuRegister fs);
- void NegS(FpuRegister fd, FpuRegister fs);
- void NegD(FpuRegister fd, FpuRegister fs);
- void RoundLS(FpuRegister fd, FpuRegister fs);
- void RoundLD(FpuRegister fd, FpuRegister fs);
- void RoundWS(FpuRegister fd, FpuRegister fs);
- void RoundWD(FpuRegister fd, FpuRegister fs);
- void TruncLS(FpuRegister fd, FpuRegister fs);
- void TruncLD(FpuRegister fd, FpuRegister fs);
- void TruncWS(FpuRegister fd, FpuRegister fs);
- void TruncWD(FpuRegister fd, FpuRegister fs);
- void CeilLS(FpuRegister fd, FpuRegister fs);
- void CeilLD(FpuRegister fd, FpuRegister fs);
- void CeilWS(FpuRegister fd, FpuRegister fs);
- void CeilWD(FpuRegister fd, FpuRegister fs);
- void FloorLS(FpuRegister fd, FpuRegister fs);
- void FloorLD(FpuRegister fd, FpuRegister fs);
- void FloorWS(FpuRegister fd, FpuRegister fs);
- void FloorWD(FpuRegister fd, FpuRegister fs);
- void SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SeleqzS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SeleqzD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SelnezS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void SelnezD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void RintS(FpuRegister fd, FpuRegister fs);
- void RintD(FpuRegister fd, FpuRegister fs);
- void ClassS(FpuRegister fd, FpuRegister fs);
- void ClassD(FpuRegister fd, FpuRegister fs);
- void MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUnS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpEqS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUeqS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpLtS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUltS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpLeS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUleS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpOrS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUneS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpNeS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUnD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpEqD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUeqD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpLtD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUltD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpLeD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUleD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpOrD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpUneD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
- void CmpNeD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
-
- void Cvtsw(FpuRegister fd, FpuRegister fs);
- void Cvtdw(FpuRegister fd, FpuRegister fs);
- void Cvtsd(FpuRegister fd, FpuRegister fs);
- void Cvtds(FpuRegister fd, FpuRegister fs);
- void Cvtsl(FpuRegister fd, FpuRegister fs);
- void Cvtdl(FpuRegister fd, FpuRegister fs);
-
- void Mfc1(GpuRegister rt, FpuRegister fs);
- void Mfhc1(GpuRegister rt, FpuRegister fs);
- void Mtc1(GpuRegister rt, FpuRegister fs);
- void Mthc1(GpuRegister rt, FpuRegister fs);
- void Dmfc1(GpuRegister rt, FpuRegister fs); // MIPS64
- void Dmtc1(GpuRegister rt, FpuRegister fs); // MIPS64
- void Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
- void Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
- void Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
- void Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
-
- void Break();
- void Nop();
- void Move(GpuRegister rd, GpuRegister rs);
- void Clear(GpuRegister rd);
- void Not(GpuRegister rd, GpuRegister rs);
-
- // MSA instructions.
- void AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void Ffint_sW(VectorRegister wd, VectorRegister ws);
- void Ffint_sD(VectorRegister wd, VectorRegister ws);
- void Ftint_sW(VectorRegister wd, VectorRegister ws);
- void Ftint_sD(VectorRegister wd, VectorRegister ws);
-
- void SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- // Immediate shift instructions, where shamtN denotes shift amount (must be between 0 and 2^N-1).
- void SlliB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SlliH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SlliW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SlliD(VectorRegister wd, VectorRegister ws, int shamt6);
- void SraiB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SraiH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SraiW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SraiD(VectorRegister wd, VectorRegister ws, int shamt6);
- void SrliB(VectorRegister wd, VectorRegister ws, int shamt3);
- void SrliH(VectorRegister wd, VectorRegister ws, int shamt4);
- void SrliW(VectorRegister wd, VectorRegister ws, int shamt5);
- void SrliD(VectorRegister wd, VectorRegister ws, int shamt6);
-
- void MoveV(VectorRegister wd, VectorRegister ws);
- void SplatiB(VectorRegister wd, VectorRegister ws, int n4);
- void SplatiH(VectorRegister wd, VectorRegister ws, int n3);
- void SplatiW(VectorRegister wd, VectorRegister ws, int n2);
- void SplatiD(VectorRegister wd, VectorRegister ws, int n1);
- void Copy_sB(GpuRegister rd, VectorRegister ws, int n4);
- void Copy_sH(GpuRegister rd, VectorRegister ws, int n3);
- void Copy_sW(GpuRegister rd, VectorRegister ws, int n2);
- void Copy_sD(GpuRegister rd, VectorRegister ws, int n1);
- void Copy_uB(GpuRegister rd, VectorRegister ws, int n4);
- void Copy_uH(GpuRegister rd, VectorRegister ws, int n3);
- void Copy_uW(GpuRegister rd, VectorRegister ws, int n2);
- void InsertB(VectorRegister wd, GpuRegister rs, int n4);
- void InsertH(VectorRegister wd, GpuRegister rs, int n3);
- void InsertW(VectorRegister wd, GpuRegister rs, int n2);
- void InsertD(VectorRegister wd, GpuRegister rs, int n1);
- void FillB(VectorRegister wd, GpuRegister rs);
- void FillH(VectorRegister wd, GpuRegister rs);
- void FillW(VectorRegister wd, GpuRegister rs);
- void FillD(VectorRegister wd, GpuRegister rs);
-
- void LdiB(VectorRegister wd, int imm8);
- void LdiH(VectorRegister wd, int imm10);
- void LdiW(VectorRegister wd, int imm10);
- void LdiD(VectorRegister wd, int imm10);
- void LdB(VectorRegister wd, GpuRegister rs, int offset);
- void LdH(VectorRegister wd, GpuRegister rs, int offset);
- void LdW(VectorRegister wd, GpuRegister rs, int offset);
- void LdD(VectorRegister wd, GpuRegister rs, int offset);
- void StB(VectorRegister wd, GpuRegister rs, int offset);
- void StH(VectorRegister wd, GpuRegister rs, int offset);
- void StW(VectorRegister wd, GpuRegister rs, int offset);
- void StD(VectorRegister wd, GpuRegister rs, int offset);
-
- void IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
- void Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
-
- void PcntB(VectorRegister wd, VectorRegister ws);
- void PcntH(VectorRegister wd, VectorRegister ws);
- void PcntW(VectorRegister wd, VectorRegister ws);
- void PcntD(VectorRegister wd, VectorRegister ws);
-
- // Helper for replicating floating point value in all destination elements.
- void ReplicateFPToVectorRegister(VectorRegister dst, FpuRegister src, bool is_double);
-
- // Higher level composite instructions.
- int InstrCountForLoadReplicatedConst32(int64_t);
- void LoadConst32(GpuRegister rd, int32_t value);
- void LoadConst64(GpuRegister rd, int64_t value); // MIPS64
-
- // This function is only used for testing purposes.
- void RecordLoadConst64Path(int value);
-
- void Addiu32(GpuRegister rt, GpuRegister rs, int32_t value);
- void Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp = AT); // MIPS64
-
- //
- // Heap poisoning.
- //
-
- // Poison a heap reference contained in `src` and store it in `dst`.
- void PoisonHeapReference(GpuRegister dst, GpuRegister src) {
- // dst = -src.
- // Negate the 32-bit ref.
- Dsubu(dst, ZERO, src);
- // And constrain it to 32 bits (zero-extend into bits 32 through 63) as on Arm64 and x86/64.
- Dext(dst, dst, 0, 32);
- }
- // Poison a heap reference contained in `reg`.
- void PoisonHeapReference(GpuRegister reg) {
- // reg = -reg.
- PoisonHeapReference(reg, reg);
- }
- // Unpoison a heap reference contained in `reg`.
- void UnpoisonHeapReference(GpuRegister reg) {
- // reg = -reg.
- // Negate the 32-bit ref.
- Dsubu(reg, ZERO, reg);
- // And constrain it to 32 bits (zero-extend into bits 32 through 63) as on Arm64 and x86/64.
- Dext(reg, reg, 0, 32);
- }
- // Poison a heap reference contained in `reg` if heap poisoning is enabled.
- void MaybePoisonHeapReference(GpuRegister reg) {
- if (kPoisonHeapReferences) {
- PoisonHeapReference(reg);
- }
- }
- // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
- void MaybeUnpoisonHeapReference(GpuRegister reg) {
- if (kPoisonHeapReferences) {
- UnpoisonHeapReference(reg);
- }
- }
-
- void Bind(Label* label) override {
- Bind(down_cast<Mips64Label*>(label));
- }
- void Jump(Label* label ATTRIBUTE_UNUSED) override {
- UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS64";
- }
-
- void Bind(Mips64Label* label);
-
- // Don't warn about a different virtual Bind/Jump in the base class.
- using JNIBase::Bind;
- using JNIBase::Jump;
-
- // Create a new label that can be used with Jump/Bind calls.
- std::unique_ptr<JNIMacroLabel> CreateLabel() override {
- LOG(FATAL) << "Not implemented on MIPS64";
- UNREACHABLE();
- }
- // Emit an unconditional jump to the label.
- void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS64";
- UNREACHABLE();
- }
- // Emit a conditional jump to the label by applying a unary condition test to the register.
- void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED,
- JNIMacroUnaryCondition cond ATTRIBUTE_UNUSED,
- ManagedRegister test ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS64";
- UNREACHABLE();
- }
-
- // Code at this offset will serve as the target for the Jump call.
- void Bind(JNIMacroLabel* label ATTRIBUTE_UNUSED) override {
- LOG(FATAL) << "Not implemented on MIPS64";
- UNREACHABLE();
- }
-
- // Create a new literal with a given value.
- // NOTE: Force the template parameter to be explicitly specified.
- template <typename T>
- Literal* NewLiteral(typename Identity<T>::type value) {
- static_assert(std::is_integral<T>::value, "T must be an integral type.");
- return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
- }
-
- // Load label address using PC-relative loads. To be used with data labels in the literal /
- // jump table area only and not with regular code labels.
- void LoadLabelAddress(GpuRegister dest_reg, Mips64Label* label);
-
- // Create a new literal with the given data.
- Literal* NewLiteral(size_t size, const uint8_t* data);
-
- // Load literal using PC-relative loads.
- void LoadLiteral(GpuRegister dest_reg, LoadOperandType load_type, Literal* literal);
-
- // Create a jump table for the given labels that will be emitted when finalizing.
- // When the table is emitted, offsets will be relative to the location of the table.
- // The table location is determined by the location of its label (the label precedes
- // the table data) and should be loaded using LoadLabelAddress().
- JumpTable* CreateJumpTable(std::vector<Mips64Label*>&& labels);
-
- // When `is_bare` is false, the branches will promote to long (if the range
- // of the individual branch instruction is insufficient) and the delay/
- // forbidden slots will be taken care of.
- // Use `is_bare = false` when the branch target may be out of reach of the
- // individual branch instruction. IOW, this is for general purpose use.
- //
- // When `is_bare` is true, just the branch instructions will be generated
- // leaving delay/forbidden slot filling up to the caller and the branches
- // won't promote to long if the range is insufficient (you'll get a
- // compilation error when the range is exceeded).
- // Use `is_bare = true` when the branch target is known to be within reach
- // of the individual branch instruction. This is intended for small local
- // optimizations around delay/forbidden slots.
- // Also prefer using `is_bare = true` if the code near the branch is to be
- // patched or analyzed at run time (e.g. introspection) to
- // - show the intent and
- // - fail during compilation rather than during patching/execution if the
- // bare branch range is insufficent but the code size and layout are
- // expected to remain unchanged
- //
- // R6 compact branches without delay/forbidden slots.
- void Bc(Mips64Label* label, bool is_bare = false);
- void Balc(Mips64Label* label, bool is_bare = false);
- // R6 compact branches with forbidden slots.
- void Bltc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bltzc(GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bgtzc(GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bgec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bgezc(GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Blezc(GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bltuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bgeuc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Beqc(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Bnec(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false);
- void Beqzc(GpuRegister rs, Mips64Label* label, bool is_bare = false);
- void Bnezc(GpuRegister rs, Mips64Label* label, bool is_bare = false);
- // R6 branches with delay slots.
- void Bc1eqz(FpuRegister ft, Mips64Label* label, bool is_bare = false);
- void Bc1nez(FpuRegister ft, Mips64Label* label, bool is_bare = false);
- // R2 branches with delay slots that are also available on R6.
- // The `is_bare` parameter exists and is checked in these branches only to
- // prevent programming mistakes. These branches never promote to long, not
- // even if `is_bare` is false.
- void Bltz(GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Bgtz(GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Bgez(GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Blez(GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Beq(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Bne(GpuRegister rs, GpuRegister rt, Mips64Label* label, bool is_bare = false); // R2
- void Beqz(GpuRegister rs, Mips64Label* label, bool is_bare = false); // R2
- void Bnez(GpuRegister rs, Mips64Label* label, bool is_bare = false); // R2
-
- void EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, size_t size);
- void AdjustBaseAndOffset(GpuRegister& base, int32_t& offset, bool is_doubleword);
- // If element_size_shift is negative at entry, its value will be calculated based on the offset.
- void AdjustBaseOffsetAndElementSizeShift(GpuRegister& base,
- int32_t& offset,
- int& element_size_shift);
-
- private:
- // This will be used as an argument for loads/stores
- // when there is no need for implicit null checks.
- struct NoImplicitNullChecker {
- void operator()() const {}
- };
-
- public:
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreConstToOffset(StoreOperandType type,
- int64_t value,
- GpuRegister base,
- int32_t offset,
- GpuRegister temp,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- // We permit `base` and `temp` to coincide (however, we check that neither is AT),
- // in which case the `base` register may be overwritten in the process.
- CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base.
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kStoreDoubleword));
- GpuRegister reg;
- // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp`
- // to load and hold the value but we can use AT instead as AT hasn't been used yet.
- // Otherwise, `temp` can be used for the value. And if `temp` is the same as the
- // original `base` (that is, `base` prior to the adjustment), the original `base`
- // register will be overwritten.
- if (base == temp) {
- temp = AT;
- }
-
- if (type == kStoreDoubleword && IsAligned<kMips64DoublewordSize>(offset)) {
- if (value == 0) {
- reg = ZERO;
- } else {
- reg = temp;
- LoadConst64(reg, value);
- }
- Sd(reg, base, offset);
- null_checker();
- } else {
- uint32_t low = Low32Bits(value);
- uint32_t high = High32Bits(value);
- if (low == 0) {
- reg = ZERO;
- } else {
- reg = temp;
- LoadConst32(reg, low);
- }
- switch (type) {
- case kStoreByte:
- Sb(reg, base, offset);
- break;
- case kStoreHalfword:
- Sh(reg, base, offset);
- break;
- case kStoreWord:
- Sw(reg, base, offset);
- break;
- case kStoreDoubleword:
- // not aligned to kMips64DoublewordSize
- CHECK_ALIGNED(offset, kMips64WordSize);
- Sw(reg, base, offset);
- null_checker();
- if (high == 0) {
- reg = ZERO;
- } else {
- reg = temp;
- if (high != low) {
- LoadConst32(reg, high);
- }
- }
- Sw(reg, base, offset + kMips64WordSize);
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kStoreDoubleword) {
- null_checker();
- }
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadFromOffset(LoadOperandType type,
- GpuRegister reg,
- GpuRegister base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kLoadDoubleword));
-
- switch (type) {
- case kLoadSignedByte:
- Lb(reg, base, offset);
- break;
- case kLoadUnsignedByte:
- Lbu(reg, base, offset);
- break;
- case kLoadSignedHalfword:
- Lh(reg, base, offset);
- break;
- case kLoadUnsignedHalfword:
- Lhu(reg, base, offset);
- break;
- case kLoadWord:
- CHECK_ALIGNED(offset, kMips64WordSize);
- Lw(reg, base, offset);
- break;
- case kLoadUnsignedWord:
- CHECK_ALIGNED(offset, kMips64WordSize);
- Lwu(reg, base, offset);
- break;
- case kLoadDoubleword:
- if (!IsAligned<kMips64DoublewordSize>(offset)) {
- CHECK_ALIGNED(offset, kMips64WordSize);
- Lwu(reg, base, offset);
- null_checker();
- Lwu(TMP2, base, offset + kMips64WordSize);
- Dinsu(reg, TMP2, 32, 32);
- } else {
- Ld(reg, base, offset);
- null_checker();
- }
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kLoadDoubleword) {
- null_checker();
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void LoadFpuFromOffset(LoadOperandType type,
- FpuRegister reg,
- GpuRegister base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- int element_size_shift = -1;
- if (type != kLoadQuadword) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kLoadDoubleword));
- } else {
- AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
- }
-
- switch (type) {
- case kLoadWord:
- CHECK_ALIGNED(offset, kMips64WordSize);
- Lwc1(reg, base, offset);
- null_checker();
- break;
- case kLoadDoubleword:
- if (!IsAligned<kMips64DoublewordSize>(offset)) {
- CHECK_ALIGNED(offset, kMips64WordSize);
- Lwc1(reg, base, offset);
- null_checker();
- Lw(TMP2, base, offset + kMips64WordSize);
- Mthc1(TMP2, reg);
- } else {
- Ldc1(reg, base, offset);
- null_checker();
- }
- break;
- case kLoadQuadword:
- switch (element_size_shift) {
- case TIMES_1: LdB(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_2: LdH(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_4: LdW(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_8: LdD(static_cast<VectorRegister>(reg), base, offset); break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- null_checker();
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreToOffset(StoreOperandType type,
- GpuRegister reg,
- GpuRegister base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- // Must not use AT as `reg`, so as not to overwrite the value being stored
- // with the adjusted `base`.
- CHECK_NE(reg, AT);
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kStoreDoubleword));
-
- switch (type) {
- case kStoreByte:
- Sb(reg, base, offset);
- break;
- case kStoreHalfword:
- Sh(reg, base, offset);
- break;
- case kStoreWord:
- CHECK_ALIGNED(offset, kMips64WordSize);
- Sw(reg, base, offset);
- break;
- case kStoreDoubleword:
- if (!IsAligned<kMips64DoublewordSize>(offset)) {
- CHECK_ALIGNED(offset, kMips64WordSize);
- Sw(reg, base, offset);
- null_checker();
- Dsrl32(TMP2, reg, 0);
- Sw(TMP2, base, offset + kMips64WordSize);
- } else {
- Sd(reg, base, offset);
- null_checker();
- }
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- if (type != kStoreDoubleword) {
- null_checker();
- }
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreFpuToOffset(StoreOperandType type,
- FpuRegister reg,
- GpuRegister base,
- int32_t offset,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- int element_size_shift = -1;
- if (type != kStoreQuadword) {
- AdjustBaseAndOffset(base, offset, /* is_doubleword= */ (type == kStoreDoubleword));
- } else {
- AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
- }
-
- switch (type) {
- case kStoreWord:
- CHECK_ALIGNED(offset, kMips64WordSize);
- Swc1(reg, base, offset);
- null_checker();
- break;
- case kStoreDoubleword:
- if (!IsAligned<kMips64DoublewordSize>(offset)) {
- CHECK_ALIGNED(offset, kMips64WordSize);
- Mfhc1(TMP2, reg);
- Swc1(reg, base, offset);
- null_checker();
- Sw(TMP2, base, offset + kMips64WordSize);
- } else {
- Sdc1(reg, base, offset);
- null_checker();
- }
- break;
- case kStoreQuadword:
- switch (element_size_shift) {
- case TIMES_1: StB(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_2: StH(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_4: StW(static_cast<VectorRegister>(reg), base, offset); break;
- case TIMES_8: StD(static_cast<VectorRegister>(reg), base, offset); break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- null_checker();
- break;
- default:
- LOG(FATAL) << "UNREACHABLE";
- }
- }
-
- void LoadFromOffset(LoadOperandType type, GpuRegister reg, GpuRegister base, int32_t offset);
- void LoadFpuFromOffset(LoadOperandType type, FpuRegister reg, GpuRegister base, int32_t offset);
- void StoreToOffset(StoreOperandType type, GpuRegister reg, GpuRegister base, int32_t offset);
- void StoreFpuToOffset(StoreOperandType type, FpuRegister reg, GpuRegister base, int32_t offset);
-
- // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
- void Emit(uint32_t value);
-
- //
- // Overridden common assembler high-level functionality.
- //
-
- // Emit code that will create an activation on the stack.
- void BuildFrame(size_t frame_size,
- ManagedRegister method_reg,
- ArrayRef<const ManagedRegister> callee_save_regs,
- const ManagedRegisterEntrySpills& entry_spills) override;
-
- // Emit code that will remove an activation from the stack.
- void RemoveFrame(size_t frame_size,
- ArrayRef<const ManagedRegister> callee_save_regs,
- bool may_suspend) override;
-
- void IncreaseFrameSize(size_t adjust) override;
- void DecreaseFrameSize(size_t adjust) override;
-
- // Store routines.
- void Store(FrameOffset offs, ManagedRegister msrc, size_t size) override;
- void StoreRef(FrameOffset dest, ManagedRegister msrc) override;
- void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) override;
-
- void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) override;
-
- void StoreStackOffsetToThread(ThreadOffset64 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) override;
-
- void StoreStackPointerToThread(ThreadOffset64 thr_offs) override;
-
- void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off,
- ManagedRegister mscratch) override;
-
- // Load routines.
- void Load(ManagedRegister mdest, FrameOffset src, size_t size) override;
-
- void LoadFromThread(ManagedRegister mdest, ThreadOffset64 src, size_t size) override;
-
- void LoadRef(ManagedRegister dest, FrameOffset src) override;
-
- void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
- bool unpoison_reference) override;
-
- void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) override;
-
- void LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset64 offs) override;
-
- // Copying routines.
- void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) override;
-
- void CopyRawPtrFromThread(FrameOffset fr_offs,
- ThreadOffset64 thr_offs,
- ManagedRegister mscratch) override;
-
- void CopyRawPtrToThread(ThreadOffset64 thr_offs,
- FrameOffset fr_offs,
- ManagedRegister mscratch) override;
-
- void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) override;
-
- void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) override;
-
- void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
- ManagedRegister mscratch, size_t size) override;
-
- void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch,
- size_t size) override;
-
- void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
- ManagedRegister mscratch, size_t size) override;
-
- void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
- ManagedRegister mscratch, size_t size) override;
-
- void MemoryBarrier(ManagedRegister) override;
-
- // Sign extension.
- void SignExtend(ManagedRegister mreg, size_t size) override;
-
- // Zero extension.
- void ZeroExtend(ManagedRegister mreg, size_t size) override;
-
- // Exploit fast access in managed code to Thread::Current().
- void GetCurrentThread(ManagedRegister tr) override;
- void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) override;
-
- // Set up out_reg to hold a Object** into the handle scope, or to be null if the
- // value is null and null_allowed. in_reg holds a possibly stale reference
- // that can be used to avoid loading the handle scope entry to see if the value is
- // null.
- void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
- ManagedRegister in_reg, bool null_allowed) override;
-
- // Set up out_off to hold a Object** into the handle scope, or to be null if the
- // value is null and null_allowed.
- void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister
- mscratch, bool null_allowed) override;
-
- // src holds a handle scope entry (Object**) load this into dst.
- void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) override;
-
- // Heap::VerifyObject on src. In some cases (such as a reference to this) we
- // know that src may not be null.
- void VerifyObject(ManagedRegister src, bool could_be_null) override;
- void VerifyObject(FrameOffset src, bool could_be_null) override;
-
- // Jump to address held at [base+offset] (used for tail calls).
- void Jump(ManagedRegister base, Offset offset, ManagedRegister scratch) override;
-
- // Call to address held at [base+offset].
- void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) override;
- void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) override;
- void CallFromThread(ThreadOffset64 offset, ManagedRegister mscratch) override;
-
- // Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) override;
-
- // Emit slow paths queued during assembly and promote short branches to long if needed.
- void FinalizeCode() override;
-
- // Emit branches and finalize all instructions.
- void FinalizeInstructions(const MemoryRegion& region) override;
-
- // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS64,
- // must be used instead of Mips64Label::GetPosition()).
- uint32_t GetLabelLocation(const Mips64Label* label) const;
-
- // Get the final position of a label after local fixup based on the old position
- // recorded before FinalizeCode().
- uint32_t GetAdjustedPosition(uint32_t old_position);
-
- // Note that PC-relative literal loads are handled as pseudo branches because they need very
- // similar relocation and may similarly expand in size to accomodate for larger offsets relative
- // to PC.
- enum BranchCondition {
- kCondLT,
- kCondGE,
- kCondLE,
- kCondGT,
- kCondLTZ,
- kCondGEZ,
- kCondLEZ,
- kCondGTZ,
- kCondEQ,
- kCondNE,
- kCondEQZ,
- kCondNEZ,
- kCondLTU,
- kCondGEU,
- kCondF, // Floating-point predicate false.
- kCondT, // Floating-point predicate true.
- kUncond,
- };
- friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs);
-
- private:
- class Branch {
- public:
- enum Type {
- // R6 short branches (can be promoted to long).
- kUncondBranch,
- kCondBranch,
- kCall,
- // R6 short branches (can't be promoted to long), forbidden/delay slots filled manually.
- kBareUncondBranch,
- kBareCondBranch,
- kBareCall,
- // R2 short branches (can't be promoted to long), delay slots filled manually.
- kR2BareCondBranch,
- // Near label.
- kLabel,
- // Near literals.
- kLiteral,
- kLiteralUnsigned,
- kLiteralLong,
- // Long branches.
- kLongUncondBranch,
- kLongCondBranch,
- kLongCall,
- // Far label.
- kFarLabel,
- // Far literals.
- kFarLiteral,
- kFarLiteralUnsigned,
- kFarLiteralLong,
- };
-
- // Bit sizes of offsets defined as enums to minimize chance of typos.
- enum OffsetBits {
- kOffset16 = 16,
- kOffset18 = 18,
- kOffset21 = 21,
- kOffset23 = 23,
- kOffset28 = 28,
- kOffset32 = 32,
- };
-
- static constexpr uint32_t kUnresolved = 0xffffffff; // Unresolved target_
- static constexpr int32_t kMaxBranchLength = 32;
- static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t);
-
- struct BranchInfo {
- // Branch length as a number of 4-byte-long instructions.
- uint32_t length;
- // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's
- // PC-relative offset (or its most significant 16-bit half, which goes first).
- uint32_t instr_offset;
- // Different MIPS instructions with PC-relative offsets apply said offsets to slightly
- // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte
- // instructions) from the instruction containing the offset.
- uint32_t pc_org;
- // How large (in bits) a PC-relative offset can be for a given type of branch (kCondBranch
- // and kBareCondBranch are an exception: use kOffset23 for beqzc/bnezc).
- OffsetBits offset_size;
- // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift
- // count.
- int offset_shift;
- };
- static const BranchInfo branch_info_[/* Type */];
-
- // Unconditional branch or call.
- Branch(uint32_t location, uint32_t target, bool is_call, bool is_bare);
- // Conditional branch.
- Branch(bool is_r6,
- uint32_t location,
- uint32_t target,
- BranchCondition condition,
- GpuRegister lhs_reg,
- GpuRegister rhs_reg,
- bool is_bare);
- // Label address (in literal area) or literal.
- Branch(uint32_t location, GpuRegister dest_reg, Type label_or_literal_type);
-
- // Some conditional branches with lhs = rhs are effectively NOPs, while some
- // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs.
- // So, we need a way to identify such branches in order to emit no instructions for them
- // or change them to unconditional.
- static bool IsNop(BranchCondition condition, GpuRegister lhs, GpuRegister rhs);
- static bool IsUncond(BranchCondition condition, GpuRegister lhs, GpuRegister rhs);
-
- static BranchCondition OppositeCondition(BranchCondition cond);
-
- Type GetType() const;
- BranchCondition GetCondition() const;
- GpuRegister GetLeftRegister() const;
- GpuRegister GetRightRegister() const;
- uint32_t GetTarget() const;
- uint32_t GetLocation() const;
- uint32_t GetOldLocation() const;
- uint32_t GetLength() const;
- uint32_t GetOldLength() const;
- uint32_t GetSize() const;
- uint32_t GetOldSize() const;
- uint32_t GetEndLocation() const;
- uint32_t GetOldEndLocation() const;
- bool IsBare() const;
- bool IsLong() const;
- bool IsResolved() const;
-
- // Returns the bit size of the signed offset that the branch instruction can handle.
- OffsetBits GetOffsetSize() const;
-
- // Calculates the distance between two byte locations in the assembler buffer and
- // returns the number of bits needed to represent the distance as a signed integer.
- //
- // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc),
- // and 26 (bc) bits, which are additionally shifted left 2 positions at run time.
- //
- // Composite branches (made of several instructions) with longer reach have 32-bit
- // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first).
- // The composite branches cover the range of PC + ~+/-2GB. The range is not end-to-end,
- // however. Consider the following implementation of a long unconditional branch, for
- // example:
- //
- // auipc at, offset_31_16 // at = pc + sign_extend(offset_31_16) << 16
- // jic at, offset_15_0 // pc = at + sign_extend(offset_15_0)
- //
- // Both of the above instructions take 16-bit signed offsets as immediate operands.
- // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000
- // due to sign extension. This must be compensated for by incrementing offset_31_16
- // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is
- // 0x7FFF, adding 1 will overflow the positive offset into the negative range.
- // Therefore, the long branch range is something like from PC - 0x80000000 to
- // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side.
- //
- // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special
- // case with the addiu instruction and a 16 bit offset.
- static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target);
-
- // Resolve a branch when the target is known.
- void Resolve(uint32_t target);
-
- // Relocate a branch by a given delta if needed due to expansion of this or another
- // branch at a given location by this delta (just changes location_ and target_).
- void Relocate(uint32_t expand_location, uint32_t delta);
-
- // If the branch is short, changes its type to long.
- void PromoteToLong();
-
- // If necessary, updates the type by promoting a short branch to a long branch
- // based on the branch location and target. Returns the amount (in bytes) by
- // which the branch size has increased.
- // max_short_distance caps the maximum distance between location_ and target_
- // that is allowed for short branches. This is for debugging/testing purposes.
- // max_short_distance = 0 forces all short branches to become long.
- // Use the implicit default argument when not debugging/testing.
- uint32_t PromoteIfNeeded(uint32_t max_short_distance = std::numeric_limits<uint32_t>::max());
-
- // Returns the location of the instruction(s) containing the offset.
- uint32_t GetOffsetLocation() const;
-
- // Calculates and returns the offset ready for encoding in the branch instruction(s).
- uint32_t GetOffset() const;
-
- private:
- // Completes branch construction by determining and recording its type.
- void InitializeType(Type initial_type, bool is_r6);
- // Helper for the above.
- void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type);
-
- uint32_t old_location_; // Offset into assembler buffer in bytes.
- uint32_t location_; // Offset into assembler buffer in bytes.
- uint32_t target_; // Offset into assembler buffer in bytes.
-
- GpuRegister lhs_reg_; // Left-hand side register in conditional branches or
- // destination register in literals.
- GpuRegister rhs_reg_; // Right-hand side register in conditional branches.
- BranchCondition condition_; // Condition for conditional branches.
-
- Type type_; // Current type of the branch.
- Type old_type_; // Initial type of the branch.
- };
- friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs);
- friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs);
-
- void EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, int shamt, int funct);
- void EmitRsd(int opcode, GpuRegister rs, GpuRegister rd, int shamt, int funct);
- void EmitRtd(int opcode, GpuRegister rt, GpuRegister rd, int shamt, int funct);
- void EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm);
- void EmitI21(int opcode, GpuRegister rs, uint32_t imm21);
- void EmitI26(int opcode, uint32_t imm26);
- void EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd, int funct);
- void EmitFI(int opcode, int fmt, FpuRegister rt, uint16_t imm);
- void EmitBcondR6(BranchCondition cond, GpuRegister rs, GpuRegister rt, uint32_t imm16_21);
- void EmitBcondR2(BranchCondition cond, GpuRegister rs, GpuRegister rt, uint16_t imm16);
- void EmitMsa3R(int operation,
- int df,
- VectorRegister wt,
- VectorRegister ws,
- VectorRegister wd,
- int minor_opcode);
- void EmitMsaBIT(int operation, int df_m, VectorRegister ws, VectorRegister wd, int minor_opcode);
- void EmitMsaELM(int operation, int df_n, VectorRegister ws, VectorRegister wd, int minor_opcode);
- void EmitMsaMI10(int s10, GpuRegister rs, VectorRegister wd, int minor_opcode, int df);
- void EmitMsaI10(int operation, int df, int i10, VectorRegister wd, int minor_opcode);
- void EmitMsa2R(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode);
- void EmitMsa2RF(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode);
-
- void Buncond(Mips64Label* label, bool is_bare);
- void Bcond(Mips64Label* label,
- bool is_r6,
- bool is_bare,
- BranchCondition condition,
- GpuRegister lhs,
- GpuRegister rhs = ZERO);
- void Call(Mips64Label* label, bool is_bare);
- void FinalizeLabeledBranch(Mips64Label* label);
-
- Branch* GetBranch(uint32_t branch_id);
- const Branch* GetBranch(uint32_t branch_id) const;
-
- void EmitLiterals();
- void ReserveJumpTableSpace();
- void EmitJumpTables();
- void PromoteBranches();
- void EmitBranch(Branch* branch);
- void EmitBranches();
- void PatchCFI();
-
- // Emits exception block.
- void EmitExceptionPoll(Mips64ExceptionSlowPath* exception);
-
- bool HasMsa() const {
- return has_msa_;
- }
-
- // List of exception blocks to generate at the end of the code cache.
- std::vector<Mips64ExceptionSlowPath> exception_blocks_;
-
- std::vector<Branch> branches_;
-
- // Whether appending instructions at the end of the buffer or overwriting the existing ones.
- bool overwriting_;
- // The current overwrite location.
- uint32_t overwrite_location_;
-
- // Use std::deque<> for literal labels to allow insertions at the end
- // without invalidating pointers and references to existing elements.
- ArenaDeque<Literal> literals_;
- ArenaDeque<Literal> long_literals_; // 64-bit literals separated for alignment reasons.
-
- // Jump table list.
- ArenaDeque<JumpTable> jump_tables_;
-
- // Data for AdjustedPosition(), see the description there.
- uint32_t last_position_adjustment_;
- uint32_t last_old_position_;
- uint32_t last_branch_id_;
-
- const bool has_msa_;
-
- DISALLOW_COPY_AND_ASSIGN(Mips64Assembler);
-};
-
-} // namespace mips64
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
deleted file mode 100644
index 2f7b223..0000000
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ /dev/null
@@ -1,3788 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "assembler_mips64.h"
-
-#include <inttypes.h>
-#include <map>
-#include <random>
-
-#include "base/bit_utils.h"
-#include "base/stl_util.h"
-#include "utils/assembler_test.h"
-
-#define __ GetAssembler()->
-
-namespace art {
-
-struct MIPS64CpuRegisterCompare {
- bool operator()(const mips64::GpuRegister& a, const mips64::GpuRegister& b) const {
- return a < b;
- }
-};
-
-class AssemblerMIPS64Test : public AssemblerTest<mips64::Mips64Assembler,
- mips64::Mips64Label,
- mips64::GpuRegister,
- mips64::FpuRegister,
- uint32_t,
- mips64::VectorRegister> {
- public:
- using Base = AssemblerTest<mips64::Mips64Assembler,
- mips64::Mips64Label,
- mips64::GpuRegister,
- mips64::FpuRegister,
- uint32_t,
- mips64::VectorRegister>;
-
- // These tests were taking too long, so we hide the DriverStr() from AssemblerTest<>
- // and reimplement it without the verification against `assembly_string`. b/73903608
- void DriverStr(const std::string& assembly_string ATTRIBUTE_UNUSED,
- const std::string& test_name ATTRIBUTE_UNUSED) {
- GetAssembler()->FinalizeCode();
- std::vector<uint8_t> data(GetAssembler()->CodeSize());
- MemoryRegion code(data.data(), data.size());
- GetAssembler()->FinalizeInstructions(code);
- }
-
- AssemblerMIPS64Test()
- : instruction_set_features_(Mips64InstructionSetFeatures::FromVariant("default", nullptr)) {}
-
- protected:
- // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
- std::string GetArchitectureString() override {
- return "mips64";
- }
-
- std::string GetAssemblerCmdName() override {
- // We assemble and link for MIPS64R6. See GetAssemblerParameters() for details.
- return "gcc";
- }
-
- std::string GetAssemblerParameters() override {
- // We assemble and link for MIPS64R6. The reason is that object files produced for MIPS64R6
- // (and MIPS32R6) with the GNU assembler don't have correct final offsets in PC-relative
- // branches in the .text section and so they require a relocation pass (there's a relocation
- // section, .rela.text, that has the needed info to fix up the branches).
- return " -march=mips64r6 -mmsa -Wa,--no-warn -Wl,-Ttext=0 -Wl,-e0 -nostdlib";
- }
-
- void Pad(std::vector<uint8_t>& data) override {
- // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple
- // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't
- // pad, so, in order for two assembler outputs to match, we need to match the padding as well.
- // NOP is encoded as four zero bytes on MIPS.
- size_t pad_size = RoundUp(data.size(), 16u) - data.size();
- data.insert(data.end(), pad_size, 0);
- }
-
- std::string GetDisassembleParameters() override {
- return " -D -bbinary -mmips:isa64r6";
- }
-
- mips64::Mips64Assembler* CreateAssembler(ArenaAllocator* allocator) override {
- return new (allocator) mips64::Mips64Assembler(allocator, instruction_set_features_.get());
- }
-
- void SetUpHelpers() override {
- if (registers_.size() == 0) {
- registers_.push_back(new mips64::GpuRegister(mips64::ZERO));
- registers_.push_back(new mips64::GpuRegister(mips64::AT));
- registers_.push_back(new mips64::GpuRegister(mips64::V0));
- registers_.push_back(new mips64::GpuRegister(mips64::V1));
- registers_.push_back(new mips64::GpuRegister(mips64::A0));
- registers_.push_back(new mips64::GpuRegister(mips64::A1));
- registers_.push_back(new mips64::GpuRegister(mips64::A2));
- registers_.push_back(new mips64::GpuRegister(mips64::A3));
- registers_.push_back(new mips64::GpuRegister(mips64::A4));
- registers_.push_back(new mips64::GpuRegister(mips64::A5));
- registers_.push_back(new mips64::GpuRegister(mips64::A6));
- registers_.push_back(new mips64::GpuRegister(mips64::A7));
- registers_.push_back(new mips64::GpuRegister(mips64::T0));
- registers_.push_back(new mips64::GpuRegister(mips64::T1));
- registers_.push_back(new mips64::GpuRegister(mips64::T2));
- registers_.push_back(new mips64::GpuRegister(mips64::T3));
- registers_.push_back(new mips64::GpuRegister(mips64::S0));
- registers_.push_back(new mips64::GpuRegister(mips64::S1));
- registers_.push_back(new mips64::GpuRegister(mips64::S2));
- registers_.push_back(new mips64::GpuRegister(mips64::S3));
- registers_.push_back(new mips64::GpuRegister(mips64::S4));
- registers_.push_back(new mips64::GpuRegister(mips64::S5));
- registers_.push_back(new mips64::GpuRegister(mips64::S6));
- registers_.push_back(new mips64::GpuRegister(mips64::S7));
- registers_.push_back(new mips64::GpuRegister(mips64::T8));
- registers_.push_back(new mips64::GpuRegister(mips64::T9));
- registers_.push_back(new mips64::GpuRegister(mips64::K0));
- registers_.push_back(new mips64::GpuRegister(mips64::K1));
- registers_.push_back(new mips64::GpuRegister(mips64::GP));
- registers_.push_back(new mips64::GpuRegister(mips64::SP));
- registers_.push_back(new mips64::GpuRegister(mips64::S8));
- registers_.push_back(new mips64::GpuRegister(mips64::RA));
-
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::ZERO), "zero");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::AT), "at");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::V0), "v0");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::V1), "v1");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A0), "a0");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A1), "a1");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A2), "a2");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A3), "a3");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A4), "a4");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A5), "a5");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A6), "a6");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::A7), "a7");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T0), "t0");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T1), "t1");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T2), "t2");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T3), "t3");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S0), "s0");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S1), "s1");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S2), "s2");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S3), "s3");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S4), "s4");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S5), "s5");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S6), "s6");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S7), "s7");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T8), "t8");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::T9), "t9");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::K0), "k0");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::K1), "k1");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::GP), "gp");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::SP), "sp");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::S8), "s8");
- secondary_register_names_.emplace(mips64::GpuRegister(mips64::RA), "ra");
-
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F0));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F1));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F2));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F3));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F4));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F5));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F6));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F7));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F8));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F9));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F10));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F11));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F12));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F13));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F14));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F15));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F16));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F17));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F18));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F19));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F20));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F21));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F22));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F23));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F24));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F25));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F26));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F27));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F28));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F29));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F30));
- fp_registers_.push_back(new mips64::FpuRegister(mips64::F31));
-
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W0));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W1));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W2));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W3));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W4));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W5));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W6));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W7));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W8));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W9));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W10));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W11));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W12));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W13));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W14));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W15));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W16));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W17));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W18));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W19));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W20));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W21));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W22));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W23));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W24));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W25));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W26));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W27));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W28));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W29));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W30));
- vec_registers_.push_back(new mips64::VectorRegister(mips64::W31));
- }
- }
-
- void TearDown() override {
- AssemblerTest::TearDown();
- STLDeleteElements(®isters_);
- STLDeleteElements(&fp_registers_);
- STLDeleteElements(&vec_registers_);
- }
-
- std::vector<mips64::Mips64Label> GetAddresses() override {
- UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
- UNREACHABLE();
- }
-
- std::vector<mips64::GpuRegister*> GetRegisters() override {
- return registers_;
- }
-
- std::vector<mips64::FpuRegister*> GetFPRegisters() override {
- return fp_registers_;
- }
-
- std::vector<mips64::VectorRegister*> GetVectorRegisters() override {
- return vec_registers_;
- }
-
- uint32_t CreateImmediate(int64_t imm_value) override {
- return imm_value;
- }
-
- std::string GetSecondaryRegisterName(const mips64::GpuRegister& reg) override {
- CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
- return secondary_register_names_[reg];
- }
-
- std::string RepeatInsn(size_t count, const std::string& insn) {
- std::string result;
- for (; count != 0u; --count) {
- result += insn;
- }
- return result;
- }
-
- void BranchHelper(void (mips64::Mips64Assembler::*f)(mips64::Mips64Label*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- mips64::Mips64Label label1, label2;
- (Base::GetAssembler()->*f)(&label1, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label1);
- (Base::GetAssembler()->*f)(&label2, is_bare);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label2);
- (Base::GetAssembler()->*f)(&label1, is_bare);
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " 1f\n" +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- instr_name + " 2f\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- "2:\n" +
- instr_name + " 1b\n" +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondOneRegHelper(void (mips64::Mips64Assembler::*f)(mips64::GpuRegister,
- mips64::Mips64Label*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- mips64::Mips64Label label;
- (Base::GetAssembler()->*f)(mips64::A0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- (Base::GetAssembler()->*f)(mips64::A1, &label, is_bare);
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a1, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchCondTwoRegsHelper(void (mips64::Mips64Assembler::*f)(mips64::GpuRegister,
- mips64::GpuRegister,
- mips64::Mips64Label*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- mips64::Mips64Label label;
- (Base::GetAssembler()->*f)(mips64::A0, mips64::A1, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- (Base::GetAssembler()->*f)(mips64::A2, mips64::A3, &label, is_bare);
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $a0, $a1, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $a2, $a3, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- void BranchFpuCondHelper(void (mips64::Mips64Assembler::*f)(mips64::FpuRegister,
- mips64::Mips64Label*,
- bool),
- const std::string& instr_name,
- bool is_bare = false) {
- mips64::Mips64Label label;
- (Base::GetAssembler()->*f)(mips64::F0, &label, is_bare);
- constexpr size_t kAdduCount1 = 63;
- for (size_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
- constexpr size_t kAdduCount2 = 64;
- for (size_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- (Base::GetAssembler()->*f)(mips64::F31, &label, is_bare);
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
-
- std::string expected =
- ".set noreorder\n" +
- instr_name + " $f0, 1f\n" +
- (is_bare ? "" : "nop\n") +
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
- "1:\n" +
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
- instr_name + " $f31, 1b\n" +
- (is_bare ? "" : "nop\n") +
- "addu $zero, $zero, $zero\n";
- DriverStr(expected, instr_name);
- }
-
- private:
- std::vector<mips64::GpuRegister*> registers_;
- std::map<mips64::GpuRegister, std::string, MIPS64CpuRegisterCompare> secondary_register_names_;
-
- std::vector<mips64::FpuRegister*> fp_registers_;
- std::vector<mips64::VectorRegister*> vec_registers_;
-
- std::unique_ptr<const Mips64InstructionSetFeatures> instruction_set_features_;
-};
-
-TEST_F(AssemblerMIPS64Test, Toolchain) {
- // This test is disabled as `gcc` (used as MIPS64 assembler, see
- // `AssemblerMIPS64Test.GetAssemblerCmdName`) is being removed from Android
- // (see b/147336214 and b/147240075).
- TEST_DISABLED();
- EXPECT_TRUE(CheckTools());
-}
-
-///////////////////
-// FP Operations //
-///////////////////
-
-TEST_F(AssemblerMIPS64Test, AddS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::AddS, "add.s ${reg1}, ${reg2}, ${reg3}"), "add.s");
-}
-
-TEST_F(AssemblerMIPS64Test, AddD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::AddD, "add.d ${reg1}, ${reg2}, ${reg3}"), "add.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SubS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SubS, "sub.s ${reg1}, ${reg2}, ${reg3}"), "sub.s");
-}
-
-TEST_F(AssemblerMIPS64Test, SubD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SubD, "sub.d ${reg1}, ${reg2}, ${reg3}"), "sub.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MulS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MulS, "mul.s ${reg1}, ${reg2}, ${reg3}"), "mul.s");
-}
-
-TEST_F(AssemblerMIPS64Test, MulD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MulD, "mul.d ${reg1}, ${reg2}, ${reg3}"), "mul.d");
-}
-
-TEST_F(AssemblerMIPS64Test, DivS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::DivS, "div.s ${reg1}, ${reg2}, ${reg3}"), "div.s");
-}
-
-TEST_F(AssemblerMIPS64Test, DivD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::DivD, "div.d ${reg1}, ${reg2}, ${reg3}"), "div.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SqrtS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::SqrtS, "sqrt.s ${reg1}, ${reg2}"), "sqrt.s");
-}
-
-TEST_F(AssemblerMIPS64Test, SqrtD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::SqrtD, "sqrt.d ${reg1}, ${reg2}"), "sqrt.d");
-}
-
-TEST_F(AssemblerMIPS64Test, AbsS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::AbsS, "abs.s ${reg1}, ${reg2}"), "abs.s");
-}
-
-TEST_F(AssemblerMIPS64Test, AbsD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::AbsD, "abs.d ${reg1}, ${reg2}"), "abs.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MovS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::MovS, "mov.s ${reg1}, ${reg2}"), "mov.s");
-}
-
-TEST_F(AssemblerMIPS64Test, MovD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::MovD, "mov.d ${reg1}, ${reg2}"), "mov.d");
-}
-
-TEST_F(AssemblerMIPS64Test, NegS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::NegS, "neg.s ${reg1}, ${reg2}"), "neg.s");
-}
-
-TEST_F(AssemblerMIPS64Test, NegD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::NegD, "neg.d ${reg1}, ${reg2}"), "neg.d");
-}
-
-TEST_F(AssemblerMIPS64Test, RoundLS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RoundLS, "round.l.s ${reg1}, ${reg2}"), "round.l.s");
-}
-
-TEST_F(AssemblerMIPS64Test, RoundLD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RoundLD, "round.l.d ${reg1}, ${reg2}"), "round.l.d");
-}
-
-TEST_F(AssemblerMIPS64Test, RoundWS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RoundWS, "round.w.s ${reg1}, ${reg2}"), "round.w.s");
-}
-
-TEST_F(AssemblerMIPS64Test, RoundWD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RoundWD, "round.w.d ${reg1}, ${reg2}"), "round.w.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CeilLS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::CeilLS, "ceil.l.s ${reg1}, ${reg2}"), "ceil.l.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CeilLD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::CeilLD, "ceil.l.d ${reg1}, ${reg2}"), "ceil.l.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CeilWS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::CeilWS, "ceil.w.s ${reg1}, ${reg2}"), "ceil.w.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CeilWD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::CeilWD, "ceil.w.d ${reg1}, ${reg2}"), "ceil.w.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FloorLS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::FloorLS, "floor.l.s ${reg1}, ${reg2}"), "floor.l.s");
-}
-
-TEST_F(AssemblerMIPS64Test, FloorLD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::FloorLD, "floor.l.d ${reg1}, ${reg2}"), "floor.l.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FloorWS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::FloorWS, "floor.w.s ${reg1}, ${reg2}"), "floor.w.s");
-}
-
-TEST_F(AssemblerMIPS64Test, FloorWD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::FloorWD, "floor.w.d ${reg1}, ${reg2}"), "floor.w.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SelS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SelS, "sel.s ${reg1}, ${reg2}, ${reg3}"), "sel.s");
-}
-
-TEST_F(AssemblerMIPS64Test, SelD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SelD, "sel.d ${reg1}, ${reg2}, ${reg3}"), "sel.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SeleqzS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SeleqzS, "seleqz.s ${reg1}, ${reg2}, ${reg3}"),
- "seleqz.s");
-}
-
-TEST_F(AssemblerMIPS64Test, SeleqzD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SeleqzD, "seleqz.d ${reg1}, ${reg2}, ${reg3}"),
- "seleqz.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SelnezS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SelnezS, "selnez.s ${reg1}, ${reg2}, ${reg3}"),
- "selnez.s");
-}
-
-TEST_F(AssemblerMIPS64Test, SelnezD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::SelnezD, "selnez.d ${reg1}, ${reg2}, ${reg3}"),
- "selnez.d");
-}
-
-TEST_F(AssemblerMIPS64Test, RintS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RintS, "rint.s ${reg1}, ${reg2}"), "rint.s");
-}
-
-TEST_F(AssemblerMIPS64Test, RintD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::RintD, "rint.d ${reg1}, ${reg2}"), "rint.d");
-}
-
-TEST_F(AssemblerMIPS64Test, ClassS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::ClassS, "class.s ${reg1}, ${reg2}"), "class.s");
-}
-
-TEST_F(AssemblerMIPS64Test, ClassD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::ClassD, "class.d ${reg1}, ${reg2}"), "class.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MinS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MinS, "min.s ${reg1}, ${reg2}, ${reg3}"), "min.s");
-}
-
-TEST_F(AssemblerMIPS64Test, MinD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MinD, "min.d ${reg1}, ${reg2}, ${reg3}"), "min.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MaxS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MaxS, "max.s ${reg1}, ${reg2}, ${reg3}"), "max.s");
-}
-
-TEST_F(AssemblerMIPS64Test, MaxD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::MaxD, "max.d ${reg1}, ${reg2}, ${reg3}"), "max.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUnS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUnS, "cmp.un.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.un.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpEqS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpEqS, "cmp.eq.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.eq.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUeqS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUeqS, "cmp.ueq.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ueq.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpLtS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpLtS, "cmp.lt.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.lt.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUltS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUltS, "cmp.ult.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ult.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpLeS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpLeS, "cmp.le.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.le.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUleS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUleS, "cmp.ule.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ule.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpOrS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpOrS, "cmp.or.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.or.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUneS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUneS, "cmp.une.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.une.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpNeS) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpNeS, "cmp.ne.s ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ne.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUnD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUnD, "cmp.un.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.un.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpEqD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpEqD, "cmp.eq.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.eq.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUeqD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUeqD, "cmp.ueq.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ueq.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpLtD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpLtD, "cmp.lt.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.lt.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUltD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUltD, "cmp.ult.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ult.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpLeD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpLeD, "cmp.le.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.le.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUleD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUleD, "cmp.ule.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ule.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpOrD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpOrD, "cmp.or.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.or.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpUneD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpUneD, "cmp.une.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.une.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CmpNeD) {
- DriverStr(RepeatFFF(&mips64::Mips64Assembler::CmpNeD, "cmp.ne.d ${reg1}, ${reg2}, ${reg3}"),
- "cmp.ne.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtDL) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtdl, "cvt.d.l ${reg1}, ${reg2}"), "cvt.d.l");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtDS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtds, "cvt.d.s ${reg1}, ${reg2}"), "cvt.d.s");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtDW) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtdw, "cvt.d.w ${reg1}, ${reg2}"), "cvt.d.w");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtSL) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtsl, "cvt.s.l ${reg1}, ${reg2}"), "cvt.s.l");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtSD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtsd, "cvt.s.d ${reg1}, ${reg2}"), "cvt.s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, CvtSW) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::Cvtsw, "cvt.s.w ${reg1}, ${reg2}"), "cvt.s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, TruncWS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::TruncWS, "trunc.w.s ${reg1}, ${reg2}"), "trunc.w.s");
-}
-
-TEST_F(AssemblerMIPS64Test, TruncWD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::TruncWD, "trunc.w.d ${reg1}, ${reg2}"), "trunc.w.d");
-}
-
-TEST_F(AssemblerMIPS64Test, TruncLS) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::TruncLS, "trunc.l.s ${reg1}, ${reg2}"), "trunc.l.s");
-}
-
-TEST_F(AssemblerMIPS64Test, TruncLD) {
- DriverStr(RepeatFF(&mips64::Mips64Assembler::TruncLD, "trunc.l.d ${reg1}, ${reg2}"), "trunc.l.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Mfc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Mfc1, "mfc1 ${reg1}, ${reg2}"), "Mfc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Mfhc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Mfhc1, "mfhc1 ${reg1}, ${reg2}"), "Mfhc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Mtc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Mtc1, "mtc1 ${reg1}, ${reg2}"), "Mtc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Mthc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Mthc1, "mthc1 ${reg1}, ${reg2}"), "Mthc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Dmfc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Dmfc1, "dmfc1 ${reg1}, ${reg2}"), "Dmfc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Dmtc1) {
- DriverStr(RepeatRF(&mips64::Mips64Assembler::Dmtc1, "dmtc1 ${reg1}, ${reg2}"), "Dmtc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Lwc1) {
- DriverStr(RepeatFRIb(&mips64::Mips64Assembler::Lwc1, -16, "lwc1 ${reg1}, {imm}(${reg2})"),
- "lwc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Ldc1) {
- DriverStr(RepeatFRIb(&mips64::Mips64Assembler::Ldc1, -16, "ldc1 ${reg1}, {imm}(${reg2})"),
- "ldc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Swc1) {
- DriverStr(RepeatFRIb(&mips64::Mips64Assembler::Swc1, -16, "swc1 ${reg1}, {imm}(${reg2})"),
- "swc1");
-}
-
-TEST_F(AssemblerMIPS64Test, Sdc1) {
- DriverStr(RepeatFRIb(&mips64::Mips64Assembler::Sdc1, -16, "sdc1 ${reg1}, {imm}(${reg2})"),
- "sdc1");
-}
-
-//////////////
-// BRANCHES //
-//////////////
-
-TEST_F(AssemblerMIPS64Test, Jalr) {
- DriverStr(".set noreorder\n" +
- RepeatRRNoDupes(&mips64::Mips64Assembler::Jalr, "jalr ${reg1}, ${reg2}"), "jalr");
-}
-
-TEST_F(AssemblerMIPS64Test, Bc) {
- BranchHelper(&mips64::Mips64Assembler::Bc, "Bc");
-}
-
-TEST_F(AssemblerMIPS64Test, Balc) {
- BranchHelper(&mips64::Mips64Assembler::Balc, "Balc");
-}
-
-TEST_F(AssemblerMIPS64Test, Beqzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Beqzc, "Beqzc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bnezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bnezc, "Bnezc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bltzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bltzc, "Bltzc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bgezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgezc, "Bgezc");
-}
-
-TEST_F(AssemblerMIPS64Test, Blezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Blezc, "Blezc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bgtzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgtzc, "Bgtzc");
-}
-
-TEST_F(AssemblerMIPS64Test, Beqc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Beqc, "Beqc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bnec) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bnec, "Bnec");
-}
-
-TEST_F(AssemblerMIPS64Test, Bltc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bltc, "Bltc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bgec) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bgec, "Bgec");
-}
-
-TEST_F(AssemblerMIPS64Test, Bltuc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bltuc, "Bltuc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bgeuc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bgeuc, "Bgeuc");
-}
-
-TEST_F(AssemblerMIPS64Test, Bc1eqz) {
- BranchFpuCondHelper(&mips64::Mips64Assembler::Bc1eqz, "Bc1eqz");
-}
-
-TEST_F(AssemblerMIPS64Test, Bc1nez) {
- BranchFpuCondHelper(&mips64::Mips64Assembler::Bc1nez, "Bc1nez");
-}
-
-TEST_F(AssemblerMIPS64Test, BareBc) {
- BranchHelper(&mips64::Mips64Assembler::Bc, "Bc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBalc) {
- BranchHelper(&mips64::Mips64Assembler::Balc, "Balc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBeqzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Beqzc, "Beqzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBnezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bnezc, "Bnezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBltzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bltzc, "Bltzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgezc, "Bgezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBlezc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Blezc, "Blezc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgtzc) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgtzc, "Bgtzc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBeqc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Beqc, "Beqc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBnec) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bnec, "Bnec", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBltc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bltc, "Bltc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgec) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bgec, "Bgec", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBltuc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bltuc, "Bltuc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgeuc) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bgeuc, "Bgeuc", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBc1eqz) {
- BranchFpuCondHelper(&mips64::Mips64Assembler::Bc1eqz, "Bc1eqz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBc1nez) {
- BranchFpuCondHelper(&mips64::Mips64Assembler::Bc1nez, "Bc1nez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBeqz) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Beqz, "Beqz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBnez) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bnez, "Bnez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBltz) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bltz, "Bltz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgez) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgez, "Bgez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBlez) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Blez, "Blez", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBgtz) {
- BranchCondOneRegHelper(&mips64::Mips64Assembler::Bgtz, "Bgtz", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBeq) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Beq, "Beq", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, BareBne) {
- BranchCondTwoRegsHelper(&mips64::Mips64Assembler::Bne, "Bne", /* is_bare= */ true);
-}
-
-TEST_F(AssemblerMIPS64Test, LongBeqc) {
- mips64::Mips64Label label;
- __ Beqc(mips64::A0, mips64::A1, &label);
- constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount1; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
- constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
- for (uint32_t i = 0; i != kAdduCount2; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Beqc(mips64::A2, mips64::A3, &label);
-
- uint32_t offset_forward = 2 + kAdduCount1; // 2: account for auipc and jic.
- offset_forward <<= 2;
- offset_forward += (offset_forward & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(kAdduCount2 + 1); // 1: account for bnec.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "bnec $a0, $a1, 1f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "1:\n" <<
- RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
- "2:\n" <<
- RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
- "bnec $a2, $a3, 3f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "3:\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBeqc");
-}
-
-TEST_F(AssemblerMIPS64Test, LongBeqzc) {
- constexpr uint32_t kNopCount1 = (1u << 20) + 1;
- constexpr uint32_t kNopCount2 = (1u << 20) + 1;
- constexpr uint32_t kRequiredCapacity = (kNopCount1 + kNopCount2 + 6u) * 4u;
- ASSERT_LT(__ GetBuffer()->Capacity(), kRequiredCapacity);
- __ GetBuffer()->ExtendCapacity(kRequiredCapacity);
- mips64::Mips64Label label;
- __ Beqzc(mips64::A0, &label);
- for (uint32_t i = 0; i != kNopCount1; ++i) {
- __ Nop();
- }
- __ Bind(&label);
- for (uint32_t i = 0; i != kNopCount2; ++i) {
- __ Nop();
- }
- __ Beqzc(mips64::A2, &label);
-
- uint32_t offset_forward = 2 + kNopCount1; // 2: account for auipc and jic.
- offset_forward <<= 2;
- offset_forward += (offset_forward & 0x8000) << 1; // Account for sign extension in jic.
-
- uint32_t offset_back = -(kNopCount2 + 1); // 1: account for bnezc.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jic.
-
- // Note, we're using the ".fill" directive to tell the assembler to generate many NOPs
- // instead of generating them ourselves in the source code. This saves test time.
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "bnezc $a0, 1f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
- "1:\n" <<
- ".fill 0x" << std::hex << kNopCount1 << " , 4, 0\n"
- "2:\n" <<
- ".fill 0x" << std::hex << kNopCount2 << " , 4, 0\n"
- "bnezc $a2, 3f\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
- "3:\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBeqzc");
-}
-
-TEST_F(AssemblerMIPS64Test, LongBalc) {
- constexpr uint32_t kNopCount1 = (1u << 25) + 1;
- constexpr uint32_t kNopCount2 = (1u << 25) + 1;
- constexpr uint32_t kRequiredCapacity = (kNopCount1 + kNopCount2 + 6u) * 4u;
- ASSERT_LT(__ GetBuffer()->Capacity(), kRequiredCapacity);
- __ GetBuffer()->ExtendCapacity(kRequiredCapacity);
- mips64::Mips64Label label1, label2;
- __ Balc(&label1);
- for (uint32_t i = 0; i != kNopCount1; ++i) {
- __ Nop();
- }
- __ Bind(&label1);
- __ Balc(&label2);
- for (uint32_t i = 0; i != kNopCount2; ++i) {
- __ Nop();
- }
- __ Bind(&label2);
- __ Balc(&label1);
-
- uint32_t offset_forward1 = 2 + kNopCount1; // 2: account for auipc and jialc.
- offset_forward1 <<= 2;
- offset_forward1 += (offset_forward1 & 0x8000) << 1; // Account for sign extension in jialc.
-
- uint32_t offset_forward2 = 2 + kNopCount2; // 2: account for auipc and jialc.
- offset_forward2 <<= 2;
- offset_forward2 += (offset_forward2 & 0x8000) << 1; // Account for sign extension in jialc.
-
- uint32_t offset_back = -(2 + kNopCount2); // 2: account for auipc and jialc.
- offset_back <<= 2;
- offset_back += (offset_back & 0x8000) << 1; // Account for sign extension in jialc.
-
- // Note, we're using the ".fill" directive to tell the assembler to generate many NOPs
- // instead of generating them ourselves in the source code. This saves a few minutes
- // of test time.
- std::ostringstream oss;
- oss <<
- ".set noreorder\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward1) << "\n"
- "jialc $at, 0x" << std::hex << Low16Bits(offset_forward1) << "\n"
- ".fill 0x" << std::hex << kNopCount1 << " , 4, 0\n"
- "1:\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_forward2) << "\n"
- "jialc $at, 0x" << std::hex << Low16Bits(offset_forward2) << "\n"
- ".fill 0x" << std::hex << kNopCount2 << " , 4, 0\n"
- "2:\n"
- "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
- "jialc $at, 0x" << std::hex << Low16Bits(offset_back) << "\n";
- std::string expected = oss.str();
- DriverStr(expected, "LongBalc");
-}
-
-//////////
-// MISC //
-//////////
-
-TEST_F(AssemblerMIPS64Test, Lwpc) {
- // Lwpc() takes an unsigned 19-bit immediate, while the GNU assembler needs a signed offset,
- // hence the sign extension from bit 18 with `imm - ((imm & 0x40000) << 1)`.
- // The GNU assembler also wants the offset to be a multiple of 4, which it will shift right
- // by 2 positions when encoding, hence `<< 2` to compensate for that shift.
- // We capture the value of the immediate with `.set imm, {imm}` because the value is needed
- // twice for the sign extension, but `{imm}` is substituted only once.
- const char* code = ".set imm, {imm}\nlw ${reg}, ((imm - ((imm & 0x40000) << 1)) << 2)($pc)";
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Lwpc, 19, code), "Lwpc");
-}
-
-TEST_F(AssemblerMIPS64Test, Lwupc) {
- // The comment for the Lwpc test applies here as well.
- const char* code = ".set imm, {imm}\nlwu ${reg}, ((imm - ((imm & 0x40000) << 1)) << 2)($pc)";
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Lwupc, 19, code), "Lwupc");
-}
-
-TEST_F(AssemblerMIPS64Test, Ldpc) {
- // The comment for the Lwpc test applies here as well.
- const char* code = ".set imm, {imm}\nld ${reg}, ((imm - ((imm & 0x20000) << 1)) << 3)($pc)";
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Ldpc, 18, code), "Ldpc");
-}
-
-TEST_F(AssemblerMIPS64Test, Auipc) {
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Auipc, 16, "auipc ${reg}, {imm}"), "Auipc");
-}
-
-TEST_F(AssemblerMIPS64Test, Addiupc) {
- // The comment from the Lwpc() test applies to this Addiupc() test as well.
- const char* code = ".set imm, {imm}\naddiupc ${reg}, (imm - ((imm & 0x40000) << 1)) << 2";
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Addiupc, 19, code), "Addiupc");
-}
-
-TEST_F(AssemblerMIPS64Test, Addu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Addu, "addu ${reg1}, ${reg2}, ${reg3}"), "addu");
-}
-
-TEST_F(AssemblerMIPS64Test, Addiu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Addiu, -16, "addiu ${reg1}, ${reg2}, {imm}"),
- "addiu");
-}
-
-TEST_F(AssemblerMIPS64Test, Daddu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Daddu, "daddu ${reg1}, ${reg2}, ${reg3}"), "daddu");
-}
-
-TEST_F(AssemblerMIPS64Test, Daddiu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Daddiu, -16, "daddiu ${reg1}, ${reg2}, {imm}"),
- "daddiu");
-}
-
-TEST_F(AssemblerMIPS64Test, Subu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Subu, "subu ${reg1}, ${reg2}, ${reg3}"), "subu");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsubu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dsubu, "dsubu ${reg1}, ${reg2}, ${reg3}"), "dsubu");
-}
-
-TEST_F(AssemblerMIPS64Test, MulR6) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::MulR6, "mul ${reg1}, ${reg2}, ${reg3}"), "mulR6");
-}
-
-TEST_F(AssemblerMIPS64Test, DivR6) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::DivR6, "div ${reg1}, ${reg2}, ${reg3}"), "divR6");
-}
-
-TEST_F(AssemblerMIPS64Test, ModR6) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::ModR6, "mod ${reg1}, ${reg2}, ${reg3}"), "modR6");
-}
-
-TEST_F(AssemblerMIPS64Test, DivuR6) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::DivuR6, "divu ${reg1}, ${reg2}, ${reg3}"),
- "divuR6");
-}
-
-TEST_F(AssemblerMIPS64Test, ModuR6) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::ModuR6, "modu ${reg1}, ${reg2}, ${reg3}"),
- "moduR6");
-}
-
-TEST_F(AssemblerMIPS64Test, Dmul) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dmul, "dmul ${reg1}, ${reg2}, ${reg3}"), "dmul");
-}
-
-TEST_F(AssemblerMIPS64Test, Ddiv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Ddiv, "ddiv ${reg1}, ${reg2}, ${reg3}"), "ddiv");
-}
-
-TEST_F(AssemblerMIPS64Test, Dmod) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dmod, "dmod ${reg1}, ${reg2}, ${reg3}"), "dmod");
-}
-
-TEST_F(AssemblerMIPS64Test, Ddivu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Ddivu, "ddivu ${reg1}, ${reg2}, ${reg3}"), "ddivu");
-}
-
-TEST_F(AssemblerMIPS64Test, Dmodu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dmodu, "dmodu ${reg1}, ${reg2}, ${reg3}"), "dmodu");
-}
-
-TEST_F(AssemblerMIPS64Test, And) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::And, "and ${reg1}, ${reg2}, ${reg3}"), "and");
-}
-
-TEST_F(AssemblerMIPS64Test, Andi) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Andi, 16, "andi ${reg1}, ${reg2}, {imm}"), "andi");
-}
-
-TEST_F(AssemblerMIPS64Test, Or) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Or, "or ${reg1}, ${reg2}, ${reg3}"), "or");
-}
-
-TEST_F(AssemblerMIPS64Test, Ori) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Ori, 16, "ori ${reg1}, ${reg2}, {imm}"), "ori");
-}
-
-TEST_F(AssemblerMIPS64Test, Xor) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Xor, "xor ${reg1}, ${reg2}, ${reg3}"), "xor");
-}
-
-TEST_F(AssemblerMIPS64Test, Xori) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Xori, 16, "xori ${reg1}, ${reg2}, {imm}"), "xori");
-}
-
-TEST_F(AssemblerMIPS64Test, Nor) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Nor, "nor ${reg1}, ${reg2}, ${reg3}"), "nor");
-}
-
-TEST_F(AssemblerMIPS64Test, Lb) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lb, -16, "lb ${reg1}, {imm}(${reg2})"), "lb");
-}
-
-TEST_F(AssemblerMIPS64Test, Lh) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lh, -16, "lh ${reg1}, {imm}(${reg2})"), "lh");
-}
-
-TEST_F(AssemblerMIPS64Test, Lw) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lw, -16, "lw ${reg1}, {imm}(${reg2})"), "lw");
-}
-
-TEST_F(AssemblerMIPS64Test, Ld) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Ld, -16, "ld ${reg1}, {imm}(${reg2})"), "ld");
-}
-
-TEST_F(AssemblerMIPS64Test, Lbu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lbu, -16, "lbu ${reg1}, {imm}(${reg2})"), "lbu");
-}
-
-TEST_F(AssemblerMIPS64Test, Lhu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lhu, -16, "lhu ${reg1}, {imm}(${reg2})"), "lhu");
-}
-
-TEST_F(AssemblerMIPS64Test, Lwu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lwu, -16, "lwu ${reg1}, {imm}(${reg2})"), "lwu");
-}
-
-TEST_F(AssemblerMIPS64Test, Lui) {
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Lui, 16, "lui ${reg}, {imm}"), "lui");
-}
-
-TEST_F(AssemblerMIPS64Test, Daui) {
- std::vector<mips64::GpuRegister*> reg1_registers = GetRegisters();
- std::vector<mips64::GpuRegister*> reg2_registers = GetRegisters();
- reg2_registers.erase(reg2_registers.begin()); // reg2 can't be ZERO, remove it.
- std::vector<int64_t> imms = CreateImmediateValuesBits(/* imm_bits= */ 16, /* as_uint= */ true);
- WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
- std::ostringstream expected;
- for (mips64::GpuRegister* reg1 : reg1_registers) {
- for (mips64::GpuRegister* reg2 : reg2_registers) {
- for (int64_t imm : imms) {
- __ Daui(*reg1, *reg2, imm);
- expected << "daui $" << *reg1 << ", $" << *reg2 << ", " << imm << "\n";
- }
- }
- }
- DriverStr(expected.str(), "daui");
-}
-
-TEST_F(AssemblerMIPS64Test, Dahi) {
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Dahi, 16, "dahi ${reg}, ${reg}, {imm}"), "dahi");
-}
-
-TEST_F(AssemblerMIPS64Test, Dati) {
- DriverStr(RepeatRIb(&mips64::Mips64Assembler::Dati, 16, "dati ${reg}, ${reg}, {imm}"), "dati");
-}
-
-TEST_F(AssemblerMIPS64Test, Sb) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sb, -16, "sb ${reg1}, {imm}(${reg2})"), "sb");
-}
-
-TEST_F(AssemblerMIPS64Test, Sh) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sh, -16, "sh ${reg1}, {imm}(${reg2})"), "sh");
-}
-
-TEST_F(AssemblerMIPS64Test, Sw) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sw, -16, "sw ${reg1}, {imm}(${reg2})"), "sw");
-}
-
-TEST_F(AssemblerMIPS64Test, Sd) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sd, -16, "sd ${reg1}, {imm}(${reg2})"), "sd");
-}
-
-TEST_F(AssemblerMIPS64Test, Slt) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Slt, "slt ${reg1}, ${reg2}, ${reg3}"), "slt");
-}
-
-TEST_F(AssemblerMIPS64Test, Sltu) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Sltu, "sltu ${reg1}, ${reg2}, ${reg3}"), "sltu");
-}
-
-TEST_F(AssemblerMIPS64Test, Slti) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Slti, -16, "slti ${reg1}, ${reg2}, {imm}"),
- "slti");
-}
-
-TEST_F(AssemblerMIPS64Test, Sltiu) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sltiu, -16, "sltiu ${reg1}, ${reg2}, {imm}"),
- "sltiu");
-}
-
-TEST_F(AssemblerMIPS64Test, Move) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Move, "or ${reg1}, ${reg2}, $zero"), "move");
-}
-
-TEST_F(AssemblerMIPS64Test, Clear) {
- DriverStr(RepeatR(&mips64::Mips64Assembler::Clear, "or ${reg}, $zero, $zero"), "clear");
-}
-
-TEST_F(AssemblerMIPS64Test, Not) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Not, "nor ${reg1}, ${reg2}, $zero"), "not");
-}
-
-TEST_F(AssemblerMIPS64Test, Bitswap) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Bitswap, "bitswap ${reg1}, ${reg2}"), "bitswap");
-}
-
-TEST_F(AssemblerMIPS64Test, Dbitswap) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Dbitswap, "dbitswap ${reg1}, ${reg2}"), "dbitswap");
-}
-
-TEST_F(AssemblerMIPS64Test, Seb) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Seb, "seb ${reg1}, ${reg2}"), "seb");
-}
-
-TEST_F(AssemblerMIPS64Test, Seh) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Seh, "seh ${reg1}, ${reg2}"), "seh");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsbh) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Dsbh, "dsbh ${reg1}, ${reg2}"), "dsbh");
-}
-
-TEST_F(AssemblerMIPS64Test, Dshd) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Dshd, "dshd ${reg1}, ${reg2}"), "dshd");
-}
-
-TEST_F(AssemblerMIPS64Test, Dext) {
- std::vector<mips64::GpuRegister*> reg1_registers = GetRegisters();
- std::vector<mips64::GpuRegister*> reg2_registers = GetRegisters();
- WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 33 * 16);
- std::ostringstream expected;
- for (mips64::GpuRegister* reg1 : reg1_registers) {
- for (mips64::GpuRegister* reg2 : reg2_registers) {
- for (int32_t pos = 0; pos < 32; pos++) {
- for (int32_t size = 1; size <= 32; size++) {
- __ Dext(*reg1, *reg2, pos, size);
- expected << "dext $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
- }
- }
- }
- }
-
- DriverStr(expected.str(), "Dext");
-}
-
-TEST_F(AssemblerMIPS64Test, Ins) {
- std::vector<mips64::GpuRegister*> regs = GetRegisters();
- WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
- std::string expected;
- for (mips64::GpuRegister* reg1 : regs) {
- for (mips64::GpuRegister* reg2 : regs) {
- for (int32_t pos = 0; pos < 32; pos++) {
- for (int32_t size = 1; pos + size <= 32; size++) {
- __ Ins(*reg1, *reg2, pos, size);
- std::ostringstream instr;
- instr << "ins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
- expected += instr.str();
- }
- }
- }
- }
- DriverStr(expected, "Ins");
-}
-
-TEST_F(AssemblerMIPS64Test, DblIns) {
- std::vector<mips64::GpuRegister*> reg1_registers = GetRegisters();
- std::vector<mips64::GpuRegister*> reg2_registers = GetRegisters();
- WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * 65 * 32);
- std::ostringstream expected;
- for (mips64::GpuRegister* reg1 : reg1_registers) {
- for (mips64::GpuRegister* reg2 : reg2_registers) {
- for (int32_t pos = 0; pos < 64; pos++) {
- for (int32_t size = 1; pos + size <= 64; size++) {
- __ DblIns(*reg1, *reg2, pos, size);
- expected << "dins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
- }
- }
- }
- }
-
- DriverStr(expected.str(), "DblIns");
-}
-
-TEST_F(AssemblerMIPS64Test, Lsa) {
- DriverStr(RepeatRRRIb(&mips64::Mips64Assembler::Lsa,
- 2,
- "lsa ${reg1}, ${reg2}, ${reg3}, {imm}",
- 1),
- "lsa");
-}
-
-TEST_F(AssemblerMIPS64Test, Dlsa) {
- DriverStr(RepeatRRRIb(&mips64::Mips64Assembler::Dlsa,
- 2,
- "dlsa ${reg1}, ${reg2}, ${reg3}, {imm}",
- 1),
- "dlsa");
-}
-
-TEST_F(AssemblerMIPS64Test, Wsbh) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Wsbh, "wsbh ${reg1}, ${reg2}"), "wsbh");
-}
-
-TEST_F(AssemblerMIPS64Test, Sll) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sll, 5, "sll ${reg1}, ${reg2}, {imm}"), "sll");
-}
-
-TEST_F(AssemblerMIPS64Test, Srl) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Srl, 5, "srl ${reg1}, ${reg2}, {imm}"), "srl");
-}
-
-TEST_F(AssemblerMIPS64Test, Rotr) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Rotr, 5, "rotr ${reg1}, ${reg2}, {imm}"), "rotr");
-}
-
-TEST_F(AssemblerMIPS64Test, Sra) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sra, 5, "sra ${reg1}, ${reg2}, {imm}"), "sra");
-}
-
-TEST_F(AssemblerMIPS64Test, Sllv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Sllv, "sllv ${reg1}, ${reg2}, ${reg3}"), "sllv");
-}
-
-TEST_F(AssemblerMIPS64Test, Srlv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Srlv, "srlv ${reg1}, ${reg2}, ${reg3}"), "srlv");
-}
-
-TEST_F(AssemblerMIPS64Test, Rotrv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Rotrv, "rotrv ${reg1}, ${reg2}, ${reg3}"), "rotrv");
-}
-
-TEST_F(AssemblerMIPS64Test, Srav) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Srav, "srav ${reg1}, ${reg2}, ${reg3}"), "srav");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsll) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsll, 5, "dsll ${reg1}, ${reg2}, {imm}"), "dsll");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsrl) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsrl, 5, "dsrl ${reg1}, ${reg2}, {imm}"), "dsrl");
-}
-
-TEST_F(AssemblerMIPS64Test, Drotr) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Drotr, 5, "drotr ${reg1}, ${reg2}, {imm}"),
- "drotr");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsra) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsra, 5, "dsra ${reg1}, ${reg2}, {imm}"), "dsra");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsll32) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsll32, 5, "dsll32 ${reg1}, ${reg2}, {imm}"),
- "dsll32");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsrl32) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsrl32, 5, "dsrl32 ${reg1}, ${reg2}, {imm}"),
- "dsrl32");
-}
-
-TEST_F(AssemblerMIPS64Test, Drotr32) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Drotr32, 5, "drotr32 ${reg1}, ${reg2}, {imm}"),
- "drotr32");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsra32) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Dsra32, 5, "dsra32 ${reg1}, ${reg2}, {imm}"),
- "dsra32");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsllv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dsllv, "dsllv ${reg1}, ${reg2}, ${reg3}"), "dsllv");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsrlv) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dsrlv, "dsrlv ${reg1}, ${reg2}, ${reg3}"), "dsrlv");
-}
-
-TEST_F(AssemblerMIPS64Test, Dsrav) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Dsrav, "dsrav ${reg1}, ${reg2}, ${reg3}"), "dsrav");
-}
-
-TEST_F(AssemblerMIPS64Test, Sc) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Sc, -9, "sc ${reg1}, {imm}(${reg2})"), "sc");
-}
-
-TEST_F(AssemblerMIPS64Test, Scd) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Scd, -9, "scd ${reg1}, {imm}(${reg2})"), "scd");
-}
-
-TEST_F(AssemblerMIPS64Test, Ll) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Ll, -9, "ll ${reg1}, {imm}(${reg2})"), "ll");
-}
-
-TEST_F(AssemblerMIPS64Test, Lld) {
- DriverStr(RepeatRRIb(&mips64::Mips64Assembler::Lld, -9, "lld ${reg1}, {imm}(${reg2})"), "lld");
-}
-
-TEST_F(AssemblerMIPS64Test, Seleqz) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Seleqz, "seleqz ${reg1}, ${reg2}, ${reg3}"),
- "seleqz");
-}
-
-TEST_F(AssemblerMIPS64Test, Selnez) {
- DriverStr(RepeatRRR(&mips64::Mips64Assembler::Selnez, "selnez ${reg1}, ${reg2}, ${reg3}"),
- "selnez");
-}
-
-TEST_F(AssemblerMIPS64Test, Clz) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Clz, "clz ${reg1}, ${reg2}"), "clz");
-}
-
-TEST_F(AssemblerMIPS64Test, Clo) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Clo, "clo ${reg1}, ${reg2}"), "clo");
-}
-
-TEST_F(AssemblerMIPS64Test, Dclz) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Dclz, "dclz ${reg1}, ${reg2}"), "dclz");
-}
-
-TEST_F(AssemblerMIPS64Test, Dclo) {
- DriverStr(RepeatRR(&mips64::Mips64Assembler::Dclo, "dclo ${reg1}, ${reg2}"), "dclo");
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFromOffset) {
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 1);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x7FFF);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x8001);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x7FFFFFFE);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x7FFFFFFF);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x80000001);
-
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 1);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x7FFF);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x8001);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x7FFFFFFE);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x7FFFFFFF);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x80000001);
-
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 2);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x7FFE);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x8002);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFE);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x80000002);
-
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 2);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x7FFE);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x8002);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFE);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x80000002);
-
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 4);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x7FFC);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x8004);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x7FFFFFF8);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x80000004);
-
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 4);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x7FFC);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x8004);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x7FFFFFF8);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x80000004);
-
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A0, 0);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 4);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 256);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 1000);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x7FFC);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x8000);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x8004);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x10000);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x27FFC);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x12345678);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, -256);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, -32768);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0xABCDEF00);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x7FFFFFF8);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x80000000);
- __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x80000004);
-
- const char* expected =
- "lb $a0, 0($a0)\n"
- "lb $a0, 0($a1)\n"
- "lb $a0, 1($a1)\n"
- "lb $a0, 256($a1)\n"
- "lb $a0, 1000($a1)\n"
- "lb $a0, 0x7FFF($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lb $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lb $a0, 9($at)\n"
- "daui $at, $a1, 1\n"
- "lb $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lb $a0, 0x5678($at)\n"
- "lb $a0, -256($a1)\n"
- "lb $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lb $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lb $a0, -2($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lb $a0, -1($at)\n"
- "daui $at, $a1, 32768\n"
- "lb $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lb $a0, 1($at)\n"
-
- "lbu $a0, 0($a0)\n"
- "lbu $a0, 0($a1)\n"
- "lbu $a0, 1($a1)\n"
- "lbu $a0, 256($a1)\n"
- "lbu $a0, 1000($a1)\n"
- "lbu $a0, 0x7FFF($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lbu $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lbu $a0, 9($at)\n"
- "daui $at, $a1, 1\n"
- "lbu $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lbu $a0, 0x5678($at)\n"
- "lbu $a0, -256($a1)\n"
- "lbu $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lbu $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lbu $a0, -2($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lbu $a0, -1($at)\n"
- "daui $at, $a1, 32768\n"
- "lbu $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lbu $a0, 1($at)\n"
-
- "lh $a0, 0($a0)\n"
- "lh $a0, 0($a1)\n"
- "lh $a0, 2($a1)\n"
- "lh $a0, 256($a1)\n"
- "lh $a0, 1000($a1)\n"
- "lh $a0, 0x7FFE($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lh $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lh $a0, 10($at)\n"
- "daui $at, $a1, 1\n"
- "lh $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lh $a0, 0x5678($at)\n"
- "lh $a0, -256($a1)\n"
- "lh $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lh $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lh $a0, -4($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lh $a0, -2($at)\n"
- "daui $at, $a1, 32768\n"
- "lh $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lh $a0, 2($at)\n"
-
- "lhu $a0, 0($a0)\n"
- "lhu $a0, 0($a1)\n"
- "lhu $a0, 2($a1)\n"
- "lhu $a0, 256($a1)\n"
- "lhu $a0, 1000($a1)\n"
- "lhu $a0, 0x7FFE($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lhu $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lhu $a0, 10($at)\n"
- "daui $at, $a1, 1\n"
- "lhu $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lhu $a0, 0x5678($at)\n"
- "lhu $a0, -256($a1)\n"
- "lhu $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lhu $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lhu $a0, -4($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lhu $a0, -2($at)\n"
- "daui $at, $a1, 32768\n"
- "lhu $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lhu $a0, 2($at)\n"
-
- "lw $a0, 0($a0)\n"
- "lw $a0, 0($a1)\n"
- "lw $a0, 4($a1)\n"
- "lw $a0, 256($a1)\n"
- "lw $a0, 1000($a1)\n"
- "lw $a0, 0x7FFC($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lw $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lw $a0, 12($at)\n"
- "daui $at, $a1, 1\n"
- "lw $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lw $a0, 0x5678($at)\n"
- "lw $a0, -256($a1)\n"
- "lw $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lw $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lw $a0, -8($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lw $a0, -4($at)\n"
- "daui $at, $a1, 32768\n"
- "lw $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lw $a0, 4($at)\n"
-
- "lwu $a0, 0($a0)\n"
- "lwu $a0, 0($a1)\n"
- "lwu $a0, 4($a1)\n"
- "lwu $a0, 256($a1)\n"
- "lwu $a0, 1000($a1)\n"
- "lwu $a0, 0x7FFC($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "lwu $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lwu $a0, 12($at)\n"
- "daui $at, $a1, 1\n"
- "lwu $a0, 0($at)\n"
- "daui $at, $a1, 0x1234\n"
- "lwu $a0, 0x5678($at)\n"
- "lwu $a0, -256($a1)\n"
- "lwu $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "lwu $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lwu $a0, -8($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lwu $a0, -4($at)\n"
- "daui $at, $a1, 32768\n"
- "lwu $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lwu $a0, 4($at)\n"
-
- "ld $a0, 0($a0)\n"
- "ld $a0, 0($a1)\n"
- "lwu $a0, 4($a1)\n"
- "lwu $t3, 8($a1)\n"
- "dinsu $a0, $t3, 32, 32\n"
- "ld $a0, 256($a1)\n"
- "ld $a0, 1000($a1)\n"
- "daddiu $at, $a1, 32760\n"
- "lwu $a0, 4($at)\n"
- "lwu $t3, 8($at)\n"
- "dinsu $a0, $t3, 32, 32\n"
- "daddiu $at, $a1, 32760\n"
- "ld $a0, 8($at)\n"
- "daddiu $at, $a1, 32760\n"
- "lwu $a0, 12($at)\n"
- "lwu $t3, 16($at)\n"
- "dinsu $a0, $t3, 32, 32\n"
- "daui $at, $a1, 1\n"
- "ld $a0, 0($at)\n"
- "daui $at, $a1, 2\n"
- "daddiu $at, $at, 8\n"
- "lwu $a0, 0x7ff4($at)\n"
- "lwu $t3, 0x7ff8($at)\n"
- "dinsu $a0, $t3, 32, 32\n"
- "daui $at, $a1, 0x1234\n"
- "ld $a0, 0x5678($at)\n"
- "ld $a0, -256($a1)\n"
- "ld $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "ld $a0, -4352($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "ld $a0, -8($at)\n"
- "daui $at, $a1, 32768\n"
- "dahi $at, $at, 1\n"
- "lwu $a0, -4($at)\n"
- "lwu $t3, 0($at)\n"
- "dinsu $a0, $t3, 32, 32\n"
- "daui $at, $a1, 32768\n"
- "ld $a0, 0($at)\n"
- "daui $at, $a1, 32768\n"
- "lwu $a0, 4($at)\n"
- "lwu $t3, 8($at)\n"
- "dinsu $a0, $t3, 32, 32\n";
- DriverStr(expected, "LoadFromOffset");
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFpuFromOffset) {
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 4);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 256);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0x7FFC);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0x8000);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0x8004);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0x10000);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0x12345678);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, -256);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, -32768);
- __ LoadFpuFromOffset(mips64::kLoadWord, mips64::F0, mips64::A0, 0xABCDEF00);
-
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 4);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 256);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0x7FFC);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0x8000);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0x8004);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0x10000);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0x12345678);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, -256);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, -32768);
- __ LoadFpuFromOffset(mips64::kLoadDoubleword, mips64::F0, mips64::A0, 0xABCDEF00);
-
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 8);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 511);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 512);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 513);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 514);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 516);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1022);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1024);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1025);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1026);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 1028);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2044);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2048);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2049);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2050);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 2052);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4088);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4096);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4097);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4098);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4100);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 4104);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x7FFC);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x8000);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x10000);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x12345678);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x12350078);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -256);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -511);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -513);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -1022);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -1026);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -2044);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -2052);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -4096);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -4104);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, -32768);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0xABCDEF00);
- __ LoadFpuFromOffset(mips64::kLoadQuadword, mips64::F0, mips64::A0, 0x7FFFABCD);
-
- const char* expected =
- "lwc1 $f0, 0($a0)\n"
- "lwc1 $f0, 4($a0)\n"
- "lwc1 $f0, 256($a0)\n"
- "lwc1 $f0, 0x7FFC($a0)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "lwc1 $f0, 8($at)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "lwc1 $f0, 12($at)\n"
- "daui $at, $a0, 1\n"
- "lwc1 $f0, 0($at)\n"
- "daui $at, $a0, 4660 # 0x1234\n"
- "lwc1 $f0, 22136($at) # 0x5678\n"
- "lwc1 $f0, -256($a0)\n"
- "lwc1 $f0, -32768($a0)\n"
- "daui $at, $a0, 0xABCE\n"
- "lwc1 $f0, -0x1100($at) # 0xEF00\n"
-
- "ldc1 $f0, 0($a0)\n"
- "lwc1 $f0, 4($a0)\n"
- "lw $t3, 8($a0)\n"
- "mthc1 $t3, $f0\n"
- "ldc1 $f0, 256($a0)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "lwc1 $f0, 4($at)\n"
- "lw $t3, 8($at)\n"
- "mthc1 $t3, $f0\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "ldc1 $f0, 8($at)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "lwc1 $f0, 12($at)\n"
- "lw $t3, 16($at)\n"
- "mthc1 $t3, $f0\n"
- "daui $at, $a0, 1\n"
- "ldc1 $f0, 0($at)\n"
- "daui $at, $a0, 4660 # 0x1234\n"
- "ldc1 $f0, 22136($at) # 0x5678\n"
- "ldc1 $f0, -256($a0)\n"
- "ldc1 $f0, -32768($a0)\n"
- "daui $at, $a0, 0xABCE\n"
- "ldc1 $f0, -0x1100($at) # 0xEF00\n"
-
- "ld.d $w0, 0($a0)\n"
- "ld.b $w0, 1($a0)\n"
- "ld.h $w0, 2($a0)\n"
- "ld.w $w0, 4($a0)\n"
- "ld.d $w0, 8($a0)\n"
- "ld.b $w0, 511($a0)\n"
- "ld.d $w0, 512($a0)\n"
- "daddiu $at, $a0, 513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, 514($a0)\n"
- "ld.w $w0, 516($a0)\n"
- "ld.h $w0, 1022($a0)\n"
- "ld.d $w0, 1024($a0)\n"
- "daddiu $at, $a0, 1025\n"
- "ld.b $w0, 0($at)\n"
- "daddiu $at, $a0, 1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, 1028($a0)\n"
- "ld.w $w0, 2044($a0)\n"
- "ld.d $w0, 2048($a0)\n"
- "daddiu $at, $a0, 2049\n"
- "ld.b $w0, 0($at)\n"
- "daddiu $at, $a0, 2050\n"
- "ld.h $w0, 0($at)\n"
- "daddiu $at, $a0, 2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, 4088($a0)\n"
- "daddiu $at, $a0, 4096\n"
- "ld.d $w0, 0($at)\n"
- "daddiu $at, $a0, 4097\n"
- "ld.b $w0, 0($at)\n"
- "daddiu $at, $a0, 4098\n"
- "ld.h $w0, 0($at)\n"
- "daddiu $at, $a0, 4100\n"
- "ld.w $w0, 0($at)\n"
- "daddiu $at, $a0, 4104\n"
- "ld.d $w0, 0($at)\n"
- "daddiu $at, $a0, 0x7FFC\n"
- "ld.w $w0, 0($at)\n"
- "daddiu $at, $a0, 0x7FF8\n"
- "ld.d $w0, 8($at)\n"
- "daui $at, $a0, 0x1\n"
- "ld.d $w0, 0($at)\n"
- "daui $at, $a0, 0x1234\n"
- "daddiu $at, $at, 0x6000\n"
- "ld.d $w0, -2440($at) # 0xF678\n"
- "daui $at, $a0, 0x1235\n"
- "ld.d $w0, 0x78($at)\n"
- "ld.d $w0, -256($a0)\n"
- "ld.b $w0, -511($a0)\n"
- "daddiu $at, $a0, -513\n"
- "ld.b $w0, 0($at)\n"
- "ld.h $w0, -1022($a0)\n"
- "daddiu $at, $a0, -1026\n"
- "ld.h $w0, 0($at)\n"
- "ld.w $w0, -2044($a0)\n"
- "daddiu $at, $a0, -2052\n"
- "ld.w $w0, 0($at)\n"
- "ld.d $w0, -4096($a0)\n"
- "daddiu $at, $a0, -4104\n"
- "ld.d $w0, 0($at)\n"
- "daddiu $at, $a0, -32768\n"
- "ld.d $w0, 0($at)\n"
- "daui $at, $a0, 0xABCE\n"
- "daddiu $at, $at, -8192 # 0xE000\n"
- "ld.d $w0, 0xF00($at)\n"
- "daui $at, $a0, 0x8000\n"
- "dahi $at, $at, 1\n"
- "daddiu $at, $at, -21504 # 0xAC00\n"
- "ld.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "LoadFpuFromOffset");
-}
-
-TEST_F(AssemblerMIPS64Test, StoreToOffset) {
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A0, 0);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 1);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 256);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 1000);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0x7FFF);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0x8000);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0x8001);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0x10000);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0x12345678);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, -256);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, -32768);
- __ StoreToOffset(mips64::kStoreByte, mips64::A0, mips64::A1, 0xABCDEF00);
-
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A0, 0);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 2);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 256);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 1000);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0x7FFE);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0x8000);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0x8002);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0x10000);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0x12345678);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, -256);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, -32768);
- __ StoreToOffset(mips64::kStoreHalfword, mips64::A0, mips64::A1, 0xABCDEF00);
-
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A0, 0);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 4);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 256);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 1000);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0x7FFC);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0x8000);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0x8004);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0x10000);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0x12345678);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, -256);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, -32768);
- __ StoreToOffset(mips64::kStoreWord, mips64::A0, mips64::A1, 0xABCDEF00);
-
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A0, 0);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 4);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 256);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 1000);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x7FFC);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x8000);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x8004);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x10000);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x12345678);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, -256);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, -32768);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0xABCDEF00);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x7FFFFFF8);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x7FFFFFFC);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x80000000);
- __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x80000004);
-
- const char* expected =
- "sb $a0, 0($a0)\n"
- "sb $a0, 0($a1)\n"
- "sb $a0, 1($a1)\n"
- "sb $a0, 256($a1)\n"
- "sb $a0, 1000($a1)\n"
- "sb $a0, 0x7FFF($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sb $a0, 8($at)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sb $a0, 9($at)\n"
- "daui $at, $a1, 1\n"
- "sb $a0, 0($at)\n"
- "daui $at, $a1, 4660 # 0x1234\n"
- "sb $a0, 22136($at) # 0x5678\n"
- "sb $a0, -256($a1)\n"
- "sb $a0, -32768($a1)\n"
- "daui $at, $a1, 43982 # 0xABCE\n"
- "sb $a0, -4352($at) # 0xEF00\n"
-
- "sh $a0, 0($a0)\n"
- "sh $a0, 0($a1)\n"
- "sh $a0, 2($a1)\n"
- "sh $a0, 256($a1)\n"
- "sh $a0, 1000($a1)\n"
- "sh $a0, 0x7FFE($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sh $a0, 8($at)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sh $a0, 10($at)\n"
- "daui $at, $a1, 1\n"
- "sh $a0, 0($at)\n"
- "daui $at, $a1, 4660 # 0x1234\n"
- "sh $a0, 22136($at) # 0x5678\n"
- "sh $a0, -256($a1)\n"
- "sh $a0, -32768($a1)\n"
- "daui $at, $a1, 43982 # 0xABCE\n"
- "sh $a0, -4352($at) # 0xEF00\n"
-
- "sw $a0, 0($a0)\n"
- "sw $a0, 0($a1)\n"
- "sw $a0, 4($a1)\n"
- "sw $a0, 256($a1)\n"
- "sw $a0, 1000($a1)\n"
- "sw $a0, 0x7FFC($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sw $a0, 8($at)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sw $a0, 12($at)\n"
- "daui $at, $a1, 1\n"
- "sw $a0, 0($at)\n"
- "daui $at, $a1, 4660 # 0x1234\n"
- "sw $a0, 22136($at) # 0x5678\n"
- "sw $a0, -256($a1)\n"
- "sw $a0, -32768($a1)\n"
- "daui $at, $a1, 43982 # 0xABCE\n"
- "sw $a0, -4352($at) # 0xEF00\n"
-
- "sd $a0, 0($a0)\n"
- "sd $a0, 0($a1)\n"
- "sw $a0, 4($a1)\n"
- "dsrl32 $t3, $a0, 0\n"
- "sw $t3, 8($a1)\n"
- "sd $a0, 256($a1)\n"
- "sd $a0, 1000($a1)\n"
- "daddiu $at, $a1, 0x7FF8\n"
- "sw $a0, 4($at)\n"
- "dsrl32 $t3, $a0, 0\n"
- "sw $t3, 8($at)\n"
- "daddiu $at, $a1, 32760 # 0x7FF8\n"
- "sd $a0, 8($at)\n"
- "daddiu $at, $a1, 32760 # 0x7FF8\n"
- "sw $a0, 12($at)\n"
- "dsrl32 $t3, $a0, 0\n"
- "sw $t3, 16($at)\n"
- "daui $at, $a1, 1\n"
- "sd $a0, 0($at)\n"
- "daui $at, $a1, 4660 # 0x1234\n"
- "sd $a0, 22136($at) # 0x5678\n"
- "sd $a0, -256($a1)\n"
- "sd $a0, -32768($a1)\n"
- "daui $at, $a1, 0xABCE\n"
- "sd $a0, -0x1100($at)\n"
- "daui $at, $a1, 0x8000\n"
- "dahi $at, $at, 1\n"
- "sd $a0, -8($at)\n"
- "daui $at, $a1, 0x8000\n"
- "dahi $at, $at, 1\n"
- "sw $a0, -4($at) # 0xFFFC\n"
- "dsrl32 $t3, $a0, 0\n"
- "sw $t3, 0($at) # 0x0\n"
- "daui $at, $a1, 0x8000\n"
- "sd $a0, 0($at) # 0x0\n"
- "daui $at, $a1, 0x8000\n"
- "sw $a0, 4($at) # 0x4\n"
- "dsrl32 $t3, $a0, 0\n"
- "sw $t3, 8($at) # 0x8\n";
- DriverStr(expected, "StoreToOffset");
-}
-
-TEST_F(AssemblerMIPS64Test, StoreFpuToOffset) {
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 4);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 256);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0x7FFC);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0x8000);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0x8004);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0x10000);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0x12345678);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, -256);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, -32768);
- __ StoreFpuToOffset(mips64::kStoreWord, mips64::F0, mips64::A0, 0xABCDEF00);
-
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 4);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 256);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0x7FFC);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0x8000);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0x8004);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0x10000);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0x12345678);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, -256);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, -32768);
- __ StoreFpuToOffset(mips64::kStoreDoubleword, mips64::F0, mips64::A0, 0xABCDEF00);
-
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 8);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 511);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 512);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 513);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 514);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 516);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1022);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1024);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1025);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1026);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 1028);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2044);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2048);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2049);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2050);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 2052);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4088);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4096);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4097);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4098);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4100);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 4104);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x7FFC);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x8000);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x10000);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x12345678);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x12350078);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -256);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -511);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -513);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -1022);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -1026);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -2044);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -2052);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -4096);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -4104);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, -32768);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0xABCDEF00);
- __ StoreFpuToOffset(mips64::kStoreQuadword, mips64::F0, mips64::A0, 0x7FFFABCD);
-
- const char* expected =
- "swc1 $f0, 0($a0)\n"
- "swc1 $f0, 4($a0)\n"
- "swc1 $f0, 256($a0)\n"
- "swc1 $f0, 0x7FFC($a0)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "swc1 $f0, 8($at)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "swc1 $f0, 12($at)\n"
- "daui $at, $a0, 1\n"
- "swc1 $f0, 0($at)\n"
- "daui $at, $a0, 4660 # 0x1234\n"
- "swc1 $f0, 22136($at) # 0x5678\n"
- "swc1 $f0, -256($a0)\n"
- "swc1 $f0, -32768($a0)\n"
- "daui $at, $a0, 0xABCE\n"
- "swc1 $f0, -0x1100($at)\n"
-
- "sdc1 $f0, 0($a0)\n"
- "mfhc1 $t3, $f0\n"
- "swc1 $f0, 4($a0)\n"
- "sw $t3, 8($a0)\n"
- "sdc1 $f0, 256($a0)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "mfhc1 $t3, $f0\n"
- "swc1 $f0, 4($at)\n"
- "sw $t3, 8($at)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "sdc1 $f0, 8($at)\n"
- "daddiu $at, $a0, 32760 # 0x7FF8\n"
- "mfhc1 $t3, $f0\n"
- "swc1 $f0, 12($at)\n"
- "sw $t3, 16($at)\n"
- "daui $at, $a0, 1\n"
- "sdc1 $f0, 0($at)\n"
- "daui $at, $a0, 4660 # 0x1234\n"
- "sdc1 $f0, 22136($at) # 0x5678\n"
- "sdc1 $f0, -256($a0)\n"
- "sdc1 $f0, -32768($a0)\n"
- "daui $at, $a0, 0xABCE\n"
- "sdc1 $f0, -0x1100($at)\n"
-
- "st.d $w0, 0($a0)\n"
- "st.b $w0, 1($a0)\n"
- "st.h $w0, 2($a0)\n"
- "st.w $w0, 4($a0)\n"
- "st.d $w0, 8($a0)\n"
- "st.b $w0, 511($a0)\n"
- "st.d $w0, 512($a0)\n"
- "daddiu $at, $a0, 513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, 514($a0)\n"
- "st.w $w0, 516($a0)\n"
- "st.h $w0, 1022($a0)\n"
- "st.d $w0, 1024($a0)\n"
- "daddiu $at, $a0, 1025\n"
- "st.b $w0, 0($at)\n"
- "daddiu $at, $a0, 1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, 1028($a0)\n"
- "st.w $w0, 2044($a0)\n"
- "st.d $w0, 2048($a0)\n"
- "daddiu $at, $a0, 2049\n"
- "st.b $w0, 0($at)\n"
- "daddiu $at, $a0, 2050\n"
- "st.h $w0, 0($at)\n"
- "daddiu $at, $a0, 2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, 4088($a0)\n"
- "daddiu $at, $a0, 4096\n"
- "st.d $w0, 0($at)\n"
- "daddiu $at, $a0, 4097\n"
- "st.b $w0, 0($at)\n"
- "daddiu $at, $a0, 4098\n"
- "st.h $w0, 0($at)\n"
- "daddiu $at, $a0, 4100\n"
- "st.w $w0, 0($at)\n"
- "daddiu $at, $a0, 4104\n"
- "st.d $w0, 0($at)\n"
- "daddiu $at, $a0, 0x7FFC\n"
- "st.w $w0, 0($at)\n"
- "daddiu $at, $a0, 0x7FF8\n"
- "st.d $w0, 8($at)\n"
- "daui $at, $a0, 0x1\n"
- "st.d $w0, 0($at)\n"
- "daui $at, $a0, 0x1234\n"
- "daddiu $at, $at, 0x6000\n"
- "st.d $w0, -2440($at) # 0xF678\n"
- "daui $at, $a0, 0x1235\n"
- "st.d $w0, 0x78($at)\n"
- "st.d $w0, -256($a0)\n"
- "st.b $w0, -511($a0)\n"
- "daddiu $at, $a0, -513\n"
- "st.b $w0, 0($at)\n"
- "st.h $w0, -1022($a0)\n"
- "daddiu $at, $a0, -1026\n"
- "st.h $w0, 0($at)\n"
- "st.w $w0, -2044($a0)\n"
- "daddiu $at, $a0, -2052\n"
- "st.w $w0, 0($at)\n"
- "st.d $w0, -4096($a0)\n"
- "daddiu $at, $a0, -4104\n"
- "st.d $w0, 0($at)\n"
- "daddiu $at, $a0, -32768\n"
- "st.d $w0, 0($at)\n"
- "daui $at, $a0, 0xABCE\n"
- "daddiu $at, $at, -8192 # 0xE000\n"
- "st.d $w0, 0xF00($at)\n"
- "daui $at, $a0, 0x8000\n"
- "dahi $at, $at, 1\n"
- "daddiu $at, $at, -21504 # 0xAC00\n"
- "st.b $w0, -51($at) # 0xFFCD\n";
- DriverStr(expected, "StoreFpuToOffset");
-}
-
-TEST_F(AssemblerMIPS64Test, StoreConstToOffset) {
- __ StoreConstToOffset(mips64::kStoreByte, 0xFF, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreHalfword, 0xFFFF, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreWord, 0x12345678, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreDoubleword, 0x123456789ABCDEF0, mips64::A1, +0, mips64::T8);
-
- __ StoreConstToOffset(mips64::kStoreByte, 0, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreHalfword, 0, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreWord, 0, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreDoubleword, 0, mips64::A1, +0, mips64::T8);
-
- __ StoreConstToOffset(mips64::kStoreDoubleword, 0x1234567812345678, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreDoubleword, 0x1234567800000000, mips64::A1, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreDoubleword, 0x0000000012345678, mips64::A1, +0, mips64::T8);
-
- __ StoreConstToOffset(mips64::kStoreWord, 0, mips64::T8, +0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreWord, 0x12345678, mips64::T8, +0, mips64::T8);
-
- __ StoreConstToOffset(mips64::kStoreWord, 0, mips64::A1, -0xFFF0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreWord, 0x12345678, mips64::A1, +0xFFF0, mips64::T8);
-
- __ StoreConstToOffset(mips64::kStoreWord, 0, mips64::T8, -0xFFF0, mips64::T8);
- __ StoreConstToOffset(mips64::kStoreWord, 0x12345678, mips64::T8, +0xFFF0, mips64::T8);
-
- const char* expected =
- "ori $t8, $zero, 0xFF\n"
- "sb $t8, 0($a1)\n"
- "ori $t8, $zero, 0xFFFF\n"
- "sh $t8, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8,0x5678\n"
- "sw $t8, 0($a1)\n"
- "lui $t8, 0x9abc\n"
- "ori $t8, $t8,0xdef0\n"
- "dahi $t8, $t8, 0x5679\n"
- "dati $t8, $t8, 0x1234\n"
- "sd $t8, 0($a1)\n"
- "sb $zero, 0($a1)\n"
- "sh $zero, 0($a1)\n"
- "sw $zero, 0($a1)\n"
- "sd $zero, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8,0x5678\n"
- "dins $t8, $t8, 0x20, 0x20\n"
- "sd $t8, 0($a1)\n"
- "lui $t8, 0x246\n"
- "ori $t8, $t8, 0x8acf\n"
- "dsll32 $t8, $t8, 0x3\n"
- "sd $t8, 0($a1)\n"
- "lui $t8, 0x1234\n"
- "ori $t8, $t8, 0x5678\n"
- "sd $t8, 0($a1)\n"
- "sw $zero, 0($t8)\n"
- "lui $at,0x1234\n"
- "ori $at, $at, 0x5678\n"
- "sw $at, 0($t8)\n"
- "daddiu $at, $a1, -32760 # 0x8008\n"
- "sw $zero, -32760($at) # 0x8008\n"
- "daddiu $at, $a1, 32760 # 0x7FF8\n"
- "lui $t8, 4660 # 0x1234\n"
- "ori $t8, $t8, 22136 # 0x5678\n"
- "sw $t8, 32760($at) # 0x7FF8\n"
- "daddiu $at, $t8, -32760 # 0x8008\n"
- "sw $zero, -32760($at) # 0x8008\n"
- "daddiu $at, $t8, 32760 # 0x7FF8\n"
- "lui $t8, 4660 # 0x1234\n"
- "ori $t8, $t8, 22136 # 0x5678\n"
- "sw $t8, 32760($at) # 0x7FF8\n";
- DriverStr(expected, "StoreConstToOffset");
-}
-//////////////////////////////
-// Loading/adding Constants //
-//////////////////////////////
-
-TEST_F(AssemblerMIPS64Test, LoadConst32) {
- // IsUint<16>(value)
- __ LoadConst32(mips64::V0, 0);
- __ LoadConst32(mips64::V0, 65535);
- // IsInt<16>(value)
- __ LoadConst32(mips64::V0, -1);
- __ LoadConst32(mips64::V0, -32768);
- // Everything else
- __ LoadConst32(mips64::V0, 65536);
- __ LoadConst32(mips64::V0, 65537);
- __ LoadConst32(mips64::V0, 2147483647);
- __ LoadConst32(mips64::V0, -32769);
- __ LoadConst32(mips64::V0, -65536);
- __ LoadConst32(mips64::V0, -65537);
- __ LoadConst32(mips64::V0, -2147483647);
- __ LoadConst32(mips64::V0, -2147483648);
-
- const char* expected =
- // IsUint<16>(value)
- "ori $v0, $zero, 0\n" // __ LoadConst32(mips64::V0, 0);
- "ori $v0, $zero, 65535\n" // __ LoadConst32(mips64::V0, 65535);
- // IsInt<16>(value)
- "addiu $v0, $zero, -1\n" // __ LoadConst32(mips64::V0, -1);
- "addiu $v0, $zero, -32768\n" // __ LoadConst32(mips64::V0, -32768);
- // Everything else
- "lui $v0, 1\n" // __ LoadConst32(mips64::V0, 65536);
- "lui $v0, 1\n" // __ LoadConst32(mips64::V0, 65537);
- "ori $v0, 1\n" // "
- "lui $v0, 32767\n" // __ LoadConst32(mips64::V0, 2147483647);
- "ori $v0, 65535\n" // "
- "lui $v0, 65535\n" // __ LoadConst32(mips64::V0, -32769);
- "ori $v0, 32767\n" // "
- "lui $v0, 65535\n" // __ LoadConst32(mips64::V0, -65536);
- "lui $v0, 65534\n" // __ LoadConst32(mips64::V0, -65537);
- "ori $v0, 65535\n" // "
- "lui $v0, 32768\n" // __ LoadConst32(mips64::V0, -2147483647);
- "ori $v0, 1\n" // "
- "lui $v0, 32768\n"; // __ LoadConst32(mips64::V0, -2147483648);
- DriverStr(expected, "LoadConst32");
-}
-
-TEST_F(AssemblerMIPS64Test, Addiu32) {
- __ Addiu32(mips64::A1, mips64::A2, -0x8000);
- __ Addiu32(mips64::A1, mips64::A2, +0);
- __ Addiu32(mips64::A1, mips64::A2, +0x7FFF);
- __ Addiu32(mips64::A1, mips64::A2, -0x8001);
- __ Addiu32(mips64::A1, mips64::A2, +0x8000);
- __ Addiu32(mips64::A1, mips64::A2, -0x10000);
- __ Addiu32(mips64::A1, mips64::A2, +0x10000);
- __ Addiu32(mips64::A1, mips64::A2, +0x12345678);
-
- const char* expected =
- "addiu $a1, $a2, -0x8000\n"
- "addiu $a1, $a2, 0\n"
- "addiu $a1, $a2, 0x7FFF\n"
- "aui $a1, $a2, 0xFFFF\n"
- "addiu $a1, $a1, 0x7FFF\n"
- "aui $a1, $a2, 1\n"
- "addiu $a1, $a1, -0x8000\n"
- "aui $a1, $a2, 0xFFFF\n"
- "aui $a1, $a2, 1\n"
- "aui $a1, $a2, 0x1234\n"
- "addiu $a1, $a1, 0x5678\n";
- DriverStr(expected, "Addiu32");
-}
-
-static uint64_t SignExtend16To64(uint16_t n) {
- return static_cast<int16_t>(n);
-}
-
-// The art::mips64::Mips64Assembler::LoadConst64() method uses a template
-// to minimize the number of instructions needed to load a 64-bit constant
-// value into a register. The template calls various methods which emit
-// MIPS machine instructions. This struct (class) uses the same template
-// but overrides the definitions of the methods which emit MIPS instructions
-// to use methods which simulate the operation of the corresponding MIPS
-// instructions. After invoking LoadConst64() the target register should
-// contain the same 64-bit value as was input to LoadConst64(). If the
-// simulated register doesn't contain the correct value then there is probably
-// an error in the template function.
-struct LoadConst64Tester {
- LoadConst64Tester() {
- // Initialize all of the registers for simulation to zero.
- for (int r = 0; r < 32; r++) {
- regs_[r] = 0;
- }
- // Clear all of the path flags.
- loadconst64_paths_ = art::mips64::kLoadConst64PathZero;
- }
- void Addiu(mips64::GpuRegister rd, mips64::GpuRegister rs, uint16_t c) {
- regs_[rd] = static_cast<int32_t>(regs_[rs] + SignExtend16To64(c));
- }
- void Daddiu(mips64::GpuRegister rd, mips64::GpuRegister rs, uint16_t c) {
- regs_[rd] = regs_[rs] + SignExtend16To64(c);
- }
- void Dahi(mips64::GpuRegister rd, uint16_t c) {
- regs_[rd] += SignExtend16To64(c) << 32;
- }
- void Dati(mips64::GpuRegister rd, uint16_t c) {
- regs_[rd] += SignExtend16To64(c) << 48;
- }
- void Dinsu(mips64::GpuRegister rt, mips64::GpuRegister rs, int pos, int size) {
- CHECK(IsUint<5>(pos - 32)) << pos;
- CHECK(IsUint<5>(size - 1)) << size;
- CHECK(IsUint<5>(pos + size - 33)) << pos << " + " << size;
- uint64_t src_mask = (UINT64_C(1) << size) - 1;
- uint64_t dsk_mask = ~(src_mask << pos);
-
- regs_[rt] = (regs_[rt] & dsk_mask) | ((regs_[rs] & src_mask) << pos);
- }
- void Dsll(mips64::GpuRegister rd, mips64::GpuRegister rt, int shamt) {
- regs_[rd] = regs_[rt] << (shamt & 0x1f);
- }
- void Dsll32(mips64::GpuRegister rd, mips64::GpuRegister rt, int shamt) {
- regs_[rd] = regs_[rt] << (32 + (shamt & 0x1f));
- }
- void Dsrl(mips64::GpuRegister rd, mips64::GpuRegister rt, int shamt) {
- regs_[rd] = regs_[rt] >> (shamt & 0x1f);
- }
- void Dsrl32(mips64::GpuRegister rd, mips64::GpuRegister rt, int shamt) {
- regs_[rd] = regs_[rt] >> (32 + (shamt & 0x1f));
- }
- void Lui(mips64::GpuRegister rd, uint16_t c) {
- regs_[rd] = SignExtend16To64(c) << 16;
- }
- void Ori(mips64::GpuRegister rd, mips64::GpuRegister rs, uint16_t c) {
- regs_[rd] = regs_[rs] | c;
- }
- void LoadConst32(mips64::GpuRegister rd, int32_t c) {
- CHECK_NE(rd, 0);
- mips64::TemplateLoadConst32<LoadConst64Tester>(this, rd, c);
- CHECK_EQ(regs_[rd], static_cast<uint64_t>(c));
- }
- void LoadConst64(mips64::GpuRegister rd, int64_t c) {
- CHECK_NE(rd, 0);
- mips64::TemplateLoadConst64<LoadConst64Tester>(this, rd, c);
- CHECK_EQ(regs_[rd], static_cast<uint64_t>(c));
- }
- uint64_t regs_[32];
-
- // Getter function for loadconst64_paths_.
- int GetPathsCovered() {
- return loadconst64_paths_;
- }
-
- void RecordLoadConst64Path(int value) {
- loadconst64_paths_ |= value;
- }
-
- private:
- // This variable holds a bitmask to tell us which paths were taken
- // through the template function which loads 64-bit values.
- int loadconst64_paths_;
-};
-
-TEST_F(AssemblerMIPS64Test, LoadConst64) {
- const uint16_t imms[] = {
- 0, 1, 2, 3, 4, 0x33, 0x66, 0x55, 0x99, 0xaa, 0xcc, 0xff, 0x5500, 0x5555,
- 0x7ffc, 0x7ffd, 0x7ffe, 0x7fff, 0x8000, 0x8001, 0x8002, 0x8003, 0x8004,
- 0xaaaa, 0xfffc, 0xfffd, 0xfffe, 0xffff
- };
- unsigned d0, d1, d2, d3;
- LoadConst64Tester tester;
-
- union {
- int64_t v64;
- uint16_t v16[4];
- } u;
-
- for (d3 = 0; d3 < sizeof imms / sizeof imms[0]; d3++) {
- u.v16[3] = imms[d3];
-
- for (d2 = 0; d2 < sizeof imms / sizeof imms[0]; d2++) {
- u.v16[2] = imms[d2];
-
- for (d1 = 0; d1 < sizeof imms / sizeof imms[0]; d1++) {
- u.v16[1] = imms[d1];
-
- for (d0 = 0; d0 < sizeof imms / sizeof imms[0]; d0++) {
- u.v16[0] = imms[d0];
-
- tester.LoadConst64(mips64::V0, u.v64);
- }
- }
- }
- }
-
- // Verify that we tested all paths through the "load 64-bit value"
- // function template.
- EXPECT_EQ(tester.GetPathsCovered(), art::mips64::kLoadConst64PathAllPaths);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFarthestNearLabelAddress) {
- mips64::Mips64Label label;
- __ LoadLabelAddress(mips64::V0, &label);
- constexpr uint32_t kAdduCount = 0x3FFDE;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- "lapc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n";
- DriverStr(expected, "LoadFarthestNearLabelAddress");
- EXPECT_EQ(__ GetLabelLocation(&label), (1 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadNearestFarLabelAddress) {
- mips64::Mips64Label label;
- __ LoadLabelAddress(mips64::V0, &label);
- constexpr uint32_t kAdduCount = 0x3FFDF;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- __ Bind(&label);
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "daddiu $v0, $at, %lo(2f - 1b)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n";
- DriverStr(expected, "LoadNearestFarLabelAddress");
- EXPECT_EQ(__ GetLabelLocation(&label), (2 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFarthestNearLiteral) {
- mips64::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips64::V0, mips64::kLoadWord, literal);
- constexpr uint32_t kAdduCount = 0x3FFDE;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "lwpc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadFarthestNearLiteral");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (1 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadNearestFarLiteral) {
- mips64::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips64::V0, mips64::kLoadWord, literal);
- constexpr uint32_t kAdduCount = 0x3FFDF;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "lw $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadNearestFarLiteral");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (2 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFarthestNearLiteralUnsigned) {
- mips64::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips64::V0, mips64::kLoadUnsignedWord, literal);
- constexpr uint32_t kAdduCount = 0x3FFDE;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "lwupc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadFarthestNearLiteralUnsigned");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (1 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadNearestFarLiteralUnsigned) {
- mips64::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
- __ LoadLiteral(mips64::V0, mips64::kLoadUnsignedWord, literal);
- constexpr uint32_t kAdduCount = 0x3FFDF;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "lwu $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".word 0x12345678\n";
- DriverStr(expected, "LoadNearestFarLiteralUnsigned");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (2 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadFarthestNearLiteralLong) {
- mips64::Literal* literal = __ NewLiteral<uint64_t>(UINT64_C(0x0123456789ABCDEF));
- __ LoadLiteral(mips64::V0, mips64::kLoadDoubleword, literal);
- constexpr uint32_t kAdduCount = 0x3FFDD;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "ldpc $v0, 1f\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "1:\n"
- ".dword 0x0123456789ABCDEF\n";
- DriverStr(expected, "LoadFarthestNearLiteralLong");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (1 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LoadNearestFarLiteralLong) {
- mips64::Literal* literal = __ NewLiteral<uint64_t>(UINT64_C(0x0123456789ABCDEF));
- __ LoadLiteral(mips64::V0, mips64::kLoadDoubleword, literal);
- constexpr uint32_t kAdduCount = 0x3FFDE;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(2f - 1b)\n"
- "ld $v0, %lo(2f - 1b)($at)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "2:\n"
- ".dword 0x0123456789ABCDEF\n";
- DriverStr(expected, "LoadNearestFarLiteralLong");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (2 + kAdduCount) * 4);
-}
-
-TEST_F(AssemblerMIPS64Test, LongLiteralAlignmentNop) {
- mips64::Literal* literal1 = __ NewLiteral<uint64_t>(UINT64_C(0x0123456789ABCDEF));
- mips64::Literal* literal2 = __ NewLiteral<uint64_t>(UINT64_C(0x5555555555555555));
- mips64::Literal* literal3 = __ NewLiteral<uint64_t>(UINT64_C(0xAAAAAAAAAAAAAAAA));
- __ LoadLiteral(mips64::A1, mips64::kLoadDoubleword, literal1);
- __ LoadLiteral(mips64::A2, mips64::kLoadDoubleword, literal2);
- __ LoadLiteral(mips64::A3, mips64::kLoadDoubleword, literal3);
- __ LoadLabelAddress(mips64::V0, literal1->GetLabel());
- __ LoadLabelAddress(mips64::V1, literal2->GetLabel());
- // A nop will be inserted here before the 64-bit literals.
-
- std::string expected =
- "ldpc $a1, 1f\n"
- // The GNU assembler incorrectly requires the ldpc instruction to be located
- // at an address that's a multiple of 8. TODO: Remove this workaround if/when
- // the assembler is fixed.
- // "ldpc $a2, 2f\n"
- ".word 0xECD80004\n"
- "ldpc $a3, 3f\n"
- "lapc $v0, 1f\n"
- "lapc $v1, 2f\n"
- "nop\n"
- "1:\n"
- ".dword 0x0123456789ABCDEF\n"
- "2:\n"
- ".dword 0x5555555555555555\n"
- "3:\n"
- ".dword 0xAAAAAAAAAAAAAAAA\n";
- DriverStr(expected, "LongLiteralAlignmentNop");
- EXPECT_EQ(__ GetLabelLocation(literal1->GetLabel()), 6 * 4u);
- EXPECT_EQ(__ GetLabelLocation(literal2->GetLabel()), 8 * 4u);
- EXPECT_EQ(__ GetLabelLocation(literal3->GetLabel()), 10 * 4u);
-}
-
-TEST_F(AssemblerMIPS64Test, LongLiteralAlignmentNoNop) {
- mips64::Literal* literal1 = __ NewLiteral<uint64_t>(UINT64_C(0x0123456789ABCDEF));
- mips64::Literal* literal2 = __ NewLiteral<uint64_t>(UINT64_C(0x5555555555555555));
- __ LoadLiteral(mips64::A1, mips64::kLoadDoubleword, literal1);
- __ LoadLiteral(mips64::A2, mips64::kLoadDoubleword, literal2);
- __ LoadLabelAddress(mips64::V0, literal1->GetLabel());
- __ LoadLabelAddress(mips64::V1, literal2->GetLabel());
-
- std::string expected =
- "ldpc $a1, 1f\n"
- // The GNU assembler incorrectly requires the ldpc instruction to be located
- // at an address that's a multiple of 8. TODO: Remove this workaround if/when
- // the assembler is fixed.
- // "ldpc $a2, 2f\n"
- ".word 0xECD80003\n"
- "lapc $v0, 1f\n"
- "lapc $v1, 2f\n"
- "1:\n"
- ".dword 0x0123456789ABCDEF\n"
- "2:\n"
- ".dword 0x5555555555555555\n";
- DriverStr(expected, "LongLiteralAlignmentNoNop");
- EXPECT_EQ(__ GetLabelLocation(literal1->GetLabel()), 4 * 4u);
- EXPECT_EQ(__ GetLabelLocation(literal2->GetLabel()), 6 * 4u);
-}
-
-TEST_F(AssemblerMIPS64Test, FarLongLiteralAlignmentNop) {
- mips64::Literal* literal = __ NewLiteral<uint64_t>(UINT64_C(0x0123456789ABCDEF));
- __ LoadLiteral(mips64::V0, mips64::kLoadDoubleword, literal);
- __ LoadLabelAddress(mips64::V1, literal->GetLabel());
- constexpr uint32_t kAdduCount = 0x3FFDF;
- for (uint32_t i = 0; i != kAdduCount; ++i) {
- __ Addu(mips64::ZERO, mips64::ZERO, mips64::ZERO);
- }
- // A nop will be inserted here before the 64-bit literal.
-
- std::string expected =
- "1:\n"
- "auipc $at, %hi(3f - 1b)\n"
- "ld $v0, %lo(3f - 1b)($at)\n"
- "2:\n"
- "auipc $at, %hi(3f - 2b)\n"
- "daddiu $v1, $at, %lo(3f - 2b)\n" +
- RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
- "nop\n"
- "3:\n"
- ".dword 0x0123456789ABCDEF\n";
- DriverStr(expected, "FarLongLiteralAlignmentNop");
- EXPECT_EQ(__ GetLabelLocation(literal->GetLabel()), (5 + kAdduCount) * 4);
-}
-
-// MSA instructions.
-
-TEST_F(AssemblerMIPS64Test, AndV) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::AndV, "and.v ${reg1}, ${reg2}, ${reg3}"), "and.v");
-}
-
-TEST_F(AssemblerMIPS64Test, OrV) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::OrV, "or.v ${reg1}, ${reg2}, ${reg3}"), "or.v");
-}
-
-TEST_F(AssemblerMIPS64Test, NorV) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::NorV, "nor.v ${reg1}, ${reg2}, ${reg3}"), "nor.v");
-}
-
-TEST_F(AssemblerMIPS64Test, XorV) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::XorV, "xor.v ${reg1}, ${reg2}, ${reg3}"), "xor.v");
-}
-
-TEST_F(AssemblerMIPS64Test, AddvB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::AddvB, "addv.b ${reg1}, ${reg2}, ${reg3}"),
- "addv.b");
-}
-
-TEST_F(AssemblerMIPS64Test, AddvH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::AddvH, "addv.h ${reg1}, ${reg2}, ${reg3}"),
- "addv.h");
-}
-
-TEST_F(AssemblerMIPS64Test, AddvW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::AddvW, "addv.w ${reg1}, ${reg2}, ${reg3}"),
- "addv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, AddvD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::AddvD, "addv.d ${reg1}, ${reg2}, ${reg3}"),
- "addv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SubvB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SubvB, "subv.b ${reg1}, ${reg2}, ${reg3}"),
- "subv.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SubvH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SubvH, "subv.h ${reg1}, ${reg2}, ${reg3}"),
- "subv.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SubvW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SubvW, "subv.w ${reg1}, ${reg2}, ${reg3}"),
- "subv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SubvD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SubvD, "subv.d ${reg1}, ${reg2}, ${reg3}"),
- "subv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_sB, "asub_s.b ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_sH, "asub_s.h ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_sW, "asub_s.w ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_sD, "asub_s.d ${reg1}, ${reg2}, ${reg3}"),
- "asub_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_uB, "asub_u.b ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_uH, "asub_u.h ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_uW, "asub_u.w ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Asub_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Asub_uD, "asub_u.d ${reg1}, ${reg2}, ${reg3}"),
- "asub_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MulvB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MulvB, "mulv.b ${reg1}, ${reg2}, ${reg3}"),
- "mulv.b");
-}
-
-TEST_F(AssemblerMIPS64Test, MulvH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MulvH, "mulv.h ${reg1}, ${reg2}, ${reg3}"),
- "mulv.h");
-}
-
-TEST_F(AssemblerMIPS64Test, MulvW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MulvW, "mulv.w ${reg1}, ${reg2}, ${reg3}"),
- "mulv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, MulvD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MulvD, "mulv.d ${reg1}, ${reg2}, ${reg3}"),
- "mulv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_sB, "div_s.b ${reg1}, ${reg2}, ${reg3}"),
- "div_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_sH, "div_s.h ${reg1}, ${reg2}, ${reg3}"),
- "div_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_sW, "div_s.w ${reg1}, ${reg2}, ${reg3}"),
- "div_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_sD, "div_s.d ${reg1}, ${reg2}, ${reg3}"),
- "div_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_uB, "div_u.b ${reg1}, ${reg2}, ${reg3}"),
- "div_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_uH, "div_u.h ${reg1}, ${reg2}, ${reg3}"),
- "div_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_uW, "div_u.w ${reg1}, ${reg2}, ${reg3}"),
- "div_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Div_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Div_uD, "div_u.d ${reg1}, ${reg2}, ${reg3}"),
- "div_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_sB, "mod_s.b ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_sH, "mod_s.h ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_sW, "mod_s.w ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_sD, "mod_s.d ${reg1}, ${reg2}, ${reg3}"),
- "mod_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_uB, "mod_u.b ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_uH, "mod_u.h ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_uW, "mod_u.w ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Mod_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Mod_uD, "mod_u.d ${reg1}, ${reg2}, ${reg3}"),
- "mod_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Add_aB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Add_aB, "add_a.b ${reg1}, ${reg2}, ${reg3}"),
- "add_a.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Add_aH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Add_aH, "add_a.h ${reg1}, ${reg2}, ${reg3}"),
- "add_a.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Add_aW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Add_aW, "add_a.w ${reg1}, ${reg2}, ${reg3}"),
- "add_a.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Add_aD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Add_aD, "add_a.d ${reg1}, ${reg2}, ${reg3}"),
- "add_a.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_sB, "ave_s.b ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_sH, "ave_s.h ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_sW, "ave_s.w ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_sD, "ave_s.d ${reg1}, ${reg2}, ${reg3}"),
- "ave_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_uB, "ave_u.b ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_uH, "ave_u.h ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_uW, "ave_u.w ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Ave_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Ave_uD, "ave_u.d ${reg1}, ${reg2}, ${reg3}"),
- "ave_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_sB, "aver_s.b ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_sH, "aver_s.h ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_sW, "aver_s.w ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_sD, "aver_s.d ${reg1}, ${reg2}, ${reg3}"),
- "aver_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_uB, "aver_u.b ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_uH, "aver_u.h ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_uW, "aver_u.w ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Aver_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Aver_uD, "aver_u.d ${reg1}, ${reg2}, ${reg3}"),
- "aver_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_sB, "max_s.b ${reg1}, ${reg2}, ${reg3}"),
- "max_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_sH, "max_s.h ${reg1}, ${reg2}, ${reg3}"),
- "max_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_sW, "max_s.w ${reg1}, ${reg2}, ${reg3}"),
- "max_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_sD, "max_s.d ${reg1}, ${reg2}, ${reg3}"),
- "max_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_uB, "max_u.b ${reg1}, ${reg2}, ${reg3}"),
- "max_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_uH, "max_u.h ${reg1}, ${reg2}, ${reg3}"),
- "max_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_uW, "max_u.w ${reg1}, ${reg2}, ${reg3}"),
- "max_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Max_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Max_uD, "max_u.d ${reg1}, ${reg2}, ${reg3}"),
- "max_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_sB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_sB, "min_s.b ${reg1}, ${reg2}, ${reg3}"),
- "min_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_sH, "min_s.h ${reg1}, ${reg2}, ${reg3}"),
- "min_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_sW, "min_s.w ${reg1}, ${reg2}, ${reg3}"),
- "min_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_sD, "min_s.d ${reg1}, ${reg2}, ${reg3}"),
- "min_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_uB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_uB, "min_u.b ${reg1}, ${reg2}, ${reg3}"),
- "min_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_uH, "min_u.h ${reg1}, ${reg2}, ${reg3}"),
- "min_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_uW, "min_u.w ${reg1}, ${reg2}, ${reg3}"),
- "min_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Min_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Min_uD, "min_u.d ${reg1}, ${reg2}, ${reg3}"),
- "min_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FaddW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FaddW, "fadd.w ${reg1}, ${reg2}, ${reg3}"),
- "fadd.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FaddD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FaddD, "fadd.d ${reg1}, ${reg2}, ${reg3}"),
- "fadd.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FsubW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FsubW, "fsub.w ${reg1}, ${reg2}, ${reg3}"),
- "fsub.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FsubD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FsubD, "fsub.d ${reg1}, ${reg2}, ${reg3}"),
- "fsub.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FmulW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmulW, "fmul.w ${reg1}, ${reg2}, ${reg3}"),
- "fmul.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FmulD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmulD, "fmul.d ${reg1}, ${reg2}, ${reg3}"),
- "fmul.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FdivW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FdivW, "fdiv.w ${reg1}, ${reg2}, ${reg3}"),
- "fdiv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FdivD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FdivD, "fdiv.d ${reg1}, ${reg2}, ${reg3}"),
- "fdiv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FmaxW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmaxW, "fmax.w ${reg1}, ${reg2}, ${reg3}"),
- "fmax.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FmaxD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmaxD, "fmax.d ${reg1}, ${reg2}, ${reg3}"),
- "fmax.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FminW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FminW, "fmin.w ${reg1}, ${reg2}, ${reg3}"),
- "fmin.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FminD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FminD, "fmin.d ${reg1}, ${reg2}, ${reg3}"),
- "fmin.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Ffint_sW) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::Ffint_sW, "ffint_s.w ${reg1}, ${reg2}"),
- "ffint_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Ffint_sD) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::Ffint_sD, "ffint_s.d ${reg1}, ${reg2}"),
- "ffint_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Ftint_sW) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::Ftint_sW, "ftint_s.w ${reg1}, ${reg2}"),
- "ftint_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Ftint_sD) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::Ftint_sD, "ftint_s.d ${reg1}, ${reg2}"),
- "ftint_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SllB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SllB, "sll.b ${reg1}, ${reg2}, ${reg3}"), "sll.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SllH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SllH, "sll.h ${reg1}, ${reg2}, ${reg3}"), "sll.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SllW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SllW, "sll.w ${reg1}, ${reg2}, ${reg3}"), "sll.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SllD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SllD, "sll.d ${reg1}, ${reg2}, ${reg3}"), "sll.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SraB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SraB, "sra.b ${reg1}, ${reg2}, ${reg3}"), "sra.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SraH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SraH, "sra.h ${reg1}, ${reg2}, ${reg3}"), "sra.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SraW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SraW, "sra.w ${reg1}, ${reg2}, ${reg3}"), "sra.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SraD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SraD, "sra.d ${reg1}, ${reg2}, ${reg3}"), "sra.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SrlB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SrlB, "srl.b ${reg1}, ${reg2}, ${reg3}"), "srl.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SrlH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SrlH, "srl.h ${reg1}, ${reg2}, ${reg3}"), "srl.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SrlW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SrlW, "srl.w ${reg1}, ${reg2}, ${reg3}"), "srl.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SrlD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::SrlD, "srl.d ${reg1}, ${reg2}, ${reg3}"), "srl.d");
-}
-
-TEST_F(AssemblerMIPS64Test, SlliB) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SlliB, 3, "slli.b ${reg1}, ${reg2}, {imm}"),
- "slli.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SlliH) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SlliH, 4, "slli.h ${reg1}, ${reg2}, {imm}"),
- "slli.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SlliW) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SlliW, 5, "slli.w ${reg1}, ${reg2}, {imm}"),
- "slli.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SlliD) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SlliD, 6, "slli.d ${reg1}, ${reg2}, {imm}"),
- "slli.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MoveV) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::MoveV, "move.v ${reg1}, ${reg2}"), "move.v");
-}
-
-TEST_F(AssemblerMIPS64Test, SplatiB) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SplatiB, 4, "splati.b ${reg1}, ${reg2}[{imm}]"),
- "splati.b");
-}
-
-TEST_F(AssemblerMIPS64Test, SplatiH) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SplatiH, 3, "splati.h ${reg1}, ${reg2}[{imm}]"),
- "splati.h");
-}
-
-TEST_F(AssemblerMIPS64Test, SplatiW) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SplatiW, 2, "splati.w ${reg1}, ${reg2}[{imm}]"),
- "splati.w");
-}
-
-TEST_F(AssemblerMIPS64Test, SplatiD) {
- DriverStr(RepeatVVIb(&mips64::Mips64Assembler::SplatiD, 1, "splati.d ${reg1}, ${reg2}[{imm}]"),
- "splati.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_sB) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_sB, 4, "copy_s.b ${reg1}, ${reg2}[{imm}]"),
- "copy_s.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_sH) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_sH, 3, "copy_s.h ${reg1}, ${reg2}[{imm}]"),
- "copy_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_sW) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_sW, 2, "copy_s.w ${reg1}, ${reg2}[{imm}]"),
- "copy_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_sD) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_sD, 1, "copy_s.d ${reg1}, ${reg2}[{imm}]"),
- "copy_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_uB) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_uB, 4, "copy_u.b ${reg1}, ${reg2}[{imm}]"),
- "copy_u.b");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_uH) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_uH, 3, "copy_u.h ${reg1}, ${reg2}[{imm}]"),
- "copy_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Copy_uW) {
- DriverStr(RepeatRVIb(&mips64::Mips64Assembler::Copy_uW, 2, "copy_u.w ${reg1}, ${reg2}[{imm}]"),
- "copy_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, InsertB) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::InsertB, 4, "insert.b ${reg1}[{imm}], ${reg2}"),
- "insert.b");
-}
-
-TEST_F(AssemblerMIPS64Test, InsertH) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::InsertH, 3, "insert.h ${reg1}[{imm}], ${reg2}"),
- "insert.h");
-}
-
-TEST_F(AssemblerMIPS64Test, InsertW) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::InsertW, 2, "insert.w ${reg1}[{imm}], ${reg2}"),
- "insert.w");
-}
-
-TEST_F(AssemblerMIPS64Test, InsertD) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::InsertD, 1, "insert.d ${reg1}[{imm}], ${reg2}"),
- "insert.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FillB) {
- DriverStr(RepeatVR(&mips64::Mips64Assembler::FillB, "fill.b ${reg1}, ${reg2}"), "fill.b");
-}
-
-TEST_F(AssemblerMIPS64Test, FillH) {
- DriverStr(RepeatVR(&mips64::Mips64Assembler::FillH, "fill.h ${reg1}, ${reg2}"), "fill.h");
-}
-
-TEST_F(AssemblerMIPS64Test, FillW) {
- DriverStr(RepeatVR(&mips64::Mips64Assembler::FillW, "fill.w ${reg1}, ${reg2}"), "fill.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FillD) {
- DriverStr(RepeatVR(&mips64::Mips64Assembler::FillD, "fill.d ${reg1}, ${reg2}"), "fill.d");
-}
-
-TEST_F(AssemblerMIPS64Test, PcntB) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::PcntB, "pcnt.b ${reg1}, ${reg2}"), "pcnt.b");
-}
-
-TEST_F(AssemblerMIPS64Test, PcntH) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::PcntH, "pcnt.h ${reg1}, ${reg2}"), "pcnt.h");
-}
-
-TEST_F(AssemblerMIPS64Test, PcntW) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::PcntW, "pcnt.w ${reg1}, ${reg2}"), "pcnt.w");
-}
-
-TEST_F(AssemblerMIPS64Test, PcntD) {
- DriverStr(RepeatVV(&mips64::Mips64Assembler::PcntD, "pcnt.d ${reg1}, ${reg2}"), "pcnt.d");
-}
-
-TEST_F(AssemblerMIPS64Test, LdiB) {
- DriverStr(RepeatVIb(&mips64::Mips64Assembler::LdiB, -8, "ldi.b ${reg}, {imm}"), "ldi.b");
-}
-
-TEST_F(AssemblerMIPS64Test, LdiH) {
- DriverStr(RepeatVIb(&mips64::Mips64Assembler::LdiH, -10, "ldi.h ${reg}, {imm}"), "ldi.h");
-}
-
-TEST_F(AssemblerMIPS64Test, LdiW) {
- DriverStr(RepeatVIb(&mips64::Mips64Assembler::LdiW, -10, "ldi.w ${reg}, {imm}"), "ldi.w");
-}
-
-TEST_F(AssemblerMIPS64Test, LdiD) {
- DriverStr(RepeatVIb(&mips64::Mips64Assembler::LdiD, -10, "ldi.d ${reg}, {imm}"), "ldi.d");
-}
-
-TEST_F(AssemblerMIPS64Test, LdB) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::LdB, -10, "ld.b ${reg1}, {imm}(${reg2})"), "ld.b");
-}
-
-TEST_F(AssemblerMIPS64Test, LdH) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::LdH, -10, "ld.h ${reg1}, {imm}(${reg2})", 0, 2),
- "ld.h");
-}
-
-TEST_F(AssemblerMIPS64Test, LdW) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::LdW, -10, "ld.w ${reg1}, {imm}(${reg2})", 0, 4),
- "ld.w");
-}
-
-TEST_F(AssemblerMIPS64Test, LdD) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::LdD, -10, "ld.d ${reg1}, {imm}(${reg2})", 0, 8),
- "ld.d");
-}
-
-TEST_F(AssemblerMIPS64Test, StB) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::StB, -10, "st.b ${reg1}, {imm}(${reg2})"), "st.b");
-}
-
-TEST_F(AssemblerMIPS64Test, StH) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::StH, -10, "st.h ${reg1}, {imm}(${reg2})", 0, 2),
- "st.h");
-}
-
-TEST_F(AssemblerMIPS64Test, StW) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::StW, -10, "st.w ${reg1}, {imm}(${reg2})", 0, 4),
- "st.w");
-}
-
-TEST_F(AssemblerMIPS64Test, StD) {
- DriverStr(RepeatVRIb(&mips64::Mips64Assembler::StD, -10, "st.d ${reg1}, {imm}(${reg2})", 0, 8),
- "st.d");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvlB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvlB, "ilvl.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvl.b");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvlH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvlH, "ilvl.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvl.h");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvlW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvlW, "ilvl.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvl.w");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvlD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvlD, "ilvl.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvl.d");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvrB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvrB, "ilvr.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvr.b");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvrH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvrH, "ilvr.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvr.h");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvrW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvrW, "ilvr.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvr.w");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvrD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvrD, "ilvr.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvr.d");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvevB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvevB, "ilvev.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.b");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvevH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvevH, "ilvev.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.h");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvevW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvevW, "ilvev.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.w");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvevD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvevD, "ilvev.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvev.d");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvodB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvodB, "ilvod.b ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.b");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvodH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvodH, "ilvod.h ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.h");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvodW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvodW, "ilvod.w ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.w");
-}
-
-TEST_F(AssemblerMIPS64Test, IlvodD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::IlvodD, "ilvod.d ${reg1}, ${reg2}, ${reg3}"),
- "ilvod.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MaddvB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MaddvB, "maddv.b ${reg1}, ${reg2}, ${reg3}"),
- "maddv.b");
-}
-
-TEST_F(AssemblerMIPS64Test, MaddvH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MaddvH, "maddv.h ${reg1}, ${reg2}, ${reg3}"),
- "maddv.h");
-}
-
-TEST_F(AssemblerMIPS64Test, MaddvW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MaddvW, "maddv.w ${reg1}, ${reg2}, ${reg3}"),
- "maddv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, MaddvD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MaddvD, "maddv.d ${reg1}, ${reg2}, ${reg3}"),
- "maddv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_sH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_sH, "hadd_s.h ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_sW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_sW, "hadd_s.w ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_sD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_sD, "hadd_s.d ${reg1}, ${reg2}, ${reg3}"),
- "hadd_s.d");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_uH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_uH, "hadd_u.h ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.h");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_uW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_uW, "hadd_u.w ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.w");
-}
-
-TEST_F(AssemblerMIPS64Test, Hadd_uD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::Hadd_uD, "hadd_u.d ${reg1}, ${reg2}, ${reg3}"),
- "hadd_u.d");
-}
-
-TEST_F(AssemblerMIPS64Test, MsubvB) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MsubvB, "msubv.b ${reg1}, ${reg2}, ${reg3}"),
- "msubv.b");
-}
-
-TEST_F(AssemblerMIPS64Test, MsubvH) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MsubvH, "msubv.h ${reg1}, ${reg2}, ${reg3}"),
- "msubv.h");
-}
-
-TEST_F(AssemblerMIPS64Test, MsubvW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MsubvW, "msubv.w ${reg1}, ${reg2}, ${reg3}"),
- "msubv.w");
-}
-
-TEST_F(AssemblerMIPS64Test, MsubvD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::MsubvD, "msubv.d ${reg1}, ${reg2}, ${reg3}"),
- "msubv.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FmaddW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmaddW, "fmadd.w ${reg1}, ${reg2}, ${reg3}"),
- "fmadd.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FmaddD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmaddD, "fmadd.d ${reg1}, ${reg2}, ${reg3}"),
- "fmadd.d");
-}
-
-TEST_F(AssemblerMIPS64Test, FmsubW) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmsubW, "fmsub.w ${reg1}, ${reg2}, ${reg3}"),
- "fmsub.w");
-}
-
-TEST_F(AssemblerMIPS64Test, FmsubD) {
- DriverStr(RepeatVVV(&mips64::Mips64Assembler::FmsubD, "fmsub.d ${reg1}, ${reg2}, ${reg3}"),
- "fmsub.d");
-}
-
-#undef __
-
-} // namespace art
diff --git a/compiler/utils/mips64/constants_mips64.h b/compiler/utils/mips64/constants_mips64.h
deleted file mode 100644
index 41eb77c..0000000
--- a/compiler/utils/mips64/constants_mips64.h
+++ /dev/null
@@ -1,115 +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.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS64_CONSTANTS_MIPS64_H_
-#define ART_COMPILER_UTILS_MIPS64_CONSTANTS_MIPS64_H_
-
-#include <iosfwd>
-
-#include <android-base/logging.h>
-
-#include "arch/mips64/registers_mips64.h"
-#include "base/globals.h"
-#include "base/macros.h"
-
-namespace art {
-namespace mips64 {
-
-// Constants used for the decoding or encoding of the individual fields of instructions.
-enum InstructionFields {
- kOpcodeShift = 26,
- kOpcodeBits = 6,
- kRsShift = 21,
- kRsBits = 5,
- kRtShift = 16,
- kRtBits = 5,
- kRdShift = 11,
- kRdBits = 5,
- kShamtShift = 6,
- kShamtBits = 5,
- kFunctShift = 0,
- kFunctBits = 6,
-
- kFmtShift = 21,
- kFmtBits = 5,
- kFtShift = 16,
- kFtBits = 5,
- kFsShift = 11,
- kFsBits = 5,
- kFdShift = 6,
- kFdBits = 5,
-
- kMsaOperationShift = 23,
- kMsaELMOperationShift = 22,
- kMsa2ROperationShift = 18,
- kMsa2RFOperationShift = 17,
- kDfShift = 21,
- kDfMShift = 16,
- kDf2RShift = 16,
- kDfNShift = 16,
- kWtShift = 16,
- kWtBits = 5,
- kWsShift = 11,
- kWsBits = 5,
- kWdShift = 6,
- kWdBits = 5,
- kS10Shift = 16,
- kI10Shift = 11,
- kS10MinorShift = 2,
-
- kBranchOffsetMask = 0x0000ffff,
- kJumpOffsetMask = 0x03ffffff,
- kMsaMajorOpcode = 0x1e,
- kMsaDfMByteMask = 0x70,
- kMsaDfMHalfwordMask = 0x60,
- kMsaDfMWordMask = 0x40,
- kMsaDfMDoublewordMask = 0x00,
- kMsaDfNByteMask = 0x00,
- kMsaDfNHalfwordMask = 0x20,
- kMsaDfNWordMask = 0x30,
- kMsaDfNDoublewordMask = 0x38,
- kMsaS10Mask = 0x3ff,
-};
-
-enum ScaleFactor {
- TIMES_1 = 0,
- TIMES_2 = 1,
- TIMES_4 = 2,
- TIMES_8 = 3
-};
-
-class Instr {
- public:
- static const uint32_t kBreakPointInstruction = 0x0000000D;
-
- bool IsBreakPoint() {
- return ((*reinterpret_cast<const uint32_t*>(this)) & 0xFC00003F) == kBreakPointInstruction;
- }
-
- // Instructions are read out of a code stream. The only way to get a
- // reference to an instruction is to convert a pointer. There is no way
- // to allocate or create instances of class Instr.
- // Use the At(pc) function to create references to Instr.
- static Instr* At(uintptr_t pc) { return reinterpret_cast<Instr*>(pc); }
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
-};
-
-} // namespace mips64
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS64_CONSTANTS_MIPS64_H_
diff --git a/compiler/utils/mips64/managed_register_mips64.cc b/compiler/utils/mips64/managed_register_mips64.cc
deleted file mode 100644
index 01cb6dd..0000000
--- a/compiler/utils/mips64/managed_register_mips64.cc
+++ /dev/null
@@ -1,57 +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 "managed_register_mips64.h"
-
-#include "base/globals.h"
-
-namespace art {
-namespace mips64 {
-
-bool Mips64ManagedRegister::Overlaps(const Mips64ManagedRegister& other) const {
- if (IsNoRegister() || other.IsNoRegister()) return false;
- CHECK(IsValidManagedRegister());
- CHECK(other.IsValidManagedRegister());
- if (Equals(other)) return true;
- if (IsFpuRegister() && other.IsVectorRegister()) {
- return (AsFpuRegister() == other.AsOverlappingFpuRegister());
- } else if (IsVectorRegister() && other.IsFpuRegister()) {
- return (AsVectorRegister() == other.AsOverlappingVectorRegister());
- }
- return false;
-}
-
-void Mips64ManagedRegister::Print(std::ostream& os) const {
- if (!IsValidManagedRegister()) {
- os << "No Register";
- } else if (IsGpuRegister()) {
- os << "GPU: " << static_cast<int>(AsGpuRegister());
- } else if (IsFpuRegister()) {
- os << "FpuRegister: " << static_cast<int>(AsFpuRegister());
- } else if (IsVectorRegister()) {
- os << "VectorRegister: " << static_cast<int>(AsVectorRegister());
- } else {
- os << "??: " << RegId();
- }
-}
-
-std::ostream& operator<<(std::ostream& os, const Mips64ManagedRegister& reg) {
- reg.Print(os);
- return os;
-}
-
-} // namespace mips64
-} // namespace art
diff --git a/compiler/utils/mips64/managed_register_mips64.h b/compiler/utils/mips64/managed_register_mips64.h
deleted file mode 100644
index 94166d3..0000000
--- a/compiler/utils/mips64/managed_register_mips64.h
+++ /dev/null
@@ -1,163 +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.
- */
-
-#ifndef ART_COMPILER_UTILS_MIPS64_MANAGED_REGISTER_MIPS64_H_
-#define ART_COMPILER_UTILS_MIPS64_MANAGED_REGISTER_MIPS64_H_
-
-#include "constants_mips64.h"
-#include "utils/managed_register.h"
-
-namespace art {
-namespace mips64 {
-
-const int kNumberOfGpuRegIds = kNumberOfGpuRegisters;
-const int kNumberOfGpuAllocIds = kNumberOfGpuRegisters;
-
-const int kNumberOfFpuRegIds = kNumberOfFpuRegisters;
-const int kNumberOfFpuAllocIds = kNumberOfFpuRegisters;
-
-const int kNumberOfVecRegIds = kNumberOfVectorRegisters;
-const int kNumberOfVecAllocIds = kNumberOfVectorRegisters;
-
-const int kNumberOfRegIds = kNumberOfGpuRegIds + kNumberOfFpuRegIds + kNumberOfVecRegIds;
-const int kNumberOfAllocIds = kNumberOfGpuAllocIds + kNumberOfFpuAllocIds + kNumberOfVecAllocIds;
-
-// Register ids map:
-// [0..R[ core registers (enum GpuRegister)
-// [R..F[ floating-point registers (enum FpuRegister)
-// [F..W[ MSA vector registers (enum VectorRegister)
-// where
-// R = kNumberOfGpuRegIds
-// F = R + kNumberOfFpuRegIds
-// W = F + kNumberOfVecRegIds
-
-// An instance of class 'ManagedRegister' represents a single Mips64 register.
-// A register can be one of the following:
-// * core register (enum GpuRegister)
-// * floating-point register (enum FpuRegister)
-// * MSA vector register (enum VectorRegister)
-//
-// 'ManagedRegister::NoRegister()' provides an invalid register.
-// There is a one-to-one mapping between ManagedRegister and register id.
-class Mips64ManagedRegister : public ManagedRegister {
- public:
- constexpr GpuRegister AsGpuRegister() const {
- CHECK(IsGpuRegister());
- return static_cast<GpuRegister>(id_);
- }
-
- constexpr FpuRegister AsFpuRegister() const {
- CHECK(IsFpuRegister());
- return static_cast<FpuRegister>(id_ - kNumberOfGpuRegIds);
- }
-
- constexpr VectorRegister AsVectorRegister() const {
- CHECK(IsVectorRegister());
- return static_cast<VectorRegister>(id_ - (kNumberOfGpuRegIds + kNumberOfFpuRegisters));
- }
-
- constexpr FpuRegister AsOverlappingFpuRegister() const {
- CHECK(IsValidManagedRegister());
- return static_cast<FpuRegister>(AsVectorRegister());
- }
-
- constexpr VectorRegister AsOverlappingVectorRegister() const {
- CHECK(IsValidManagedRegister());
- return static_cast<VectorRegister>(AsFpuRegister());
- }
-
- constexpr bool IsGpuRegister() const {
- CHECK(IsValidManagedRegister());
- return (0 <= id_) && (id_ < kNumberOfGpuRegIds);
- }
-
- constexpr bool IsFpuRegister() const {
- CHECK(IsValidManagedRegister());
- const int test = id_ - kNumberOfGpuRegIds;
- return (0 <= test) && (test < kNumberOfFpuRegIds);
- }
-
- constexpr bool IsVectorRegister() const {
- CHECK(IsValidManagedRegister());
- const int test = id_ - (kNumberOfGpuRegIds + kNumberOfFpuRegIds);
- return (0 <= test) && (test < kNumberOfVecRegIds);
- }
-
- void Print(std::ostream& os) const;
-
- // Returns true if the two managed-registers ('this' and 'other') overlap.
- // Either managed-register may be the NoRegister. If both are the NoRegister
- // then false is returned.
- bool Overlaps(const Mips64ManagedRegister& other) const;
-
- static constexpr Mips64ManagedRegister FromGpuRegister(GpuRegister r) {
- CHECK_NE(r, kNoGpuRegister);
- return FromRegId(r);
- }
-
- static constexpr Mips64ManagedRegister FromFpuRegister(FpuRegister r) {
- CHECK_NE(r, kNoFpuRegister);
- return FromRegId(r + kNumberOfGpuRegIds);
- }
-
- static constexpr Mips64ManagedRegister FromVectorRegister(VectorRegister r) {
- CHECK_NE(r, kNoVectorRegister);
- return FromRegId(r + kNumberOfGpuRegIds + kNumberOfFpuRegIds);
- }
-
- private:
- constexpr bool IsValidManagedRegister() const {
- return (0 <= id_) && (id_ < kNumberOfRegIds);
- }
-
- constexpr int RegId() const {
- CHECK(!IsNoRegister());
- return id_;
- }
-
- int AllocId() const {
- CHECK(IsValidManagedRegister());
- CHECK_LT(id_, kNumberOfAllocIds);
- return id_;
- }
-
- int AllocIdLow() const;
- int AllocIdHigh() const;
-
- friend class ManagedRegister;
-
- explicit constexpr Mips64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
-
- static constexpr Mips64ManagedRegister FromRegId(int reg_id) {
- Mips64ManagedRegister reg(reg_id);
- CHECK(reg.IsValidManagedRegister());
- return reg;
- }
-};
-
-std::ostream& operator<<(std::ostream& os, const Mips64ManagedRegister& reg);
-
-} // namespace mips64
-
-constexpr inline mips64::Mips64ManagedRegister ManagedRegister::AsMips64() const {
- mips64::Mips64ManagedRegister reg(id_);
- CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
- return reg;
-}
-
-} // namespace art
-
-#endif // ART_COMPILER_UTILS_MIPS64_MANAGED_REGISTER_MIPS64_H_
diff --git a/compiler/utils/mips64/managed_register_mips64_test.cc b/compiler/utils/mips64/managed_register_mips64_test.cc
deleted file mode 100644
index bbfeeee..0000000
--- a/compiler/utils/mips64/managed_register_mips64_test.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (C) 2017 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 "managed_register_mips64.h"
-
-#include "base/globals.h"
-#include "gtest/gtest.h"
-
-namespace art {
-namespace mips64 {
-
-TEST(Mips64ManagedRegister, NoRegister) {
- Mips64ManagedRegister reg = ManagedRegister::NoRegister().AsMips64();
- EXPECT_TRUE(reg.IsNoRegister());
- EXPECT_FALSE(reg.Overlaps(reg));
-}
-
-TEST(Mips64ManagedRegister, GpuRegister) {
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromGpuRegister(ZERO);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(ZERO, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(AT);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(AT, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(V0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(V0, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(A0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(A0, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(A7);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(A7, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(T0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(T0, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(T3);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(T3, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(S0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(S0, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(GP);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(GP, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(SP);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(SP, reg.AsGpuRegister());
-
- reg = Mips64ManagedRegister::FromGpuRegister(RA);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_TRUE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_EQ(RA, reg.AsGpuRegister());
-}
-
-TEST(Mips64ManagedRegister, FpuRegister) {
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromFpuRegister(F0);
- Mips64ManagedRegister vreg = Mips64ManagedRegister::FromVectorRegister(W0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_TRUE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(vreg));
- EXPECT_EQ(F0, reg.AsFpuRegister());
- EXPECT_EQ(W0, reg.AsOverlappingVectorRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F1);
- vreg = Mips64ManagedRegister::FromVectorRegister(W1);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_TRUE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(vreg));
- EXPECT_EQ(F1, reg.AsFpuRegister());
- EXPECT_EQ(W1, reg.AsOverlappingVectorRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromFpuRegister(F1)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F20);
- vreg = Mips64ManagedRegister::FromVectorRegister(W20);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_TRUE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(vreg));
- EXPECT_EQ(F20, reg.AsFpuRegister());
- EXPECT_EQ(W20, reg.AsOverlappingVectorRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromFpuRegister(F20)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F31);
- vreg = Mips64ManagedRegister::FromVectorRegister(W31);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_TRUE(reg.IsFpuRegister());
- EXPECT_FALSE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(vreg));
- EXPECT_EQ(F31, reg.AsFpuRegister());
- EXPECT_EQ(W31, reg.AsOverlappingVectorRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromFpuRegister(F31)));
-}
-
-TEST(Mips64ManagedRegister, VectorRegister) {
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromVectorRegister(W0);
- Mips64ManagedRegister freg = Mips64ManagedRegister::FromFpuRegister(F0);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_TRUE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(freg));
- EXPECT_EQ(W0, reg.AsVectorRegister());
- EXPECT_EQ(F0, reg.AsOverlappingFpuRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W2);
- freg = Mips64ManagedRegister::FromFpuRegister(F2);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_TRUE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(freg));
- EXPECT_EQ(W2, reg.AsVectorRegister());
- EXPECT_EQ(F2, reg.AsOverlappingFpuRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromVectorRegister(W2)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W13);
- freg = Mips64ManagedRegister::FromFpuRegister(F13);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_TRUE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(freg));
- EXPECT_EQ(W13, reg.AsVectorRegister());
- EXPECT_EQ(F13, reg.AsOverlappingFpuRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromVectorRegister(W13)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W29);
- freg = Mips64ManagedRegister::FromFpuRegister(F29);
- EXPECT_FALSE(reg.IsNoRegister());
- EXPECT_FALSE(reg.IsGpuRegister());
- EXPECT_FALSE(reg.IsFpuRegister());
- EXPECT_TRUE(reg.IsVectorRegister());
- EXPECT_TRUE(reg.Overlaps(freg));
- EXPECT_EQ(W29, reg.AsVectorRegister());
- EXPECT_EQ(F29, reg.AsOverlappingFpuRegister());
- EXPECT_TRUE(reg.Equals(Mips64ManagedRegister::FromVectorRegister(W29)));
-}
-
-TEST(Mips64ManagedRegister, Equals) {
- ManagedRegister no_reg = ManagedRegister::NoRegister();
- EXPECT_TRUE(no_reg.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(no_reg.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(no_reg.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(no_reg.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_FALSE(no_reg.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(no_reg.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_ZERO = Mips64ManagedRegister::FromGpuRegister(ZERO);
- EXPECT_FALSE(reg_ZERO.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_TRUE(reg_ZERO.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_ZERO.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_ZERO.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_FALSE(reg_ZERO.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_ZERO.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_A1 = Mips64ManagedRegister::FromGpuRegister(A1);
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_TRUE(reg_A1.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_A1.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_S2 = Mips64ManagedRegister::FromGpuRegister(S2);
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::FromGpuRegister(S1)));
- EXPECT_TRUE(reg_S2.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_S2.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_F0 = Mips64ManagedRegister::FromFpuRegister(F0);
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_TRUE(reg_F0.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromFpuRegister(F1)));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg_F0.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_F31 = Mips64ManagedRegister::FromFpuRegister(F31);
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromGpuRegister(S2)));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromFpuRegister(F1)));
- EXPECT_TRUE(reg_F31.Equals(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg_F31.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
-
- Mips64ManagedRegister reg_W0 = Mips64ManagedRegister::FromVectorRegister(W0);
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromGpuRegister(S1)));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_TRUE(reg_W0.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromVectorRegister(W1)));
- EXPECT_FALSE(reg_W0.Equals(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- Mips64ManagedRegister reg_W31 = Mips64ManagedRegister::FromVectorRegister(W31);
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::NoRegister()));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromGpuRegister(A1)));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromGpuRegister(S1)));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg_W31.Equals(Mips64ManagedRegister::FromVectorRegister(W1)));
- EXPECT_TRUE(reg_W31.Equals(Mips64ManagedRegister::FromVectorRegister(W31)));
-}
-
-TEST(Mips64ManagedRegister, Overlaps) {
- Mips64ManagedRegister reg = Mips64ManagedRegister::FromFpuRegister(F0);
- Mips64ManagedRegister reg_o = Mips64ManagedRegister::FromVectorRegister(W0);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(F0, reg_o.AsOverlappingFpuRegister());
- EXPECT_EQ(W0, reg.AsOverlappingVectorRegister());
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F4);
- reg_o = Mips64ManagedRegister::FromVectorRegister(W4);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(F4, reg_o.AsOverlappingFpuRegister());
- EXPECT_EQ(W4, reg.AsOverlappingVectorRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F16);
- reg_o = Mips64ManagedRegister::FromVectorRegister(W16);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(F16, reg_o.AsOverlappingFpuRegister());
- EXPECT_EQ(W16, reg.AsOverlappingVectorRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromFpuRegister(F31);
- reg_o = Mips64ManagedRegister::FromVectorRegister(W31);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(F31, reg_o.AsOverlappingFpuRegister());
- EXPECT_EQ(W31, reg.AsOverlappingVectorRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W0);
- reg_o = Mips64ManagedRegister::FromFpuRegister(F0);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(W0, reg_o.AsOverlappingVectorRegister());
- EXPECT_EQ(F0, reg.AsOverlappingFpuRegister());
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W4);
- reg_o = Mips64ManagedRegister::FromFpuRegister(F4);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(W4, reg_o.AsOverlappingVectorRegister());
- EXPECT_EQ(F4, reg.AsOverlappingFpuRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W16);
- reg_o = Mips64ManagedRegister::FromFpuRegister(F16);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(W16, reg_o.AsOverlappingVectorRegister());
- EXPECT_EQ(F16, reg.AsOverlappingFpuRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromVectorRegister(W31);
- reg_o = Mips64ManagedRegister::FromFpuRegister(F31);
- EXPECT_TRUE(reg.Overlaps(reg_o));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_EQ(W31, reg_o.AsOverlappingVectorRegister());
- EXPECT_EQ(F31, reg.AsOverlappingFpuRegister());
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromGpuRegister(ZERO);
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromGpuRegister(A0);
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromGpuRegister(S0);
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-
- reg = Mips64ManagedRegister::FromGpuRegister(RA);
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(ZERO)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(A0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(S0)));
- EXPECT_TRUE(reg.Overlaps(Mips64ManagedRegister::FromGpuRegister(RA)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromFpuRegister(F31)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W0)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W4)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W16)));
- EXPECT_FALSE(reg.Overlaps(Mips64ManagedRegister::FromVectorRegister(W31)));
-}
-
-} // namespace mips64
-} // namespace art