aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGhost <>2025-07-13 23:03:26 +0200
committercrueter <crueter@eden-emu.dev>2025-07-13 23:03:26 +0200
commitfe4f5a3860fcb2941f2dabe1327c7bd2eb229ca6 (patch)
tree47500285f3dc8304ee0ea887108d891eb4512d7a
parenta0a208db578b8d77579573d437ad251029db1635 (diff)
[dynarmic] lea over mov and other stuff (#24)
Co-authored-by: Esther1024 <danishreyjavik@outlook.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/24 Co-authored-by: Ghost <> Co-committed-by: Ghost <>
-rw-r--r--.gitignore1
-rw-r--r--externals/dynarmic/CMakeLists.txt6
-rw-r--r--externals/dynarmic/src/dynarmic/CMakeLists.txt105
-rw-r--r--externals/dynarmic/src/dynarmic/backend/arm64/abi.h3
-rw-r--r--externals/dynarmic/src/dynarmic/backend/riscv64/code_block.h13
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp47
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp7
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp16
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp9
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp9
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp1
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp80
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h7
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp39
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp3
-rw-r--r--externals/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp2
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h12
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h11
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp48
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp4
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h2
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp6
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp30
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp36
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h31
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/extension.cpp6
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/saturated.cpp9
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp8
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp5
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp8
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp9
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp4
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp4
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp4
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp8
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp254
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h321
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h16
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp61
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp20
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp58
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp10
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp52
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp8
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp98
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_different.cpp54
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_same.cpp140
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp92
-rw-r--r--externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp80
-rw-r--r--externals/dynarmic/src/dynarmic/interface/A32/arch_version.h4
-rw-r--r--externals/dynarmic/src/dynarmic/interface/A32/config.h85
-rw-r--r--externals/dynarmic/src/dynarmic/interface/A64/config.h137
-rw-r--r--externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp2872
-rw-r--r--externals/dynarmic/src/dynarmic/ir/ir_emitter.h3208
54 files changed, 3894 insertions, 4269 deletions
diff --git a/.gitignore b/.gitignore
index 7484a368e6..9aaf549512 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,7 @@ CMakeLists.txt.user*
# Visual Studio CMake settings
CMakeSettings.json
+.cache/
# OSX global filetypes
# Created by Finder or Spotlight in directories for various OS functionality (indexing, etc)
diff --git a/externals/dynarmic/CMakeLists.txt b/externals/dynarmic/CMakeLists.txt
index efb5edf165..3db8d8077b 100644
--- a/externals/dynarmic/CMakeLists.txt
+++ b/externals/dynarmic/CMakeLists.txt
@@ -98,8 +98,7 @@ else()
-Wextra
-Wcast-qual
-pedantic
- -Wno-missing-braces
- -Wstack-usage=4096)
+ -Wno-missing-braces)
if (ARCHITECTURE STREQUAL "x86_64")
list(APPEND DYNARMIC_CXX_FLAGS -mtune=core2)
@@ -123,12 +122,15 @@ else()
# GCC knows that the variable is actually a Reg64. isMEM() will never return true for a
# Reg64, but GCC doesn't know that.
list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds)
+ list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang")
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
# And this in turns limits the size of a std::array.
list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024)
+ # Clang mistakenly blames CMake for using unused arguments during compilation
+ list(APPEND DYNARMIC_CXX_FLAGS -Wno-unused-command-line-argument)
endif()
endif()
diff --git a/externals/dynarmic/src/dynarmic/CMakeLists.txt b/externals/dynarmic/src/dynarmic/CMakeLists.txt
index 9227951fcc..a43c9eae10 100644
--- a/externals/dynarmic/src/dynarmic/CMakeLists.txt
+++ b/externals/dynarmic/src/dynarmic/CMakeLists.txt
@@ -125,52 +125,6 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
frontend/A32/translate/a32_translate.h
frontend/A32/translate/conditional_state.cpp
frontend/A32/translate/conditional_state.h
- frontend/A32/translate/impl/a32_branch.cpp
- frontend/A32/translate/impl/a32_crc32.cpp
- frontend/A32/translate/impl/a32_exception_generating.cpp
- frontend/A32/translate/impl/a32_translate_impl.cpp
- frontend/A32/translate/impl/a32_translate_impl.h
- frontend/A32/translate/impl/asimd_load_store_structures.cpp
- frontend/A32/translate/impl/asimd_misc.cpp
- frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
- frontend/A32/translate/impl/asimd_three_regs.cpp
- frontend/A32/translate/impl/asimd_two_regs_misc.cpp
- frontend/A32/translate/impl/asimd_two_regs_scalar.cpp
- frontend/A32/translate/impl/asimd_two_regs_shift.cpp
- frontend/A32/translate/impl/barrier.cpp
- frontend/A32/translate/impl/coprocessor.cpp
- frontend/A32/translate/impl/data_processing.cpp
- frontend/A32/translate/impl/divide.cpp
- frontend/A32/translate/impl/extension.cpp
- frontend/A32/translate/impl/hint.cpp
- frontend/A32/translate/impl/load_store.cpp
- frontend/A32/translate/impl/misc.cpp
- frontend/A32/translate/impl/multiply.cpp
- frontend/A32/translate/impl/packing.cpp
- frontend/A32/translate/impl/parallel.cpp
- frontend/A32/translate/impl/reversal.cpp
- frontend/A32/translate/impl/saturated.cpp
- frontend/A32/translate/impl/status_register_access.cpp
- frontend/A32/translate/impl/synchronization.cpp
- frontend/A32/translate/impl/thumb16.cpp
- frontend/A32/translate/impl/thumb32_branch.cpp
- frontend/A32/translate/impl/thumb32_control.cpp
- frontend/A32/translate/impl/thumb32_coprocessor.cpp
- frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
- frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
- frontend/A32/translate/impl/thumb32_data_processing_register.cpp
- frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp
- frontend/A32/translate/impl/thumb32_load_byte.cpp
- frontend/A32/translate/impl/thumb32_load_halfword.cpp
- frontend/A32/translate/impl/thumb32_load_store_dual.cpp
- frontend/A32/translate/impl/thumb32_load_store_multiple.cpp
- frontend/A32/translate/impl/thumb32_load_word.cpp
- frontend/A32/translate/impl/thumb32_long_multiply.cpp
- frontend/A32/translate/impl/thumb32_misc.cpp
- frontend/A32/translate/impl/thumb32_multiply.cpp
- frontend/A32/translate/impl/thumb32_parallel.cpp
- frontend/A32/translate/impl/thumb32_store_single_data_item.cpp
- frontend/A32/translate/impl/vfp.cpp
frontend/A32/translate/translate_arm.cpp
frontend/A32/translate/translate_thumb.cpp
interface/A32/a32.h
@@ -194,65 +148,6 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS)
frontend/A64/decoder/a64.inc
frontend/A64/translate/a64_translate.cpp
frontend/A64/translate/a64_translate.h
- frontend/A64/translate/impl/a64_branch.cpp
- frontend/A64/translate/impl/a64_exception_generating.cpp
- frontend/A64/translate/impl/data_processing_addsub.cpp
- frontend/A64/translate/impl/data_processing_bitfield.cpp
- frontend/A64/translate/impl/data_processing_conditional_compare.cpp
- frontend/A64/translate/impl/data_processing_conditional_select.cpp
- frontend/A64/translate/impl/data_processing_crc32.cpp
- frontend/A64/translate/impl/data_processing_logical.cpp
- frontend/A64/translate/impl/data_processing_multiply.cpp
- frontend/A64/translate/impl/data_processing_pcrel.cpp
- frontend/A64/translate/impl/data_processing_register.cpp
- frontend/A64/translate/impl/data_processing_shift.cpp
- frontend/A64/translate/impl/floating_point_compare.cpp
- frontend/A64/translate/impl/floating_point_conditional_compare.cpp
- frontend/A64/translate/impl/floating_point_conditional_select.cpp
- frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp
- frontend/A64/translate/impl/floating_point_conversion_integer.cpp
- frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp
- frontend/A64/translate/impl/floating_point_data_processing_three_register.cpp
- frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp
- frontend/A64/translate/impl/impl.cpp
- frontend/A64/translate/impl/impl.h
- frontend/A64/translate/impl/load_store_exclusive.cpp
- frontend/A64/translate/impl/load_store_load_literal.cpp
- frontend/A64/translate/impl/load_store_multiple_structures.cpp
- frontend/A64/translate/impl/load_store_no_allocate_pair.cpp
- frontend/A64/translate/impl/load_store_register_immediate.cpp
- frontend/A64/translate/impl/load_store_register_pair.cpp
- frontend/A64/translate/impl/load_store_register_register_offset.cpp
- frontend/A64/translate/impl/load_store_register_unprivileged.cpp
- frontend/A64/translate/impl/load_store_single_structure.cpp
- frontend/A64/translate/impl/move_wide.cpp
- frontend/A64/translate/impl/simd_across_lanes.cpp
- frontend/A64/translate/impl/simd_aes.cpp
- frontend/A64/translate/impl/simd_copy.cpp
- frontend/A64/translate/impl/simd_crypto_four_register.cpp
- frontend/A64/translate/impl/simd_crypto_three_register.cpp
- frontend/A64/translate/impl/simd_extract.cpp
- frontend/A64/translate/impl/simd_modified_immediate.cpp
- frontend/A64/translate/impl/simd_permute.cpp
- frontend/A64/translate/impl/simd_scalar_pairwise.cpp
- frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
- frontend/A64/translate/impl/simd_scalar_three_same.cpp
- frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
- frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
- frontend/A64/translate/impl/simd_sha.cpp
- frontend/A64/translate/impl/simd_sha512.cpp
- frontend/A64/translate/impl/simd_shift_by_immediate.cpp
- frontend/A64/translate/impl/simd_table_lookup.cpp
- frontend/A64/translate/impl/simd_three_different.cpp
- frontend/A64/translate/impl/simd_three_same.cpp
- frontend/A64/translate/impl/simd_three_same_extra.cpp
- frontend/A64/translate/impl/simd_two_register_misc.cpp
- frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
- frontend/A64/translate/impl/sys_dc.cpp
- frontend/A64/translate/impl/sys_ic.cpp
- frontend/A64/translate/impl/system.cpp
- frontend/A64/translate/impl/system_flag_format.cpp
- frontend/A64/translate/impl/system_flag_manipulation.cpp
interface/A64/a64.h
interface/A64/config.h
ir/opt/a64_callback_config_pass.cpp
diff --git a/externals/dynarmic/src/dynarmic/backend/arm64/abi.h b/externals/dynarmic/src/dynarmic/backend/arm64/abi.h
index 609b06cd22..d3d5de963a 100644
--- a/externals/dynarmic/src/dynarmic/backend/arm64/abi.h
+++ b/externals/dynarmic/src/dynarmic/backend/arm64/abi.h
@@ -59,13 +59,12 @@ constexpr RegisterList ToRegList(oaknut::Reg reg) {
}
if (reg.index() == 31) {
- throw std::out_of_range("ZR not allowed in reg list");
+ ASSERT_FALSE("ZR not allowed in reg list");
}
if (reg.index() == -1) {
return RegisterList{1} << 31;
}
-
return RegisterList{1} << reg.index();
}
diff --git a/externals/dynarmic/src/dynarmic/backend/riscv64/code_block.h b/externals/dynarmic/src/dynarmic/backend/riscv64/code_block.h
index 6ac014a51a..8f98fdf01f 100644
--- a/externals/dynarmic/src/dynarmic/backend/riscv64/code_block.h
+++ b/externals/dynarmic/src/dynarmic/backend/riscv64/code_block.h
@@ -14,29 +14,26 @@ namespace Dynarmic::Backend::RV64 {
class CodeBlock {
public:
- explicit CodeBlock(std::size_t size)
- : memsize(size) {
+ explicit CodeBlock(std::size_t size) noexcept : memsize(size) {
mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
-
if (mem == nullptr)
- throw std::bad_alloc{};
+ ASSERT_FALSE("out of memory");
}
- ~CodeBlock() {
+ ~CodeBlock() noexcept {
if (mem == nullptr)
return;
-
munmap(mem, memsize);
}
template<typename T>
- T ptr() const {
+ T ptr() const noexcept {
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
return reinterpret_cast<T>(mem);
}
protected:
- u8* mem;
+ u8* mem = nullptr;
size_t memsize = 0;
};
} // namespace Dynarmic::Backend::RV64
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
index ce38a52c73..740625c982 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
@@ -124,35 +124,36 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
EmitCondPrelude(ctx);
- for (auto iter = block.begin(); iter != block.end(); ++iter) {
- IR::Inst* inst = &*iter;
-
- // Call the relevant Emit* member function.
- switch (inst->GetOpcode()) {
-#define OPCODE(name, type, ...) \
- case IR::Opcode::name: \
- A32EmitX64::Emit##name(ctx, inst); \
- break;
-#define A32OPC(name, type, ...) \
- case IR::Opcode::A32##name: \
- A32EmitX64::EmitA32##name(ctx, inst); \
- break;
+ auto const loop_all_inst = [this, &block, &ctx](auto const func) {
+ for (auto iter = block.begin(); iter != block.end(); ++iter) [[likely]] {
+ auto* inst = &*iter;
+ // Call the relevant Emit* member function.
+ switch (inst->GetOpcode()) {
+#define OPCODE(name, type, ...) \
+ case IR::Opcode::name: \
+ A32EmitX64::Emit##name(ctx, inst); \
+ break;
+#define A32OPC(name, type, ...) \
+ case IR::Opcode::A32##name: \
+ A32EmitX64::EmitA32##name(ctx, inst);\
+ break;
#define A64OPC(...)
#include "dynarmic/ir/opcodes.inc"
#undef OPCODE
#undef A32OPC
#undef A64OPC
-
- default:
- ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
- break;
+ default: [[unlikely]] ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
+ }
+ reg_alloc.EndOfAllocScope();
+ func(reg_alloc);
}
-
- reg_alloc.EndOfAllocScope();
-
- if (conf.very_verbose_debugging_output) {
+ };
+ if (!conf.very_verbose_debugging_output) [[likely]] {
+ loop_all_inst([](auto&) { /*noop*/ });
+ } else [[unlikely]] {
+ loop_all_inst([this](auto& reg_alloc) {
EmitVerboseDebuggingOutput(reg_alloc);
- }
+ });
}
reg_alloc.AssertNoMoreUses();
@@ -229,7 +230,7 @@ void A32EmitX64::GenTerminalHandlers() {
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]);
- code.sub(eax, 1);
+ code.dec(eax);
code.and_(eax, u32(A32JitState::RSBPtrMask));
code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
index ad84e0ecc0..4d7bb0d7b1 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
@@ -198,18 +198,19 @@ void A64EmitX64::GenTerminalHandlers() {
code.or_(rbx, rcx);
};
- Xbyak::Label fast_dispatch_cache_miss, rsb_cache_miss;
+ Xbyak::Label fast_dispatch_cache_miss;
+ Xbyak::Label rsb_cache_miss;
code.align();
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
calculate_location_descriptor();
code.mov(eax, dword[r15 + offsetof(A64JitState, rsb_ptr)]);
- code.sub(eax, 1);
+ code.dec(eax);
code.and_(eax, u32(A64JitState::RSBPtrMask));
code.mov(dword[r15 + offsetof(A64JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[r15 + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
- code.jne(rsb_cache_miss);
+ code.jne(rsb_cache_miss, code.T_NEAR);
} else {
code.jne(code.GetReturnFromRunCodeAddress());
}
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp
index 450b16d000..fe7dfa011f 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp
@@ -33,13 +33,13 @@ void A64EmitX64::GenMemory128Accessors() {
#ifdef _WIN32
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code, [&](Xbyak::Reg64 return_value_ptr, [[maybe_unused]] RegList args) {
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
- code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (8 + 16 + ABI_SHADOW_SPACE)]);
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
});
code.movups(xmm1, xword[code.ABI_RETURN]);
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
#else
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCall(code);
if (code.HasHostFeature(HostFeature::SSE41)) {
code.movq(xmm1, code.ABI_RETURN);
@@ -57,13 +57,13 @@ void A64EmitX64::GenMemory128Accessors() {
code.align();
memory_write_128 = code.getCurr<void (*)()>();
#ifdef _WIN32
- code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (8 + 16 + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
code.movaps(xword[code.ABI_PARAM3], xmm1);
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
#else
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
if (code.HasHostFeature(HostFeature::SSE41)) {
code.movq(code.ABI_PARAM3, xmm1);
code.pextrq(code.ABI_PARAM4, xmm1, 1);
@@ -81,7 +81,7 @@ void A64EmitX64::GenMemory128Accessors() {
code.align();
memory_exclusive_write_128 = code.getCurr<void (*)()>();
#ifdef _WIN32
- code.sub(rsp, 8 + 32 + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (8 + 32 + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 16]);
code.movaps(xword[code.ABI_PARAM3], xmm1);
@@ -89,7 +89,7 @@ void A64EmitX64::GenMemory128Accessors() {
Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive128>(conf.callbacks).EmitCall(code);
code.add(rsp, 8 + 32 + ABI_SHADOW_SPACE);
#else
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
if (code.HasHostFeature(HostFeature::SSE41)) {
code.movq(code.ABI_PARAM3, xmm1);
code.pextrq(code.ABI_PARAM4, xmm1, 1);
@@ -131,8 +131,8 @@ void A64EmitX64::GenFastmemFallbacks() {
{64, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive64>(conf.callbacks)},
}};
- for (bool ordered : {false, true}) {
- for (int vaddr_idx : idxes) {
+ for (auto const ordered : {false, true}) {
+ for (auto const vaddr_idx : idxes) {
if (vaddr_idx == 4 || vaddr_idx == 15) {
continue;
}
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/externals/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
index 22d9868fc5..e5fb25573b 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
@@ -63,7 +63,8 @@ public:
uint8_t* alloc(size_t size) override {
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
if (p == nullptr) {
- throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
+ using Xbyak::Error;
+ XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
}
return static_cast<uint8_t*>(p);
}
@@ -95,7 +96,8 @@ public:
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
if (p == MAP_FAILED) {
- throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
+ using Xbyak::Error;
+ XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
}
std::memcpy(p, &size, sizeof(size_t));
return static_cast<uint8_t*>(p) + DYNARMIC_PAGE_SIZE;
@@ -514,7 +516,8 @@ size_t BlockOfCode::GetTotalCodeSize() const {
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
if (size_ + alloc_size >= maxSize_) {
- throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
+ using Xbyak::Error;
+ XBYAK_THROW(Xbyak::ERR_CODE_IS_TOO_BIG);
}
EnsureMemoryCommitted(alloc_size);
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp
index 8bd9102d0d..b9a705813f 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp
@@ -104,7 +104,7 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I
}
void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) {
- code.sub(rsp, sizeof(RegisterData));
+ code.lea(rsp, ptr[rsp - sizeof(RegisterData)]);
code.stmxcsr(dword[rsp + offsetof(RegisterData, mxcsr)]);
for (int i = 0; i < 16; i++) {
if (rsp.getIdx() == i) {
@@ -223,7 +223,7 @@ void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Reg value = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
code.test(value, value);
code.lahf();
- code.mov(al, 0);
+ code.xor_(al, al);
ctx.reg_alloc.DefineValue(inst, nzcv);
}
@@ -270,7 +270,6 @@ void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
code.shr(nzcv, 28);
code.imul(nzcv, nzcv, NZCV::to_x64_multiplier);
code.and_(nzcv, NZCV::x64_mask);
-
ctx.reg_alloc.DefineValue(inst, nzcv);
}
}
@@ -331,10 +330,8 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
code.jle(pass);
break;
default:
- ASSERT_MSG(false, "Unknown cond {}", static_cast<size_t>(cond));
- break;
+ UNREACHABLE();
}
-
return pass;
}
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp
index 98197c2db3..cb1afdec9e 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp
@@ -992,7 +992,6 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
code.seto(overflow);
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
}
-
ctx.reg_alloc.DefineValue(inst, result);
}
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp
index 182c887538..aeb4ceac3c 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp
@@ -33,6 +33,23 @@
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/microinstruction.h"
+#define FCODE(NAME) \
+ [&code](auto... args) { \
+ if constexpr (fsize == 32) { \
+ code.NAME##s(args...); \
+ } else { \
+ code.NAME##d(args...); \
+ } \
+ }
+#define ICODE(NAME) \
+ [&code](auto... args) { \
+ if constexpr (fsize == 32) { \
+ code.NAME##d(args...); \
+ } else { \
+ code.NAME##q(args...); \
+ } \
+ }
+
namespace Dynarmic::Backend::X64 {
using namespace Xbyak::util;
@@ -60,23 +77,6 @@ constexpr u64 f64_max_s32 = 0x41dfffffffc00000u; // 2147483647 as a double
constexpr u64 f64_max_u32 = 0x41efffffffe00000u; // 4294967295 as a double
constexpr u64 f64_max_s64_lim = 0x43e0000000000000u; // 2^63 as a double (actual maximum unrepresentable)
-#define FCODE(NAME) \
- [&code](auto... args) { \
- if constexpr (fsize == 32) { \
- code.NAME##s(args...); \
- } else { \
- code.NAME##d(args...); \
- } \
- }
-#define ICODE(NAME) \
- [&code](auto... args) { \
- if constexpr (fsize == 32) { \
- code.NAME##d(args...); \
- } else { \
- code.NAME##q(args...); \
- } \
- }
-
template<size_t fsize>
void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> to_daz) {
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
@@ -473,7 +473,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
}
template<size_t fsize, bool is_max>
-static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
+static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) noexcept {
using FPT = mcl::unsigned_integer_of_size<fsize>;
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
@@ -701,15 +701,14 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
// x64 rounds before flushing to zero
// AArch64 rounds after flushing to zero
// This difference of behaviour is noticable if something would round to a smallest normalized number
-
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
code.movq(code.ABI_PARAM1, operand1);
code.movq(code.ABI_PARAM2, operand2);
code.movq(code.ABI_PARAM3, operand3);
code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value());
#ifdef _WIN32
- code.sub(rsp, 16 + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (16 + ABI_SHADOW_SPACE)]);
code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]);
code.mov(qword[rsp + ABI_SHADOW_SPACE], rax);
code.CallFunction(fallback_fn);
@@ -735,13 +734,13 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
code.vmovaps(xmm0, code.Const(xword, FP::FPInfo<FPT>::mantissa_msb));
FCODE(ucomis)(operand2, operand3);
- code.jp(has_nan);
+ code.jp(has_nan, code.T_NEAR);
FCODE(ucomis)(operand1, operand1);
- code.jnp(indeterminate);
+ code.jnp(indeterminate, code.T_NEAR);
// AArch64 specifically emits a default NaN for the case when the addend is a QNaN and the two other arguments are {inf, zero}
code.ptest(operand1, xmm0);
- code.jz(op1_snan);
+ code.jz(op1_snan, code.T_NEAR);
FCODE(vmuls)(xmm0, operand2, operand3); // check if {op2, op3} are {inf, zero}/{zero, inf}
FCODE(ucomis)(xmm0, xmm0);
code.jnp(*end);
@@ -753,10 +752,10 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
code.L(has_nan);
FCODE(ucomis)(operand1, operand1);
- code.jnp(op1_done);
+ code.jnp(op1_done, code.T_NEAR);
code.movaps(result, operand1); // this is done because of NaN behavior of vfmadd231s (priority of op2, op3, op1)
code.ptest(operand1, xmm0);
- code.jnz(op1_done);
+ code.jnz(op1_done, code.T_NEAR);
code.L(op1_snan);
code.vorps(result, operand1, xmm0);
code.jmp(*end);
@@ -774,9 +773,9 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
code.L(op2_done);
FCODE(ucomis)(operand3, operand3);
- code.jnp(op3_done);
+ code.jnp(op3_done, code.T_NEAR);
code.ptest(operand3, xmm0);
- code.jnz(op3_done);
+ code.jnz(op3_done, code.T_NEAR);
code.vorps(result, operand3, xmm0);
code.jmp(*end);
code.L(op3_done);
@@ -1019,7 +1018,7 @@ static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst*
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*fallback);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
code.movq(code.ABI_PARAM1, operand1);
code.movq(code.ABI_PARAM2, operand2);
@@ -1204,9 +1203,9 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
}
// a > 0 && a < 0x00800000;
- code.sub(tmp, 1);
+ code.dec(tmp);
code.cmp(tmp, 0x007FFFFF);
- code.jb(fallback);
+ code.jb(fallback, code.T_NEAR); //within -127,128
needs_fallback = true;
}
@@ -1235,17 +1234,17 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
code.ucomisd(value, result);
if (ctx.FPCR().DN()) {
- code.jc(default_nan);
- code.je(zero);
+ code.jc(default_nan, code.T_NEAR);
+ code.je(zero, code.T_NEAR);
} else {
- code.jp(nan);
- code.je(zero);
- code.jc(default_nan);
+ code.jp(nan, code.T_NEAR);
+ code.je(zero, code.T_NEAR);
+ code.jc(default_nan, code.T_NEAR);
}
if (!ctx.FPCR().FZ()) {
needs_fallback = true;
- code.jmp(fallback);
+ code.jmp(fallback, code.T_NEAR);
} else {
// result = 0
code.jmp(*end, code.T_NEAR);
@@ -1278,7 +1277,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
code.L(fallback);
if (needs_fallback) {
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
code.movq(code.ABI_PARAM1, operand);
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
@@ -1361,7 +1360,7 @@ static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst*
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*fallback);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
code.movq(code.ABI_PARAM1, operand1);
code.movq(code.ABI_PARAM2, operand2);
@@ -2132,3 +2131,6 @@ void EmitX64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result);
}
} // namespace Dynarmic::Backend::X64
+
+#undef FCODE
+#undef ICODE
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h
index c99980d617..b25b33101c 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h
@@ -161,8 +161,7 @@ template<>
template<>
[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr<A64EmitContext>(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional<Xbyak::Reg64> tmp) {
- const size_t unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
-
+ auto const unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
if (unused_top_bits == 0) {
return r13 + vaddr;
} else if (ctx.conf.silently_mirror_fastmem) {
@@ -306,7 +305,7 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int
code.L(loop);
code.lock();
code.cmpxchg16b(xword[addr]);
- code.jnz(loop);
+ code.jnz(loop, code.T_NEAR);
break;
}
default:
@@ -373,7 +372,7 @@ void EmitExclusiveTestAndClear(BlockOfCode& code, const UserConfig& conf, Xbyak:
Xbyak::Label ok;
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index)));
code.cmp(qword[pointer], vaddr);
- code.jne(ok);
+ code.jne(ok, code.T_NEAR);
code.mov(qword[pointer], tmp);
code.L(ok);
}
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
index b8aa3eb653..88d0786b03 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
@@ -33,13 +33,6 @@
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/microinstruction.h"
-namespace Dynarmic::Backend::X64 {
-
-using namespace Xbyak::util;
-namespace mp = mcl::mp;
-
-namespace {
-
#define FCODE(NAME) \
[&code](auto... args) { \
if constexpr (fsize == 32) { \
@@ -57,6 +50,13 @@ namespace {
} \
}
+namespace Dynarmic::Backend::X64 {
+
+using namespace Xbyak::util;
+namespace mp = mcl::mp;
+
+namespace {
+
template<typename Lambda>
void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) {
const bool switch_mxcsr = ctx.FPCR(fpcr_controlled) != ctx.FPCR();
@@ -122,11 +122,11 @@ void HandleNaNs(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, std::
const Xbyak::Xmm result = xmms[0];
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
const size_t stack_space = xmms.size() * 16;
- code.sub(rsp, static_cast<u32>(stack_space + ABI_SHADOW_SPACE));
+ code.lea(rsp, ptr[rsp - static_cast<u32>(stack_space + ABI_SHADOW_SPACE)]);
for (size_t i = 0; i < xmms.size(); ++i) {
code.movaps(xword[rsp + ABI_SHADOW_SPACE + i * 16], xmms[i]);
}
@@ -443,7 +443,7 @@ void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak
const u32 fpcr = ctx.FPCR(fpcr_controlled).Value();
constexpr u32 stack_space = 2 * 16;
- code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
code.mov(code.ABI_PARAM3.cvt32(), fpcr);
@@ -479,7 +479,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby
#ifdef _WIN32
constexpr u32 stack_space = 4 * 16;
- code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]);
@@ -488,7 +488,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby
code.mov(qword[rsp + ABI_SHADOW_SPACE + 0], rax);
#else
constexpr u32 stack_space = 3 * 16;
- code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
@@ -536,7 +536,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya
#ifdef _WIN32
constexpr u32 stack_space = 5 * 16;
- code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]);
@@ -546,7 +546,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya
code.mov(qword[rsp + ABI_SHADOW_SPACE + 8], rax);
#else
constexpr u32 stack_space = 4 * 16;
- code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
+ code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
@@ -1371,7 +1371,7 @@ void EmitFPVectorMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*fallback);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
if (needs_rounding_correction && needs_nan_correction) {
EmitFourOpFallbackWithoutRegAlloc<LoadPreviousResult::Yes>(code, ctx, result, xmm_a, xmm_b, xmm_c, EmitFPVectorMulAddFallback<FPT, true, true>, fpcr_controlled);
@@ -1635,7 +1635,7 @@ static void EmitRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*fallback);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
@@ -1812,7 +1812,7 @@ static void EmitRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* ins
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*bad_values);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
EmitTwoOpFallbackWithoutRegAlloc(code, ctx, result, operand, fallback_fn, fpcr_controlled);
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
@@ -1898,7 +1898,7 @@ static void EmitRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
code.L(*fallback);
- code.sub(rsp, 8);
+ code.lea(rsp, ptr[rsp - 8]);
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
@@ -2180,3 +2180,6 @@ void EmitX64::EmitFPVectorToUnsignedFixed64(EmitContext& ctx, IR::Inst* inst) {
}
} // namespace Dynarmic::Backend::X64
+
+#undef FCODE
+#undef ICODE
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp
index fb30549fb0..5bab9c93f4 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp
@@ -338,3 +338,6 @@ void EmitX64::EmitVectorUnsignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst)
}
} // namespace Dynarmic::Backend::X64
+
+#undef FCODE
+#undef ICODE
diff --git a/externals/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp b/externals/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp
index a7f964337a..633e1aac9d 100644
--- a/externals/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp
+++ b/externals/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp
@@ -186,7 +186,7 @@ struct ExceptionHandler::Impl final {
code.cmp(code.rax, static_cast<u32>(code.GetTotalCodeSize()));
code.ja(exception_handler_without_cb);
- code.sub(code.rsp, 8);
+ code.lea(code.rsp, code.ptr[code.rsp - 8]);
code.mov(code.ABI_PARAM1, mcl::bit_cast<u64>(&cb));
code.mov(code.ABI_PARAM2, code.ABI_PARAM3);
code.CallLambda(
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h
index 9fde4f8775..38160f96d4 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h
@@ -15,7 +15,7 @@
namespace Dynarmic::A32 {
-enum class ArchVersion;
+enum class ArchVersion : std::uint8_t;
enum class CoprocReg;
enum class Exception;
enum class ExtReg;
@@ -27,12 +27,11 @@ enum class Reg;
* The user of this class updates `current_location` as appropriate.
*/
class IREmitter : public IR::IREmitter {
+ IR::U64 ImmCurrentLocationDescriptor();
public:
IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version)
: IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {}
-
- LocationDescriptor current_location;
-
+
size_t ArchVersion() const;
u32 PC() const;
@@ -107,10 +106,9 @@ public:
IR::U64 CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm);
void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option);
void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option);
-
-private:
+public:
+ LocationDescriptor current_location;
enum ArchVersion arch_version;
- IR::U64 ImmCurrentLocationDescriptor();
};
} // namespace Dynarmic::A32
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h b/externals/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h
index 16ae52e13a..e4cf4a2865 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h
@@ -33,13 +33,11 @@ inline size_t ToFastLookupIndexArm(u32 instruction) {
} // namespace detail
template<typename V>
-ArmDecodeTable<V> GetArmDecodeTable() {
+constexpr ArmDecodeTable<V> GetArmDecodeTable() {
std::vector<ArmMatcher<V>> list = {
-
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
#include "./arm.inc"
#undef INST
-
};
// If a matcher has more bits in its mask it is more specific, so it should come first.
@@ -62,9 +60,10 @@ ArmDecodeTable<V> GetArmDecodeTable() {
template<typename V>
std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) {
- static const auto table = GetArmDecodeTable<V>();
-
- const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
+ alignas(64) static const auto table = GetArmDecodeTable<V>();
+ const auto matches_instruction = [instruction](const auto& matcher) {
+ return matcher.Matches(instruction);
+ };
const auto& subtable = table[detail::ToFastLookupIndexArm(instruction)];
auto iter = std::find_if(subtable.begin(), subtable.end(), matches_instruction);
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp
index 97a7f11adf..2e69927ace 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp
@@ -25,3 +25,51 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
}
} // namespace Dynarmic::A32
+
+// ls -l | awk '{print "#include \"dynarmic/frontend/A32/translate/impl/" $9 "\""}'
+#include "dynarmic/frontend/A32/translate/impl/a32_branch.cpp"
+#include "dynarmic/frontend/A32/translate/impl/a32_crc32.cpp"
+#include "dynarmic/frontend/A32/translate/impl/a32_exception_generating.cpp"
+#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp"
+//#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_misc.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp"
+#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp"
+#include "dynarmic/frontend/A32/translate/impl/barrier.cpp"
+#include "dynarmic/frontend/A32/translate/impl/coprocessor.cpp"
+#include "dynarmic/frontend/A32/translate/impl/data_processing.cpp"
+#include "dynarmic/frontend/A32/translate/impl/divide.cpp"
+#include "dynarmic/frontend/A32/translate/impl/extension.cpp"
+#include "dynarmic/frontend/A32/translate/impl/hint.cpp"
+#include "dynarmic/frontend/A32/translate/impl/load_store.cpp"
+#include "dynarmic/frontend/A32/translate/impl/misc.cpp"
+#include "dynarmic/frontend/A32/translate/impl/multiply.cpp"
+#include "dynarmic/frontend/A32/translate/impl/packing.cpp"
+#include "dynarmic/frontend/A32/translate/impl/parallel.cpp"
+#include "dynarmic/frontend/A32/translate/impl/reversal.cpp"
+#include "dynarmic/frontend/A32/translate/impl/saturated.cpp"
+#include "dynarmic/frontend/A32/translate/impl/status_register_access.cpp"
+#include "dynarmic/frontend/A32/translate/impl/synchronization.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb16.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_branch.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_control.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_long_multiply.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_misc.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp"
+#include "dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp"
+#include "dynarmic/frontend/A32/translate/impl/vfp.cpp"
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp
index 276f8384e7..c83529f343 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp
@@ -11,6 +11,10 @@
namespace Dynarmic::A32 {
+bool TranslatorVisitor::arm_NOP() {
+ return true;
+}
+
bool TranslatorVisitor::ArmConditionPassed(Cond cond) {
return IsConditionPassed(*this, cond);
}
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
index 44ac24503c..d33069c6e0 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
@@ -258,7 +258,7 @@ struct TranslatorVisitor final {
bool arm_CLZ(Cond cond, Reg d, Reg m);
bool arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
bool arm_MOVW(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
- bool arm_NOP() { return true; }
+ bool arm_NOP();
bool arm_RBIT(Cond cond, Reg d, Reg m);
bool arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp
index a69f39bfb6..da8f43f2fb 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp
@@ -6,6 +6,7 @@
#include <mcl/bit/bit_field.hpp>
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
namespace {
@@ -17,11 +18,6 @@ enum class Comparison {
AbsoluteGT,
};
-enum class AccumulateBehavior {
- None,
- Accumulate,
-};
-
enum class WidenBehaviour {
Second,
Both,
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
index 62b9af55a5..ddae1f420b 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
@@ -8,10 +8,11 @@
#include <mcl/bit/bit_field.hpp>
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
namespace {
-enum class Comparison {
+enum class ComparisonATRM {
EQ,
GE,
GT,
@@ -19,7 +20,7 @@ enum class Comparison {
LT,
};
-bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm, Comparison type) {
+bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm, ComparisonATRM type) {
if (sz == 0b11 || (F && sz != 0b10)) {
return v.UndefinedInstruction();
}
@@ -36,15 +37,15 @@ bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F,
if (F) {
switch (type) {
- case Comparison::EQ:
+ case ComparisonATRM::EQ:
return v.ir.FPVectorEqual(32, reg_m, zero, false);
- case Comparison::GE:
+ case ComparisonATRM::GE:
return v.ir.FPVectorGreaterEqual(32, reg_m, zero, false);
- case Comparison::GT:
+ case ComparisonATRM::GT:
return v.ir.FPVectorGreater(32, reg_m, zero, false);
- case Comparison::LE:
+ case ComparisonATRM::LE:
return v.ir.FPVectorGreaterEqual(32, zero, reg_m, false);
- case Comparison::LT:
+ case ComparisonATRM::LT:
return v.ir.FPVectorGreater(32, zero, reg_m, false);
}
@@ -67,11 +68,6 @@ bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F,
return true;
}
-enum class AccumulateBehavior {
- None,
- Accumulate,
-};
-
bool PairedAddOperation(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool op, bool Q, bool M, size_t Vm, AccumulateBehavior accumulate) {
if (sz == 0b11) {
return v.UndefinedInstruction();
@@ -385,23 +381,23 @@ bool TranslatorVisitor::asimd_VQNEG(bool D, size_t sz, size_t Vd, bool Q, bool M
}
bool TranslatorVisitor::asimd_VCGT_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
- return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, Comparison::GT);
+ return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, ComparisonATRM::GT);
}
bool TranslatorVisitor::asimd_VCGE_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
- return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, Comparison::GE);
+ return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, ComparisonATRM::GE);
}
bool TranslatorVisitor::asimd_VCEQ_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
- return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, Comparison::EQ);
+ return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, ComparisonATRM::EQ);
}
bool TranslatorVisitor::asimd_VCLE_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
- return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, Comparison::LE);
+ return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, ComparisonATRM::LE);
}
bool TranslatorVisitor::asimd_VCLT_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
- return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, Comparison::LT);
+ return CompareWithZero(*this, D, sz, Vd, F, Q, M, Vm, ComparisonATRM::LT);
}
bool TranslatorVisitor::asimd_VABS(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp
index b7300f91e4..cbdfea04ce 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp
@@ -16,7 +16,7 @@ enum class Accumulating {
Accumulate
};
-enum class Rounding {
+enum class RoundingATRS {
None,
Round,
};
@@ -32,7 +32,7 @@ enum class Signedness {
Unsigned
};
-IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round_value, IR::U128 original, IR::U128 shifted) {
+IR::U128 PerformRoundingATRSCorrection(TranslatorVisitor& v, size_t esize, u64 round_value, IR::U128 original, IR::U128 shifted) {
const auto round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value));
const auto round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(original, round_const), round_const);
return v.ir.VectorSub(esize, shifted, round_correction);
@@ -58,7 +58,7 @@ std::pair<size_t, size_t> ElementSizeAndShiftAmount(bool right_shift, bool L, si
}
}
-bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm, Accumulating accumulate, Rounding rounding) {
+bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm, Accumulating accumulate, RoundingATRS RoundingATRS) {
if (!L && mcl::bit::get_bits<3, 5>(imm6) == 0) {
return v.DecodeError();
}
@@ -75,9 +75,9 @@ bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bo
auto result = U ? v.ir.VectorLogicalShiftRight(esize, reg_m, static_cast<u8>(shift_amount))
: v.ir.VectorArithmeticShiftRight(esize, reg_m, static_cast<u8>(shift_amount));
- if (rounding == Rounding::Round) {
+ if (RoundingATRS == RoundingATRS::Round) {
const u64 round_value = 1ULL << (shift_amount - 1);
- result = PerformRoundingCorrection(v, esize, round_value, reg_m, result);
+ result = PerformRoundingATRSCorrection(v, esize, round_value, reg_m, result);
}
if (accumulate == Accumulating::Accumulate) {
@@ -89,7 +89,7 @@ bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bo
return true;
}
-bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, bool M, size_t Vm, Rounding rounding, Narrowing narrowing, Signedness signedness) {
+bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, bool M, size_t Vm, RoundingATRS RoundingATRS, Narrowing narrowing, Signedness signedness) {
if (mcl::bit::get_bits<3, 5>(imm6) == 0) {
return v.DecodeError();
}
@@ -113,9 +113,9 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, b
return v.ir.VectorLogicalShiftRight(source_esize, reg_m, shift_amount);
}();
- if (rounding == Rounding::Round) {
+ if (RoundingATRS == RoundingATRS::Round) {
const u64 round_value = 1ULL << (shift_amount - 1);
- wide_result = PerformRoundingCorrection(v, source_esize, round_value, reg_m, wide_result);
+ wide_result = PerformRoundingATRSCorrection(v, source_esize, round_value, reg_m, wide_result);
}
const auto result = [&] {
@@ -141,22 +141,22 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, b
bool TranslatorVisitor::asimd_SHR(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm) {
return ShiftRight(*this, U, D, imm6, Vd, L, Q, M, Vm,
- Accumulating::None, Rounding::None);
+ Accumulating::None, RoundingATRS::None);
}
bool TranslatorVisitor::asimd_SRA(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm) {
return ShiftRight(*this, U, D, imm6, Vd, L, Q, M, Vm,
- Accumulating::Accumulate, Rounding::None);
+ Accumulating::Accumulate, RoundingATRS::None);
}
bool TranslatorVisitor::asimd_VRSHR(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm) {
return ShiftRight(*this, U, D, imm6, Vd, L, Q, M, Vm,
- Accumulating::None, Rounding::Round);
+ Accumulating::None, RoundingATRS::Round);
}
bool TranslatorVisitor::asimd_VRSRA(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm) {
return ShiftRight(*this, U, D, imm6, Vd, L, Q, M, Vm,
- Accumulating::Accumulate, Rounding::Round);
+ Accumulating::Accumulate, RoundingATRS::Round);
}
bool TranslatorVisitor::asimd_VSRI(bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm) {
@@ -271,32 +271,32 @@ bool TranslatorVisitor::asimd_VSHL(bool D, size_t imm6, size_t Vd, bool L, bool
bool TranslatorVisitor::asimd_VSHRN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::None, Narrowing::Truncation, Signedness::Unsigned);
+ RoundingATRS::None, Narrowing::Truncation, Signedness::Unsigned);
}
bool TranslatorVisitor::asimd_VRSHRN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::Round, Narrowing::Truncation, Signedness::Unsigned);
+ RoundingATRS::Round, Narrowing::Truncation, Signedness::Unsigned);
}
bool TranslatorVisitor::asimd_VQRSHRUN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::Round, Narrowing::SaturateToUnsigned, Signedness::Signed);
+ RoundingATRS::Round, Narrowing::SaturateToUnsigned, Signedness::Signed);
}
bool TranslatorVisitor::asimd_VQSHRUN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::None, Narrowing::SaturateToUnsigned, Signedness::Signed);
+ RoundingATRS::None, Narrowing::SaturateToUnsigned, Signedness::Signed);
}
bool TranslatorVisitor::asimd_VQSHRN(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::None, U ? Narrowing::SaturateToUnsigned : Narrowing::SaturateToSigned, U ? Signedness::Unsigned : Signedness::Signed);
+ RoundingATRS::None, U ? Narrowing::SaturateToUnsigned : Narrowing::SaturateToSigned, U ? Signedness::Unsigned : Signedness::Signed);
}
bool TranslatorVisitor::asimd_VQRSHRN(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
return ShiftRightNarrowing(*this, D, imm6, Vd, M, Vm,
- Rounding::Round, U ? Narrowing::SaturateToUnsigned : Narrowing::SaturateToSigned, U ? Signedness::Unsigned : Signedness::Signed);
+ RoundingATRS::Round, U ? Narrowing::SaturateToUnsigned : Narrowing::SaturateToSigned, U ? Signedness::Unsigned : Signedness::Signed);
}
bool TranslatorVisitor::asimd_VSHLL(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h
new file mode 100644
index 0000000000..39b2c4355c
--- /dev/null
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+
+namespace Dynarmic::A32 {
+
+static inline IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) noexcept {
+ return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
+}
+
+static inline IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) noexcept {
+ return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
+}
+
+static inline IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) noexcept {
+ const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
+ return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
+}
+
+static inline bool ITBlockCheck(const A32::IREmitter& ir) noexcept {
+ return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
+}
+
+using ExtensionFunctionU16 = IR::U32 (IREmitter::*)(const IR::U16&);
+
+enum class AccumulateBehavior {
+ None,
+ Accumulate,
+};
+
+}
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/extension.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/extension.cpp
index 3ee6a670f0..518f8b944e 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/extension.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/extension.cpp
@@ -4,14 +4,10 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
- const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
- return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
-}
-
// SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
bool TranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
if (d == Reg::PC || m == Reg::PC) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/saturated.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/saturated.cpp
index 41db115044..2371e54ae7 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/saturated.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/saturated.cpp
@@ -4,17 +4,10 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
- return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
-}
-
-static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
- return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
-}
-
// Saturation instructions
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
index 1a6767dbee..14a3fef2d1 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
@@ -7,15 +7,9 @@
#include <mcl/bitsizeof.hpp>
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
- return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
-}
-
-static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
- return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
-}
using SaturationFunction = IR::ResultAndOverflow<IR::U32> (IREmitter::*)(const IR::U32&, size_t);
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
index 1dda532d92..1498ac6c7b 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
@@ -4,13 +4,10 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
namespace {
-IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
- const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
- return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
-}
using ShiftFunction = IR::ResultAndCarry<IR::U32> (IREmitter::*)(const IR::U32&, const IR::U8&, const IR::U1&);
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp
index 42b2ebf4aa..d309d42d66 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp
@@ -25,9 +25,9 @@ static bool PLIHandler(TranslatorVisitor& v) {
return v.RaiseException(Exception::PreloadInstruction);
}
-using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U8&);
+using ExtensionFunctionU8 = IR::U32 (IREmitter::*)(const IR::U8&);
-static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunction ext_fn) {
+static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunctionU8 ext_fn) {
const u32 imm32 = imm12.ZeroExtend();
const u32 base = v.ir.AlignPC(4);
const u32 address = U ? (base + imm32) : (base - imm32);
@@ -37,7 +37,7 @@ static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
return true;
}
-static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunction ext_fn) {
+static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunctionU8 ext_fn) {
if (m == Reg::PC) {
return v.UnpredictableInstruction();
}
@@ -52,7 +52,7 @@ static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
return true;
}
-static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunction ext_fn) {
+static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunctionU8 ext_fn) {
const u32 imm32 = imm12.ZeroExtend();
const IR::U32 reg_n = v.ir.GetRegister(n);
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp
index 5b9f1639af..d8a043e553 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp
@@ -4,12 +4,11 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U16&);
-
-static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunction ext_fn) {
+static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunctionU16 ext_fn) {
const auto imm32 = imm12.ZeroExtend();
const auto base = v.ir.AlignPC(4);
const auto address = U ? (base + imm32) : (base - imm32);
@@ -19,7 +18,7 @@ static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
return true;
}
-static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunction ext_fn) {
+static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunctionU16 ext_fn) {
if (m == Reg::PC) {
return v.UnpredictableInstruction();
}
@@ -34,7 +33,7 @@ static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
return true;
}
-static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunction ext_fn) {
+static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunctionU16 ext_fn) {
const u32 imm32 = imm12.ZeroExtend();
const IR::U32 reg_n = v.ir.GetRegister(n);
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp
index 17d4285c23..eb574d773c 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp
@@ -6,11 +6,9 @@
#include <mcl/bit/bit_field.hpp>
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static bool ITBlockCheck(const A32::IREmitter& ir) {
- return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
-}
static bool TableBranch(TranslatorVisitor& v, Reg n, Reg m, bool half) {
if (m == Reg::PC) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp
index 2bc782b973..d446fbf3dd 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp
@@ -6,11 +6,9 @@
#include <mcl/bit/bit_count.hpp>
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static bool ITBlockCheck(const A32::IREmitter& ir) {
- return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
-}
static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32& start_address, const IR::U32& writeback_address) {
auto address = start_address;
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp
index b92e27fc66..b7556a8caa 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp
@@ -4,11 +4,9 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static bool ITBlockCheck(const A32::IREmitter& ir) {
- return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
-}
bool TranslatorVisitor::thumb32_LDR_lit(bool U, Reg t, Imm<12> imm12) {
if (t == Reg::PC && ITBlockCheck(ir)) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp
index 654940967d..64d57e917d 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp
@@ -4,15 +4,9 @@
*/
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
+#include "dynarmic/frontend/A32/translate/impl/common.h"
namespace Dynarmic::A32 {
-static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
- return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
-}
-
-static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
- return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
-}
bool TranslatorVisitor::thumb32_SADD8(Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp
index 3f5a70bdc0..68f536c8d5 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp
@@ -5,261 +5,7 @@
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
-#include <mcl/assert.hpp>
-
-#include "dynarmic/ir/opcodes.h"
-
namespace Dynarmic::A64 {
-using Opcode = IR::Opcode;
-
-u64 IREmitter::PC() const {
- return current_location->PC();
-}
-
-u64 IREmitter::AlignPC(size_t alignment) const {
- const u64 pc = PC();
- return static_cast<u64>(pc - pc % alignment);
-}
-
-void IREmitter::SetCheckBit(const IR::U1& value) {
- Inst(Opcode::A64SetCheckBit, value);
-}
-
-IR::U1 IREmitter::GetCFlag() {
- return Inst<IR::U1>(Opcode::A64GetCFlag);
-}
-
-IR::U32 IREmitter::GetNZCVRaw() {
- return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
-}
-
-void IREmitter::SetNZCVRaw(IR::U32 value) {
- Inst(Opcode::A64SetNZCVRaw, value);
-}
-
-void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
- Inst(Opcode::A64SetNZCV, nzcv);
-}
-
-void IREmitter::CallSupervisor(u32 imm) {
- Inst(Opcode::A64CallSupervisor, Imm32(imm));
-}
-
-void IREmitter::ExceptionRaised(Exception exception) {
- Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
-}
-
-void IREmitter::DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) {
- Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast<u64>(op)), value);
-}
-
-void IREmitter::InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) {
- Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
-}
-
-void IREmitter::DataSynchronizationBarrier() {
- Inst(Opcode::A64DataSynchronizationBarrier);
-}
-
-void IREmitter::DataMemoryBarrier() {
- Inst(Opcode::A64DataMemoryBarrier);
-}
-
-void IREmitter::InstructionSynchronizationBarrier() {
- Inst(Opcode::A64InstructionSynchronizationBarrier);
-}
-
-IR::U32 IREmitter::GetCNTFRQ() {
- return Inst<IR::U32>(Opcode::A64GetCNTFRQ);
-}
-
-IR::U64 IREmitter::GetCNTPCT() {
- return Inst<IR::U64>(Opcode::A64GetCNTPCT);
-}
-
-IR::U32 IREmitter::GetCTR() {
- return Inst<IR::U32>(Opcode::A64GetCTR);
-}
-
-IR::U32 IREmitter::GetDCZID() {
- return Inst<IR::U32>(Opcode::A64GetDCZID);
-}
-
-IR::U64 IREmitter::GetTPIDR() {
- return Inst<IR::U64>(Opcode::A64GetTPIDR);
-}
-
-void IREmitter::SetTPIDR(const IR::U64& value) {
- Inst(Opcode::A64SetTPIDR, value);
-}
-
-IR::U64 IREmitter::GetTPIDRRO() {
- return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
-}
-
-void IREmitter::ClearExclusive() {
- Inst(Opcode::A64ClearExclusive);
-}
-
-IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U8>(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U16>(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U64>(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U128>(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U8>(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U16>(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U64>(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) {
- return Inst<IR::U128>(Opcode::A64ExclusiveReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
-}
-
-void IREmitter::WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) {
- Inst(Opcode::A64WriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-void IREmitter::WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) {
- Inst(Opcode::A64WriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-void IREmitter::WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) {
- Inst(Opcode::A64WriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-void IREmitter::WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) {
- Inst(Opcode::A64WriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-void IREmitter::WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) {
- Inst(Opcode::A64WriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) {
- return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
-}
-
-IR::U32 IREmitter::GetW(Reg reg) {
- if (reg == Reg::ZR)
- return Imm32(0);
- return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
-}
-
-IR::U64 IREmitter::GetX(Reg reg) {
- if (reg == Reg::ZR)
- return Imm64(0);
- return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
-}
-
-IR::U128 IREmitter::GetS(Vec vec) {
- return Inst<IR::U128>(Opcode::A64GetS, IR::Value(vec));
-}
-
-IR::U128 IREmitter::GetD(Vec vec) {
- return Inst<IR::U128>(Opcode::A64GetD, IR::Value(vec));
-}
-
-IR::U128 IREmitter::GetQ(Vec vec) {
- return Inst<IR::U128>(Opcode::A64GetQ, IR::Value(vec));
-}
-
-IR::U64 IREmitter::GetSP() {
- return Inst<IR::U64>(Opcode::A64GetSP);
-}
-
-IR::U32 IREmitter::GetFPCR() {
- return Inst<IR::U32>(Opcode::A64GetFPCR);
-}
-
-IR::U32 IREmitter::GetFPSR() {
- return Inst<IR::U32>(Opcode::A64GetFPSR);
-}
-
-void IREmitter::SetW(const Reg reg, const IR::U32& value) {
- if (reg == Reg::ZR)
- return;
- Inst(Opcode::A64SetW, IR::Value(reg), value);
-}
-
-void IREmitter::SetX(const Reg reg, const IR::U64& value) {
- if (reg == Reg::ZR)
- return;
- Inst(Opcode::A64SetX, IR::Value(reg), value);
-}
-
-void IREmitter::SetS(const Vec vec, const IR::U128& value) {
- Inst(Opcode::A64SetS, IR::Value(vec), value);
-}
-
-void IREmitter::SetD(const Vec vec, const IR::U128& value) {
- Inst(Opcode::A64SetD, IR::Value(vec), value);
-}
-
-void IREmitter::SetQ(const Vec vec, const IR::U128& value) {
- Inst(Opcode::A64SetQ, IR::Value(vec), value);
-}
-
-void IREmitter::SetSP(const IR::U64& value) {
- Inst(Opcode::A64SetSP, value);
-}
-
-void IREmitter::SetFPCR(const IR::U32& value) {
- Inst(Opcode::A64SetFPCR, value);
-}
-
-void IREmitter::SetFPSR(const IR::U32& value) {
- Inst(Opcode::A64SetFPSR, value);
-}
-
-void IREmitter::SetPC(const IR::U64& value) {
- Inst(Opcode::A64SetPC, value);
-}
-
-IR::U64 IREmitter::ImmCurrentLocationDescriptor() {
- return Imm64(IR::LocationDescriptor{*current_location}.Value());
-}
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h
index 7fc8bea7c4..3bf633a3da 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h
@@ -8,12 +8,14 @@
#include <optional>
#include <mcl/stdint.hpp>
+#include <mcl/assert.hpp>
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
#include "dynarmic/frontend/A64/a64_types.h"
#include "dynarmic/interface/A64/config.h"
#include "dynarmic/ir/ir_emitter.h"
#include "dynarmic/ir/value.h"
+#include "dynarmic/ir/opcodes.h"
namespace Dynarmic::A64 {
@@ -24,79 +26,262 @@ namespace Dynarmic::A64 {
*/
class IREmitter : public IR::IREmitter {
public:
- explicit IREmitter(IR::Block& block)
- : IR::IREmitter(block) {}
- explicit IREmitter(IR::Block& block, LocationDescriptor descriptor)
- : IR::IREmitter(block), current_location(descriptor) {}
+ explicit IREmitter(IR::Block& block) : IR::IREmitter(block) {}
+ explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {}
std::optional<LocationDescriptor> current_location;
- u64 PC() const;
- u64 AlignPC(size_t alignment) const;
-
- void SetCheckBit(const IR::U1& value);
- IR::U1 GetCFlag();
- IR::U32 GetNZCVRaw();
- void SetNZCVRaw(IR::U32 value);
- void SetNZCV(const IR::NZCV& nzcv);
-
- void CallSupervisor(u32 imm);
- void ExceptionRaised(Exception exception);
- void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value);
- void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value);
- void DataSynchronizationBarrier();
- void DataMemoryBarrier();
- void InstructionSynchronizationBarrier();
- IR::U32 GetCNTFRQ();
- IR::U64 GetCNTPCT(); // TODO: Ensure sub-basic-block cycle counts are updated before this.
- IR::U32 GetCTR();
- IR::U32 GetDCZID();
- IR::U64 GetTPIDR();
- IR::U64 GetTPIDRRO();
- void SetTPIDR(const IR::U64& value);
-
- void ClearExclusive();
- IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type);
- IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type);
- void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type);
- void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type);
- void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type);
- void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type);
- void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type);
- IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type);
- IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type);
- IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type);
- IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type);
- IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type);
-
- IR::U32 GetW(Reg source_reg);
- IR::U64 GetX(Reg source_reg);
- IR::U128 GetS(Vec source_vec);
- IR::U128 GetD(Vec source_vec);
- IR::U128 GetQ(Vec source_vec);
- IR::U64 GetSP();
- IR::U32 GetFPCR();
- IR::U32 GetFPSR();
- void SetW(Reg dest_reg, const IR::U32& value);
- void SetX(Reg dest_reg, const IR::U64& value);
- void SetS(Vec dest_vec, const IR::U128& value);
- void SetD(Vec dest_vec, const IR::U128& value);
- void SetQ(Vec dest_vec, const IR::U128& value);
- void SetSP(const IR::U64& value);
- void SetFPCR(const IR::U32& value);
- void SetFPSR(const IR::U32& value);
- void SetPC(const IR::U64& value);
+ using Opcode = IR::Opcode;
+
+ u64 PC() const noexcept {
+ return current_location->PC();
+ }
+
+ u64 AlignPC(size_t alignment) const noexcept {
+ const u64 pc = PC();
+ return static_cast<u64>(pc - pc % alignment);
+ }
+
+ void SetCheckBit(const IR::U1& value) noexcept {
+ Inst(Opcode::A64SetCheckBit, value);
+ }
+
+ IR::U1 GetCFlag() noexcept {
+ return Inst<IR::U1>(Opcode::A64GetCFlag);
+ }
+
+ IR::U32 GetNZCVRaw() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
+ }
+
+ void SetNZCVRaw(IR::U32 value) noexcept {
+ Inst(Opcode::A64SetNZCVRaw, value);
+ }
+
+ void SetNZCV(const IR::NZCV& nzcv) noexcept {
+ Inst(Opcode::A64SetNZCV, nzcv);
+ }
+
+ void CallSupervisor(u32 imm) noexcept {
+ Inst(Opcode::A64CallSupervisor, Imm32(imm));
+ }
+
+ void ExceptionRaised(Exception exception) noexcept {
+ Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
+ }
+
+ void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) noexcept {
+ Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast<u64>(op)), value);
+ }
+
+ void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) noexcept {
+ Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
+ }
+
+ void DataSynchronizationBarrier() noexcept {
+ Inst(Opcode::A64DataSynchronizationBarrier);
+ }
+
+ void DataMemoryBarrier() noexcept {
+ Inst(Opcode::A64DataMemoryBarrier);
+ }
+
+ void InstructionSynchronizationBarrier() noexcept {
+ Inst(Opcode::A64InstructionSynchronizationBarrier);
+ }
+
+ IR::U32 GetCNTFRQ() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetCNTFRQ);
+ }
+
+ IR::U64 GetCNTPCT() noexcept {
+ return Inst<IR::U64>(Opcode::A64GetCNTPCT);
+ }
+
+ IR::U32 GetCTR() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetCTR);
+ }
+
+ IR::U32 GetDCZID() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetDCZID);
+ }
+
+ IR::U64 GetTPIDR() noexcept {
+ return Inst<IR::U64>(Opcode::A64GetTPIDR);
+ }
+
+ void SetTPIDR(const IR::U64& value) noexcept {
+ Inst(Opcode::A64SetTPIDR, value);
+ }
+
+ IR::U64 GetTPIDRRO() noexcept {
+ return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
+ }
+
+ void ClearExclusive() noexcept {
+ Inst(Opcode::A64ClearExclusive);
+ }
+
+ IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U8>(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U16>(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U64>(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U128>(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U8>(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U16>(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U64>(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
+ return Inst<IR::U128>(Opcode::A64ExclusiveReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
+ }
+
+ void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) noexcept {
+ Inst(Opcode::A64WriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) noexcept {
+ Inst(Opcode::A64WriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) noexcept {
+ Inst(Opcode::A64WriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) noexcept {
+ Inst(Opcode::A64WriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) noexcept {
+ Inst(Opcode::A64WriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) noexcept {
+ return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
+ }
+
+ IR::U32 GetW(Reg reg) noexcept {
+ if (reg == Reg::ZR)
+ return Imm32(0);
+ return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
+ }
+
+ IR::U64 GetX(Reg reg) noexcept {
+ if (reg == Reg::ZR)
+ return Imm64(0);
+ return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
+ }
+
+ IR::U128 GetS(Vec vec) noexcept {
+ return Inst<IR::U128>(Opcode::A64GetS, IR::Value(vec));
+ }
+
+ IR::U128 GetD(Vec vec) noexcept {
+ return Inst<IR::U128>(Opcode::A64GetD, IR::Value(vec));
+ }
+
+ IR::U128 GetQ(Vec vec) noexcept {
+ return Inst<IR::U128>(Opcode::A64GetQ, IR::Value(vec));
+ }
+
+ IR::U64 GetSP() noexcept {
+ return Inst<IR::U64>(Opcode::A64GetSP);
+ }
+
+ IR::U32 GetFPCR() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetFPCR);
+ }
+
+ IR::U32 GetFPSR() noexcept {
+ return Inst<IR::U32>(Opcode::A64GetFPSR);
+ }
+
+ void SetW(const Reg reg, const IR::U32& value) noexcept {
+ if (reg == Reg::ZR)
+ return;
+ Inst(Opcode::A64SetW, IR::Value(reg), value);
+ }
+
+ void SetX(const Reg reg, const IR::U64& value) noexcept {
+ if (reg == Reg::ZR)
+ return;
+ Inst(Opcode::A64SetX, IR::Value(reg), value);
+ }
+
+ void SetS(const Vec vec, const IR::U128& value) noexcept {
+ Inst(Opcode::A64SetS, IR::Value(vec), value);
+ }
+
+ void SetD(const Vec vec, const IR::U128& value) noexcept {
+ Inst(Opcode::A64SetD, IR::Value(vec), value);
+ }
+
+ void SetQ(const Vec vec, const IR::U128& value) noexcept {
+ Inst(Opcode::A64SetQ, IR::Value(vec), value);
+ }
+
+ void SetSP(const IR::U64& value) noexcept {
+ Inst(Opcode::A64SetSP, value);
+ }
+
+ void SetFPCR(const IR::U32& value) noexcept {
+ Inst(Opcode::A64SetFPCR, value);
+ }
+
+ void SetFPSR(const IR::U32& value) noexcept {
+ Inst(Opcode::A64SetFPSR, value);
+ }
+
+ void SetPC(const IR::U64& value) noexcept {
+ Inst(Opcode::A64SetPC, value);
+ }
private:
- IR::U64 ImmCurrentLocationDescriptor();
+ IR::U64 ImmCurrentLocationDescriptor() noexcept {
+ return Imm64(IR::LocationDescriptor{*current_location}.Value());
+ }
};
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h b/externals/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h
index f264893502..e807490d16 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h
@@ -33,27 +33,26 @@ inline size_t ToFastLookupIndex(u32 instruction) {
} // namespace detail
template<typename V>
-DecodeTable<V> GetDecodeTable() {
+constexpr DecodeTable<V> GetDecodeTable() {
std::vector<Matcher<V>> list = {
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
#include "./a64.inc"
#undef INST
};
+ // If a matcher has more bits in its mask it is more specific, so it should come first.
std::stable_sort(list.begin(), list.end(), [](const auto& matcher1, const auto& matcher2) {
// If a matcher has more bits in its mask it is more specific, so it should come first.
return mcl::bit::count_ones(matcher1.GetMask()) > mcl::bit::count_ones(matcher2.GetMask());
});
// Exceptions to the above rule of thumb.
- const std::set<std::string> comes_first{
- "MOVI, MVNI, ORR, BIC (vector, immediate)",
- "FMOV (vector, immediate)",
- "Unallocated SIMD modified immediate",
- };
-
std::stable_partition(list.begin(), list.end(), [&](const auto& matcher) {
- return comes_first.count(matcher.GetName()) > 0;
+ return std::set<std::string>{
+ "MOVI, MVNI, ORR, BIC (vector, immediate)",
+ "FMOV (vector, immediate)",
+ "Unallocated SIMD modified immediate",
+ }.count(matcher.GetName()) > 0;
});
DecodeTable<V> table{};
@@ -75,7 +74,6 @@ std::optional<std::reference_wrapper<const Matcher<V>>> Decode(u32 instruction)
const auto matches_instruction = [instruction](const auto& matcher) {
return matcher.Matches(instruction);
};
-
const auto& subtable = table[detail::ToFastLookupIndex(instruction)];
auto iter = std::find_if(subtable.begin(), subtable.end(), matches_instruction);
return iter != subtable.end() ? std::optional<std::reference_wrapper<const Matcher<V>>>(*iter) : std::nullopt;
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
index 05996aeb64..352c2e6ae2 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
@@ -67,3 +67,64 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
}
} // namespace Dynarmic::A64
+
+// ls -l | awk '{print "#include \"dynarmic/frontend/A64/translate/impl/" $9 "\""}'
+#include "dynarmic/frontend/A64/translate/impl/a64_branch.cpp"
+#include "dynarmic/frontend/A64/translate/impl/a64_exception_generating.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_addsub.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_bitfield.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_conditional_compare.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_conditional_select.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_crc32.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_logical.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_multiply.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_pcrel.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/data_processing_shift.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_compare.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_conditional_compare.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_conditional_select.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_conversion_integer.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_data_processing_three_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/impl.cpp"
+#include "dynarmic/frontend/A64/translate/impl/impl.h"
+#include "dynarmic/frontend/A64/translate/impl/load_store_exclusive.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_load_literal.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_multiple_structures.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_no_allocate_pair.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_register_immediate.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_register_pair.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_register_register_offset.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_register_unprivileged.cpp"
+#include "dynarmic/frontend/A64/translate/impl/load_store_single_structure.cpp"
+#include "dynarmic/frontend/A64/translate/impl/move_wide.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_across_lanes.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_aes.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_copy.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_crypto_four_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_crypto_three_register.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_extract.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_permute.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_sha512.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_sha.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_table_lookup.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_three_different.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_three_same.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_three_same_extra.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp"
+#include "dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp"
+#include "dynarmic/frontend/A64/translate/impl/sys_dc.cpp"
+#include "dynarmic/frontend/A64/translate/impl/sys_ic.cpp"
+#include "dynarmic/frontend/A64/translate/impl/system.cpp"
+#include "dynarmic/frontend/A64/translate/impl/system_flag_format.cpp"
+#include "dynarmic/frontend/A64/translate/impl/system_flag_manipulation.cpp"
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp
index 63615b0f9a..e3b8d7502c 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_pairwise.cpp
@@ -7,14 +7,14 @@
namespace Dynarmic::A64 {
namespace {
-enum class MinMaxOperation {
+enum class MinMaxOperationSSPW {
Max,
MaxNumeric,
Min,
MinNumeric,
};
-bool FPPairwiseMinMax(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, MinMaxOperation operation) {
+bool FPPairwiseMinMax(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, MinMaxOperationSSPW operation) {
const size_t esize = sz ? 64 : 32;
const IR::U128 operand = v.V(128, Vn);
@@ -22,13 +22,13 @@ bool FPPairwiseMinMax(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, MinMaxOpera
const IR::U32U64 element2 = v.ir.VectorGetElement(esize, operand, 1);
const IR::U32U64 result = [&] {
switch (operation) {
- case MinMaxOperation::Max:
+ case MinMaxOperationSSPW::Max:
return v.ir.FPMax(element1, element2);
- case MinMaxOperation::MaxNumeric:
+ case MinMaxOperationSSPW::MaxNumeric:
return v.ir.FPMaxNumeric(element1, element2);
- case MinMaxOperation::Min:
+ case MinMaxOperationSSPW::Min:
return v.ir.FPMin(element1, element2);
- case MinMaxOperation::MinNumeric:
+ case MinMaxOperationSSPW::MinNumeric:
return v.ir.FPMinNumeric(element1, element2);
default:
UNREACHABLE();
@@ -63,18 +63,18 @@ bool TranslatorVisitor::FADDP_pair_2(bool size, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FMAXNMP_pair_2(bool sz, Vec Vn, Vec Vd) {
- return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::MaxNumeric);
+ return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperationSSPW::MaxNumeric);
}
bool TranslatorVisitor::FMAXP_pair_2(bool sz, Vec Vn, Vec Vd) {
- return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::Max);
+ return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperationSSPW::Max);
}
bool TranslatorVisitor::FMINNMP_pair_2(bool sz, Vec Vn, Vec Vd) {
- return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::MinNumeric);
+ return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperationSSPW::MinNumeric);
}
bool TranslatorVisitor::FMINP_pair_2(bool sz, Vec Vn, Vec Vd) {
- return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::Min);
+ return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperationSSPW::Min);
}
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
index a0570edc7e..5d60cb31c3 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
@@ -27,7 +27,7 @@ enum class ShiftExtraBehavior {
Accumulate,
};
-enum class Signedness {
+enum class SignednessSSSBI {
Signed,
Unsigned,
};
@@ -63,7 +63,7 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
return true;
}
-bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, ShiftExtraBehavior behavior, Signedness signedness) {
+bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, ShiftExtraBehavior behavior, SignednessSSSBI SignednessSSSBI) {
if (!immh.Bit<3>()) {
return v.ReservedValue();
}
@@ -73,7 +73,7 @@ bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
const IR::U64 operand = v.V_scalar(esize, Vn);
IR::U64 result = [&]() -> IR::U64 {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSSBI == SignednessSSSBI::Signed) {
return v.ir.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount));
}
return v.ir.LogicalShiftRight(operand, v.ir.Imm8(shift_amount));
@@ -88,7 +88,7 @@ bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
return true;
}
-bool RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, ShiftExtraBehavior behavior, Signedness signedness) {
+bool RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, ShiftExtraBehavior behavior, SignednessSSSBI SignednessSSSBI) {
if (!immh.Bit<3>()) {
return v.ReservedValue();
}
@@ -100,7 +100,7 @@ bool RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
const IR::U64 round_bit = v.ir.LogicalShiftRight(v.ir.LogicalShiftLeft(operand, v.ir.Imm8(64 - shift_amount)), v.ir.Imm8(63));
const IR::U64 result = [&] {
const IR::U64 shifted = [&]() -> IR::U64 {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSSBI == SignednessSSSBI::Signed) {
return v.ir.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount));
}
return v.ir.LogicalShiftRight(operand, v.ir.Imm8(shift_amount));
@@ -163,7 +163,7 @@ bool ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec
return true;
}
-bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Narrowing narrowing, Signedness signedness) {
+bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Narrowing narrowing, SignednessSSSBI SignednessSSSBI) {
if (immh == 0b0000) {
return v.ReservedValue();
}
@@ -179,7 +179,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
const IR::U128 operand = v.ir.ZeroExtendToQuad(v.ir.VectorGetElement(source_esize, v.V(128, Vn), 0));
IR::U128 wide_result = [&] {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSSBI == SignednessSSSBI::Signed) {
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
}
return v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount);
@@ -190,12 +190,12 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
case Narrowing::Truncation:
return v.ir.VectorNarrow(source_esize, wide_result);
case Narrowing::SaturateToUnsigned:
- if (signedness == Signedness::Signed) {
+ if (SignednessSSSBI == SignednessSSSBI::Signed) {
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
}
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
case Narrowing::SaturateToSigned:
- ASSERT(signedness == Signedness::Signed);
+ ASSERT(SignednessSSSBI == SignednessSSSBI::Signed);
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
}
UNREACHABLE();
@@ -206,7 +206,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
return true;
}
-bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign, FloatConversionDirection direction, FP::RoundingMode rounding_mode) {
+bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, SignednessSSSBI sign, FloatConversionDirection direction, FP::RoundingMode rounding_mode) {
const u32 immh_value = immh.ZeroExtend();
if ((immh_value & 0b1110) == 0b0000) {
@@ -227,23 +227,23 @@ bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Ve
switch (direction) {
case FloatConversionDirection::FloatToFixed:
if (esize == 64) {
- return sign == Signedness::Signed
+ return sign == SignednessSSSBI::Signed
? v.ir.FPToFixedS64(operand, fbits, rounding_mode)
: v.ir.FPToFixedU64(operand, fbits, rounding_mode);
}
- return sign == Signedness::Signed
+ return sign == SignednessSSSBI::Signed
? v.ir.FPToFixedS32(operand, fbits, rounding_mode)
: v.ir.FPToFixedU32(operand, fbits, rounding_mode);
case FloatConversionDirection::FixedToFloat:
if (esize == 64) {
- return sign == Signedness::Signed
+ return sign == SignednessSSSBI::Signed
? v.ir.FPSignedFixedToDouble(operand, fbits, rounding_mode)
: v.ir.FPUnsignedFixedToDouble(operand, fbits, rounding_mode);
}
- return sign == Signedness::Signed
+ return sign == SignednessSSSBI::Signed
? v.ir.FPSignedFixedToSingle(operand, fbits, rounding_mode)
: v.ir.FPUnsignedFixedToSingle(operand, fbits, rounding_mode);
}
@@ -257,19 +257,19 @@ bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Ve
} // Anonymous namespace
bool TranslatorVisitor::FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
+ return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, SignednessSSSBI::Signed, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
+ return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, SignednessSSSBI::Unsigned, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::SCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
+ return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, SignednessSSSBI::Signed, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::UCVTF_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
+ return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, SignednessSSSBI::Unsigned, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@@ -289,27 +289,27 @@ bool TranslatorVisitor::SQSHLU_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SQSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToSigned, Signedness::Signed);
+ return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToSigned, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SQSHRUN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToUnsigned, Signedness::Signed);
+ return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToUnsigned, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SRSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
+ return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SRSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
+ return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
+ return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
+ return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, SignednessSSSBI::Signed);
}
bool TranslatorVisitor::SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@@ -332,23 +332,23 @@ bool TranslatorVisitor::UQSHL_imm_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::UQSHRN_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToUnsigned, Signedness::Unsigned);
+ return ShiftRightNarrowing(*this, immh, immb, Vn, Vd, Narrowing::SaturateToUnsigned, SignednessSSSBI::Unsigned);
}
bool TranslatorVisitor::URSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
+ return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, SignednessSSSBI::Unsigned);
}
bool TranslatorVisitor::URSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
+ return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, SignednessSSSBI::Unsigned);
}
bool TranslatorVisitor::USHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
+ return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, SignednessSSSBI::Unsigned);
}
bool TranslatorVisitor::USRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
+ return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, SignednessSSSBI::Unsigned);
}
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp
index fb9ae9d141..d551605bda 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp
@@ -26,12 +26,12 @@ enum class ComparisonVariant {
Zero,
};
-enum class Signedness {
+enum class SignednessSSTS {
Signed,
Unsigned,
};
-bool RoundingShiftLeft(TranslatorVisitor& v, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) {
+bool RoundingShiftLeft(TranslatorVisitor& v, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, SignednessSSTS sign) {
if (size != 0b11) {
return v.ReservedValue();
}
@@ -39,7 +39,7 @@ bool RoundingShiftLeft(TranslatorVisitor& v, Imm<2> size, Vec Vm, Vec Vn, Vec Vd
const IR::U128 operand1 = v.V(64, Vn);
const IR::U128 operand2 = v.V(64, Vm);
const IR::U128 result = [&] {
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSSTS::Signed) {
return v.ir.VectorRoundingShiftLeftSigned(64, operand1, operand2);
}
@@ -369,7 +369,7 @@ bool TranslatorVisitor::SQSHL_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SRSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingShiftLeft(*this, size, Vm, Vn, Vd, Signedness::Signed);
+ return RoundingShiftLeft(*this, size, Vm, Vn, Vd, SignednessSSTS::Signed);
}
bool TranslatorVisitor::SSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -411,7 +411,7 @@ bool TranslatorVisitor::UQSHL_reg_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::URSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingShiftLeft(*this, size, Vm, Vn, Vd, Signedness::Unsigned);
+ return RoundingShiftLeft(*this, size, Vm, Vn, Vd, SignednessSSTS::Unsigned);
}
bool TranslatorVisitor::USHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
index 2289f5cbd1..0fc37f538f 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
@@ -7,7 +7,7 @@
namespace Dynarmic::A64 {
namespace {
-enum class ComparisonType {
+enum class ComparisonTypeSSTRM {
EQ,
GE,
GT,
@@ -15,12 +15,12 @@ enum class ComparisonType {
LT
};
-enum class Signedness {
+enum class SignednessSSTRM {
Signed,
Unsigned
};
-bool ScalarFPCompareAgainstZero(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, ComparisonType type) {
+bool ScalarFPCompareAgainstZero(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, ComparisonTypeSSTRM type) {
const size_t esize = sz ? 64 : 32;
const size_t datasize = esize;
@@ -28,15 +28,15 @@ bool ScalarFPCompareAgainstZero(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, C
const IR::U128 zero = v.ir.ZeroVector();
const IR::U128 result = [&] {
switch (type) {
- case ComparisonType::EQ:
+ case ComparisonTypeSSTRM::EQ:
return v.ir.FPVectorEqual(esize, operand, zero);
- case ComparisonType::GE:
+ case ComparisonTypeSSTRM::GE:
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
- case ComparisonType::GT:
+ case ComparisonTypeSSTRM::GT:
return v.ir.FPVectorGreater(esize, operand, zero);
- case ComparisonType::LE:
+ case ComparisonTypeSSTRM::LE:
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
- case ComparisonType::LT:
+ case ComparisonTypeSSTRM::LT:
return v.ir.FPVectorGreater(esize, zero, operand);
}
@@ -47,18 +47,18 @@ bool ScalarFPCompareAgainstZero(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, C
return true;
}
-bool ScalarFPConvertWithRound(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, FP::RoundingMode rmode, Signedness sign) {
+bool ScalarFPConvertWithRound(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, FP::RoundingMode rmode, SignednessSSTRM sign) {
const size_t esize = sz ? 64 : 32;
const IR::U32U64 operand = v.V_scalar(esize, Vn);
const IR::U32U64 result = [&]() -> IR::U32U64 {
if (sz) {
- return sign == Signedness::Signed
+ return sign == SignednessSSTRM::Signed
? v.ir.FPToFixedS64(operand, 0, rmode)
: v.ir.FPToFixedU64(operand, 0, rmode);
}
- return sign == Signedness::Signed
+ return sign == SignednessSSTRM::Signed
? v.ir.FPToFixedS32(operand, 0, rmode)
: v.ir.FPToFixedU32(operand, 0, rmode);
}();
@@ -107,55 +107,55 @@ bool TranslatorVisitor::FCMEQ_zero_1(Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCMEQ_zero_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonType::EQ);
+ return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonTypeSSTRM::EQ);
}
bool TranslatorVisitor::FCMGE_zero_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonType::GE);
+ return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonTypeSSTRM::GE);
}
bool TranslatorVisitor::FCMGT_zero_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonType::GT);
+ return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonTypeSSTRM::GT);
}
bool TranslatorVisitor::FCMLE_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonType::LE);
+ return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonTypeSSTRM::LE);
}
bool TranslatorVisitor::FCMLT_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonType::LT);
+ return ScalarFPCompareAgainstZero(*this, sz, Vn, Vd, ComparisonTypeSSTRM::LT);
}
bool TranslatorVisitor::FCVTAS_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, Signedness::Signed);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, SignednessSSTRM::Signed);
}
bool TranslatorVisitor::FCVTAU_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, Signedness::Unsigned);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieAwayFromZero, SignednessSSTRM::Unsigned);
}
bool TranslatorVisitor::FCVTMS_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, Signedness::Signed);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, SignednessSSTRM::Signed);
}
bool TranslatorVisitor::FCVTMU_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, Signedness::Unsigned);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsMinusInfinity, SignednessSSTRM::Unsigned);
}
bool TranslatorVisitor::FCVTNS_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, Signedness::Signed);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, SignednessSSTRM::Signed);
}
bool TranslatorVisitor::FCVTNU_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, Signedness::Unsigned);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::ToNearest_TieEven, SignednessSSTRM::Unsigned);
}
bool TranslatorVisitor::FCVTPS_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, Signedness::Signed);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, SignednessSSTRM::Signed);
}
bool TranslatorVisitor::FCVTPU_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, Signedness::Unsigned);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsPlusInfinity, SignednessSSTRM::Unsigned);
}
bool TranslatorVisitor::FCVTXN_1(bool sz, Vec Vn, Vec Vd) {
@@ -171,11 +171,11 @@ bool TranslatorVisitor::FCVTXN_1(bool sz, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCVTZS_int_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsZero, Signedness::Signed);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsZero, SignednessSSTRM::Signed);
}
bool TranslatorVisitor::FCVTZU_int_2(bool sz, Vec Vn, Vec Vd) {
- return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsZero, Signedness::Unsigned);
+ return ScalarFPConvertWithRound(*this, sz, Vn, Vd, FP::RoundingMode::TowardsZero, SignednessSSTRM::Unsigned);
}
bool TranslatorVisitor::FRECPE_1(Vec Vn, Vec Vd) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
index dbbc4ce12c..7a5d9847d7 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
@@ -9,7 +9,7 @@
namespace Dynarmic::A64 {
namespace {
-std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
+std::pair<size_t, Vec> CombineScalar(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
if (size == 0b01) {
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
}
@@ -122,7 +122,7 @@ bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm
}
const size_t esize = 8 << size.ZeroExtend();
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineScalar(size, H, L, M, Vmlo);
const IR::UAny operand1 = V_scalar(esize, Vn);
const IR::UAny operand2 = ir.VectorGetElement(esize, V(128, Vm), index);
@@ -137,7 +137,7 @@ bool TranslatorVisitor::SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> V
}
const size_t esize = 8 << size.ZeroExtend();
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineScalar(size, H, L, M, Vmlo);
const IR::U128 operand1 = ir.ZeroExtendToQuad(ir.VectorGetElement(esize, V(128, Vn), 0));
const IR::U128 operand2 = V(128, Vm);
@@ -154,7 +154,7 @@ bool TranslatorVisitor::SQDMULL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm
}
const size_t esize = 8 << size.ZeroExtend();
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineScalar(size, H, L, M, Vmlo);
const IR::U128 operand1 = ir.ZeroExtendToQuad(ir.VectorGetElement(esize, V(128, Vn), 0));
const IR::U128 operand2 = V(128, Vm);
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp
index 41b0952249..559721a22a 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp
@@ -20,24 +20,24 @@ enum class Accumulating {
Accumulate
};
-enum class Signedness {
+enum class SignednessSSBI {
Signed,
Unsigned
};
-enum class Narrowing {
+enum class NarrowingSSBI {
Truncation,
SaturateToUnsigned,
SaturateToSigned,
};
-enum class SaturatingShiftLeftType {
+enum class SaturatingShiftLeftTypeSSBI {
Signed,
Unsigned,
SignedWithUnsignedSaturation,
};
-enum class FloatConversionDirection {
+enum class FloatConversionDirectionSSBI {
FixedToFloat,
FloatToFixed,
};
@@ -48,7 +48,7 @@ IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round
return v.ir.VectorSub(esize, shifted, round_correction);
}
-bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Rounding rounding, Accumulating accumulating, Signedness signedness) {
+bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Rounding rounding, Accumulating accumulating, SignednessSSBI SignednessSSBI) {
if (immh == 0b0000) {
return v.DecodeError();
}
@@ -65,7 +65,7 @@ bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn,
const IR::U128 operand = v.V(datasize, Vn);
IR::U128 result = [&] {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSBI == SignednessSSBI::Signed) {
return v.ir.VectorArithmeticShiftRight(esize, operand, shift_amount);
}
return v.ir.VectorLogicalShiftRight(esize, operand, shift_amount);
@@ -85,7 +85,7 @@ bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn,
return true;
}
-bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Rounding rounding, Narrowing narrowing, Signedness signedness) {
+bool ShiftRightNarrowingSSBI(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Rounding rounding, NarrowingSSBI NarrowingSSBI, SignednessSSBI SignednessSSBI) {
if (immh == 0b0000) {
return v.DecodeError();
}
@@ -103,7 +103,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
const IR::U128 operand = v.V(128, Vn);
IR::U128 wide_result = [&] {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSBI == SignednessSSBI::Signed) {
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
}
return v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount);
@@ -115,16 +115,16 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
}
const IR::U128 result = [&] {
- switch (narrowing) {
- case Narrowing::Truncation:
+ switch (NarrowingSSBI) {
+ case NarrowingSSBI::Truncation:
return v.ir.VectorNarrow(source_esize, wide_result);
- case Narrowing::SaturateToUnsigned:
- if (signedness == Signedness::Signed) {
+ case NarrowingSSBI::SaturateToUnsigned:
+ if (SignednessSSBI == SignednessSSBI::Signed) {
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
}
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
- case Narrowing::SaturateToSigned:
- ASSERT(signedness == Signedness::Signed);
+ case NarrowingSSBI::SaturateToSigned:
+ ASSERT(SignednessSSBI == SignednessSSBI::Signed);
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
}
UNREACHABLE();
@@ -134,7 +134,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
return true;
}
-bool ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness signedness) {
+bool ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, SignednessSSBI SignednessSSBI) {
if (immh == 0b0000) {
return v.DecodeError();
}
@@ -151,7 +151,7 @@ bool ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec V
const IR::U128 operand = v.Vpart(datasize, Vn, part);
const IR::U128 expanded_operand = [&] {
- if (signedness == Signedness::Signed) {
+ if (SignednessSSBI == SignednessSSBI::Signed) {
return v.ir.VectorSignExtend(esize, operand);
}
return v.ir.VectorZeroExtend(esize, operand);
@@ -162,7 +162,7 @@ bool ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec V
return true;
}
-bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, SaturatingShiftLeftType type) {
+bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, SaturatingShiftLeftTypeSSBI type) {
if (!Q && immh.Bit<3>()) {
return v.ReservedValue();
}
@@ -174,11 +174,11 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
const IR::U128 operand = v.V(datasize, Vn);
const IR::U128 shift_vec = v.ir.VectorBroadcast(esize, v.I(esize, shift));
const IR::U128 result = [&] {
- if (type == SaturatingShiftLeftType::Signed) {
+ if (type == SaturatingShiftLeftTypeSSBI::Signed) {
return v.ir.VectorSignedSaturatedShiftLeft(esize, operand, shift_vec);
}
- if (type == SaturatingShiftLeftType::Unsigned) {
+ if (type == SaturatingShiftLeftTypeSSBI::Unsigned) {
return v.ir.VectorUnsignedSaturatedShiftLeft(esize, operand, shift_vec);
}
@@ -189,7 +189,7 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
return true;
}
-bool ConvertFloat(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness signedness, FloatConversionDirection direction, FP::RoundingMode rounding_mode) {
+bool ConvertFloat(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, SignednessSSBI SignednessSSBI, FloatConversionDirectionSSBI direction, FP::RoundingMode rounding_mode) {
if (immh == 0b0000) {
return v.DecodeError();
}
@@ -210,12 +210,12 @@ bool ConvertFloat(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn
const IR::U128 operand = v.V(datasize, Vn);
const IR::U128 result = [&] {
switch (direction) {
- case FloatConversionDirection::FixedToFloat:
- return signedness == Signedness::Signed
+ case FloatConversionDirectionSSBI::FixedToFloat:
+ return SignednessSSBI == SignednessSSBI::Signed
? v.ir.FPVectorFromSignedFixed(esize, operand, fbits, rounding_mode)
: v.ir.FPVectorFromUnsignedFixed(esize, operand, fbits, rounding_mode);
- case FloatConversionDirection::FloatToFixed:
- return signedness == Signedness::Signed
+ case FloatConversionDirectionSSBI::FloatToFixed:
+ return SignednessSSBI == SignednessSSBI::Signed
? v.ir.FPVectorToSignedFixed(esize, operand, fbits, rounding_mode)
: v.ir.FPVectorToUnsignedFixed(esize, operand, fbits, rounding_mode);
}
@@ -229,19 +229,19 @@ bool ConvertFloat(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn
} // Anonymous namespace
bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::None, Signedness::Signed);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::None, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SRSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::None, Signedness::Signed);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::None, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SRSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::Accumulate, Signedness::Signed);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::Accumulate, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::Accumulate, Signedness::Signed);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::Accumulate, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@@ -264,71 +264,71 @@ bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd)
}
bool TranslatorVisitor::SHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::Truncation, Signedness::Unsigned);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::None, NarrowingSSBI::Truncation, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::RSHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::Truncation, Signedness::Unsigned);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::Round, NarrowingSSBI::Truncation, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::SQSHL_imm_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftType::Signed);
+ return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftTypeSSBI::Signed);
}
bool TranslatorVisitor::SQSHLU_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftType::SignedWithUnsignedSaturation);
+ return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftTypeSSBI::SignedWithUnsignedSaturation);
}
bool TranslatorVisitor::SQSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::SaturateToSigned, Signedness::Signed);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::None, NarrowingSSBI::SaturateToSigned, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SQRSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::SaturateToSigned, Signedness::Signed);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::Round, NarrowingSSBI::SaturateToSigned, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SQSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::SaturateToUnsigned, Signedness::Signed);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::None, NarrowingSSBI::SaturateToUnsigned, SignednessSSBI::Signed);
}
bool TranslatorVisitor::SQRSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::SaturateToUnsigned, Signedness::Signed);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::Round, NarrowingSSBI::SaturateToUnsigned, SignednessSSBI::Signed);
}
bool TranslatorVisitor::UQSHL_imm_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftType::Unsigned);
+ return SaturatingShiftLeft(*this, Q, immh, immb, Vn, Vd, SaturatingShiftLeftTypeSSBI::Unsigned);
}
bool TranslatorVisitor::UQSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::SaturateToUnsigned, Signedness::Unsigned);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::None, NarrowingSSBI::SaturateToUnsigned, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::UQRSHRN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::SaturateToUnsigned, Signedness::Unsigned);
+ return ShiftRightNarrowingSSBI(*this, Q, immh, immb, Vn, Vd, Rounding::Round, NarrowingSSBI::SaturateToUnsigned, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::SSHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Signed);
+ return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Signed);
}
bool TranslatorVisitor::URSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::None, Signedness::Unsigned);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::None, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::URSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::Accumulate, Signedness::Unsigned);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Accumulating::Accumulate, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::USHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::None, Signedness::Unsigned);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::None, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::USRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::Accumulate, Signedness::Unsigned);
+ return ShiftRight(*this, Q, immh, immb, Vn, Vd, Rounding::None, Accumulating::Accumulate, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::USHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned);
+ return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Unsigned);
}
bool TranslatorVisitor::SRI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@@ -384,19 +384,19 @@ bool TranslatorVisitor::SLI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd)
}
bool TranslatorVisitor::SCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
+ return ConvertFloat(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Signed, FloatConversionDirectionSSBI::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::UCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
+ return ConvertFloat(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Unsigned, FloatConversionDirectionSSBI::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::FCVTZS_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
+ return ConvertFloat(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Signed, FloatConversionDirectionSSBI::FloatToFixed, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::FCVTZU_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
- return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
+ return ConvertFloat(*this, Q, immh, immb, Vn, Vd, SignednessSSBI::Unsigned, FloatConversionDirectionSSBI::FloatToFixed, FP::RoundingMode::TowardsZero);
}
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_different.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_different.cpp
index 8cc677b652..8f460665da 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_different.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_different.cpp
@@ -12,12 +12,12 @@ enum class AbsoluteDifferenceBehavior {
Accumulate
};
-enum class Signedness {
+enum class SignednessSTD {
Signed,
Unsigned
};
-bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, AbsoluteDifferenceBehavior behavior, Signedness sign) {
+bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, AbsoluteDifferenceBehavior behavior, SignednessSTD sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -27,7 +27,7 @@ bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V
const IR::U128 operand1 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vn, Q));
const IR::U128 operand2 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vm, Q));
- IR::U128 result = sign == Signedness::Signed ? v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2)
+ IR::U128 result = sign == SignednessSTD::Signed ? v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2)
: v.ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2);
if (behavior == AbsoluteDifferenceBehavior::Accumulate) {
@@ -45,7 +45,7 @@ enum class MultiplyLongBehavior {
Subtract
};
-bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MultiplyLongBehavior behavior, Signedness sign) {
+bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MultiplyLongBehavior behavior, SignednessSTD sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -59,7 +59,7 @@ bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec
const auto reg_n = v.Vpart(datasize, Vn, Q);
const auto reg_m = v.Vpart(datasize, Vm, Q);
- return sign == Signedness::Signed
+ return sign == SignednessSTD::Signed
? v.ir.VectorMultiplySignedWiden(esize, reg_n, reg_m)
: v.ir.VectorMultiplyUnsignedWiden(esize, reg_n, reg_m);
}();
@@ -81,7 +81,7 @@ enum class LongOperationBehavior {
Subtraction
};
-bool LongOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, LongOperationBehavior behavior, Signedness sign) {
+bool LongOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, LongOperationBehavior behavior, SignednessSTD sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -92,7 +92,7 @@ bool LongOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Ve
const auto get_operand = [&](Vec vec) {
const IR::U128 tmp = v.Vpart(64, vec, part);
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTD::Signed) {
return v.ir.VectorSignExtend(esize, tmp);
}
@@ -118,7 +118,7 @@ enum class WideOperationBehavior {
Subtraction
};
-bool WideOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, WideOperationBehavior behavior, Signedness sign) {
+bool WideOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, WideOperationBehavior behavior, SignednessSTD sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -130,7 +130,7 @@ bool WideOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Ve
const IR::U128 operand2 = [&] {
const IR::U128 tmp = v.Vpart(64, Vm, part);
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTD::Signed) {
return v.ir.VectorSignExtend(esize, tmp);
}
@@ -166,75 +166,75 @@ bool TranslatorVisitor::PMULL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::Accumulate, Signedness::Signed);
+ return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::Accumulate, SignednessSTD::Signed);
}
bool TranslatorVisitor::SABDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::None, Signedness::Signed);
+ return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::None, SignednessSTD::Signed);
}
bool TranslatorVisitor::SADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Addition, Signedness::Signed);
+ return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Addition, SignednessSTD::Signed);
}
bool TranslatorVisitor::SADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Addition, Signedness::Signed);
+ return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Addition, SignednessSTD::Signed);
}
bool TranslatorVisitor::SMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, SignednessSTD::Signed);
}
bool TranslatorVisitor::SMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, SignednessSTD::Signed);
}
bool TranslatorVisitor::SMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, SignednessSTD::Signed);
}
bool TranslatorVisitor::SSUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Subtraction, Signedness::Signed);
+ return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Subtraction, SignednessSTD::Signed);
}
bool TranslatorVisitor::SSUBL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Subtraction, Signedness::Signed);
+ return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Subtraction, SignednessSTD::Signed);
}
bool TranslatorVisitor::UADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Addition, Signedness::Unsigned);
+ return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Addition, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::Accumulate, Signedness::Unsigned);
+ return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::Accumulate, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UABDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::None, Signedness::Unsigned);
+ return AbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::None, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Addition, Signedness::Unsigned);
+ return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Addition, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::UMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::USUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Subtraction, Signedness::Unsigned);
+ return WideOperation(*this, Q, size, Vm, Vn, Vd, WideOperationBehavior::Subtraction, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::USUBL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Subtraction, Signedness::Unsigned);
+ return LongOperation(*this, Q, size, Vm, Vn, Vd, LongOperationBehavior::Subtraction, SignednessSTD::Unsigned);
}
bool TranslatorVisitor::SQDMULL_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_same.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_same.cpp
index 5c8bf13aeb..1cfc2ced78 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_same.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_three_same.cpp
@@ -12,12 +12,12 @@ enum class Operation {
Subtract,
};
-enum class ExtraBehavior {
+enum class ExtraBehaviorSTS {
None,
Round
};
-bool HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Operation op, ExtraBehavior behavior) {
+bool HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Operation op, ExtraBehaviorSTS behavior) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -35,7 +35,7 @@ bool HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V
return v.ir.VectorSub(doubled_esize, operand1, operand2);
}();
- if (behavior == ExtraBehavior::Round) {
+ if (behavior == ExtraBehaviorSTS::Round) {
const u64 round_const = 1ULL << (esize - 1);
const IR::U128 round_operand = v.ir.VectorBroadcast(doubled_esize, v.I(doubled_esize, round_const));
wide = v.ir.VectorAdd(doubled_esize, wide, round_operand);
@@ -48,12 +48,12 @@ bool HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V
return true;
}
-enum class AbsDiffExtraBehavior {
+enum class AbsDiffExtraBehaviorSTS {
None,
Accumulate
};
-bool SignedAbsoluteDifference(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, AbsDiffExtraBehavior behavior) {
+bool SignedAbsoluteDifference(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, AbsDiffExtraBehaviorSTS behavior) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -66,7 +66,7 @@ bool SignedAbsoluteDifference(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm,
const IR::U128 result = [&] {
const IR::U128 tmp = v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2);
- if (behavior == AbsDiffExtraBehavior::Accumulate) {
+ if (behavior == AbsDiffExtraBehaviorSTS::Accumulate) {
const IR::U128 d = v.V(datasize, Vd);
return v.ir.VectorAdd(esize, d, tmp);
}
@@ -78,12 +78,12 @@ bool SignedAbsoluteDifference(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm,
return true;
}
-enum class Signedness {
+enum class SignednessSTS {
Signed,
Unsigned
};
-bool RoundingHalvingAdd(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) {
+bool RoundingHalvingAdd(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, SignednessSTS sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -93,14 +93,14 @@ bool RoundingHalvingAdd(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec V
const IR::U128 operand1 = v.V(datasize, Vm);
const IR::U128 operand2 = v.V(datasize, Vn);
- const IR::U128 result = sign == Signedness::Signed ? v.ir.VectorRoundingHalvingAddSigned(esize, operand1, operand2)
+ const IR::U128 result = sign == SignednessSTS::Signed ? v.ir.VectorRoundingHalvingAddSigned(esize, operand1, operand2)
: v.ir.VectorRoundingHalvingAddUnsigned(esize, operand1, operand2);
v.V(datasize, Vd, result);
return true;
}
-bool RoundingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) {
+bool RoundingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, SignednessSTS sign) {
if (size == 0b11 && !Q) {
return v.ReservedValue();
}
@@ -111,7 +111,7 @@ bool RoundingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn
const IR::U128 operand1 = v.V(datasize, Vn);
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTS::Signed) {
return v.ir.VectorRoundingShiftLeftSigned(esize, operand1, operand2);
}
@@ -122,7 +122,7 @@ bool RoundingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn
return true;
}
-enum class ComparisonType {
+enum class ComparisonTypeSTS {
EQ,
GE,
AbsoluteGE,
@@ -130,7 +130,7 @@ enum class ComparisonType {
AbsoluteGT
};
-bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, ComparisonType type) {
+bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, ComparisonTypeSTS type) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -142,17 +142,17 @@ bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
switch (type) {
- case ComparisonType::EQ:
+ case ComparisonTypeSTS::EQ:
return v.ir.FPVectorEqual(esize, operand1, operand2);
- case ComparisonType::GE:
+ case ComparisonTypeSTS::GE:
return v.ir.FPVectorGreaterEqual(esize, operand1, operand2);
- case ComparisonType::AbsoluteGE:
+ case ComparisonTypeSTS::AbsoluteGE:
return v.ir.FPVectorGreaterEqual(esize,
v.ir.FPVectorAbs(esize, operand1),
v.ir.FPVectorAbs(esize, operand2));
- case ComparisonType::GT:
+ case ComparisonTypeSTS::GT:
return v.ir.FPVectorGreater(esize, operand1, operand2);
- case ComparisonType::AbsoluteGT:
+ case ComparisonTypeSTS::AbsoluteGT:
return v.ir.FPVectorGreater(esize,
v.ir.FPVectorAbs(esize, operand1),
v.ir.FPVectorAbs(esize, operand2));
@@ -165,12 +165,12 @@ bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
return true;
}
-enum class MinMaxOperation {
+enum class MinMaxOperationSTS {
Min,
Max,
};
-bool VectorMinMaxOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MinMaxOperation operation, Signedness sign) {
+bool VectorMinMaxOperationSTS(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MinMaxOperationSTS operation, SignednessSTS sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -182,14 +182,14 @@ bool VectorMinMaxOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Ve
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
switch (operation) {
- case MinMaxOperation::Max:
- if (sign == Signedness::Signed) {
+ case MinMaxOperationSTS::Max:
+ if (sign == SignednessSTS::Signed) {
return v.ir.VectorMaxSigned(esize, operand1, operand2);
}
return v.ir.VectorMaxUnsigned(esize, operand1, operand2);
- case MinMaxOperation::Min:
- if (sign == Signedness::Signed) {
+ case MinMaxOperationSTS::Min:
+ if (sign == SignednessSTS::Signed) {
return v.ir.VectorMinSigned(esize, operand1, operand2);
}
return v.ir.VectorMinUnsigned(esize, operand1, operand2);
@@ -203,7 +203,7 @@ bool VectorMinMaxOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Ve
return true;
}
-bool FPMinMaxOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, MinMaxOperation operation) {
+bool FPMinMaxOperationSTS(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, MinMaxOperationSTS operation) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -214,7 +214,7 @@ bool FPMinMaxOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
const IR::U128 operand1 = v.V(datasize, Vn);
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
- if (operation == MinMaxOperation::Min) {
+ if (operation == MinMaxOperationSTS::Min) {
return v.ir.FPVectorMin(esize, operand1, operand2);
}
@@ -225,7 +225,7 @@ bool FPMinMaxOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
return true;
}
-bool FPMinMaxNumericOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, MinMaxOperation operation) {
+bool FPMinMaxNumericOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd, MinMaxOperationSTS operation) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -236,7 +236,7 @@ bool FPMinMaxNumericOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec
const IR::U128 operand1 = v.V(datasize, Vn);
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
- if (operation == MinMaxOperation::Min) {
+ if (operation == MinMaxOperationSTS::Min) {
return v.ir.FPVectorMinNumeric(esize, operand1, operand2);
}
@@ -247,7 +247,7 @@ bool FPMinMaxNumericOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec
return true;
}
-bool PairedMinMaxOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MinMaxOperation operation, Signedness sign) {
+bool PairedMinMaxOperationSTS(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, MinMaxOperationSTS operation, SignednessSTS sign) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -259,14 +259,14 @@ bool PairedMinMaxOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Ve
const IR::U128 operand2 = v.V(datasize, Vm);
IR::U128 result = [&] {
switch (operation) {
- case MinMaxOperation::Max:
- if (sign == Signedness::Signed) {
+ case MinMaxOperationSTS::Max:
+ if (sign == SignednessSTS::Signed) {
return Q ? v.ir.VectorPairedMaxSigned(esize, operand1, operand2) : v.ir.VectorPairedMaxSignedLower(esize, operand1, operand2);
}
return Q ? v.ir.VectorPairedMaxUnsigned(esize, operand1, operand2) : v.ir.VectorPairedMaxUnsignedLower(esize, operand1, operand2);
- case MinMaxOperation::Min:
- if (sign == Signedness::Signed) {
+ case MinMaxOperationSTS::Min:
+ if (sign == SignednessSTS::Signed) {
return Q ? v.ir.VectorPairedMinSigned(esize, operand1, operand2) : v.ir.VectorPairedMinSignedLower(esize, operand1, operand2);
}
return Q ? v.ir.VectorPairedMinUnsigned(esize, operand1, operand2) : v.ir.VectorPairedMinUnsignedLower(esize, operand1, operand2);
@@ -311,7 +311,7 @@ bool FPPairedMinMax(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Vec V
return true;
}
-bool SaturatingArithmeticOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Operation op, Signedness sign) {
+bool SaturatingArithmeticOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Operation op, SignednessSTS sign) {
if (size == 0b11 && !Q) {
return v.ReservedValue();
}
@@ -323,7 +323,7 @@ bool SaturatingArithmeticOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Ve
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTS::Signed) {
if (op == Operation::Add) {
return v.ir.VectorSignedSaturatedAdd(esize, operand1, operand2);
}
@@ -342,7 +342,7 @@ bool SaturatingArithmeticOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Ve
return true;
}
-bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) {
+bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, SignednessSTS sign) {
if (size == 0b11 && !Q) {
return v.ReservedValue();
}
@@ -353,7 +353,7 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec
const IR::U128 operand1 = v.V(datasize, Vn);
const IR::U128 operand2 = v.V(datasize, Vm);
const IR::U128 result = [&] {
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTS::Signed) {
return v.ir.VectorSignedSaturatedShiftLeft(esize, operand1, operand2);
}
@@ -401,27 +401,27 @@ bool TranslatorVisitor::CMGE_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd)
}
bool TranslatorVisitor::SABA(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SignedAbsoluteDifference(*this, Q, size, Vm, Vn, Vd, AbsDiffExtraBehavior::Accumulate);
+ return SignedAbsoluteDifference(*this, Q, size, Vm, Vn, Vd, AbsDiffExtraBehaviorSTS::Accumulate);
}
bool TranslatorVisitor::SABD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SignedAbsoluteDifference(*this, Q, size, Vm, Vn, Vd, AbsDiffExtraBehavior::None);
+ return SignedAbsoluteDifference(*this, Q, size, Vm, Vn, Vd, AbsDiffExtraBehaviorSTS::None);
}
bool TranslatorVisitor::SMAX(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return VectorMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Max, Signedness::Signed);
+ return VectorMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Max, SignednessSTS::Signed);
}
bool TranslatorVisitor::SMAXP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return PairedMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Max, Signedness::Signed);
+ return PairedMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Max, SignednessSTS::Signed);
}
bool TranslatorVisitor::SMIN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return VectorMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Min, Signedness::Signed);
+ return VectorMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Min, SignednessSTS::Signed);
}
bool TranslatorVisitor::SMINP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return PairedMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Min, Signedness::Signed);
+ return PairedMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Min, SignednessSTS::Signed);
}
bool TranslatorVisitor::SQDMULH_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -506,19 +506,19 @@ bool TranslatorVisitor::MUL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::ADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, ExtraBehavior::None);
+ return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, ExtraBehaviorSTS::None);
}
bool TranslatorVisitor::RADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, ExtraBehavior::Round);
+ return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, ExtraBehaviorSTS::Round);
}
bool TranslatorVisitor::SUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, ExtraBehavior::None);
+ return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, ExtraBehaviorSTS::None);
}
bool TranslatorVisitor::RSUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, ExtraBehavior::Round);
+ return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, ExtraBehaviorSTS::Round);
}
bool TranslatorVisitor::SHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -554,15 +554,15 @@ bool TranslatorVisitor::SHSUB(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SQADD_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, Signedness::Signed);
+ return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, SignednessSTS::Signed);
}
bool TranslatorVisitor::SQSUB_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, Signedness::Signed);
+ return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, SignednessSTS::Signed);
}
bool TranslatorVisitor::SRHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingHalvingAdd(*this, Q, size, Vm, Vn, Vd, Signedness::Signed);
+ return RoundingHalvingAdd(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Signed);
}
bool TranslatorVisitor::UHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -598,15 +598,15 @@ bool TranslatorVisitor::UHSUB(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::UQADD_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, Signedness::Unsigned);
+ return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Add, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::UQSUB_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, Signedness::Unsigned);
+ return SaturatingArithmeticOperation(*this, Q, size, Vm, Vn, Vd, Operation::Subtract, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::URHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingHalvingAdd(*this, Q, size, Vm, Vn, Vd, Signedness::Unsigned);
+ return RoundingHalvingAdd(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::ADDP_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -642,11 +642,11 @@ bool TranslatorVisitor::FABD_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FACGE_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonType::AbsoluteGE);
+ return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonTypeSTS::AbsoluteGE);
}
bool TranslatorVisitor::FACGT_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonType::AbsoluteGT);
+ return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonTypeSTS::AbsoluteGT);
}
bool TranslatorVisitor::FADD_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
@@ -737,15 +737,15 @@ bool TranslatorVisitor::FCMEQ_reg_3(bool Q, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCMEQ_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonType::EQ);
+ return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonTypeSTS::EQ);
}
bool TranslatorVisitor::FCMGE_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonType::GE);
+ return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonTypeSTS::GE);
}
bool TranslatorVisitor::FCMGT_reg_4(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonType::GT);
+ return FPCompareRegister(*this, Q, sz, Vm, Vn, Vd, ComparisonTypeSTS::GT);
}
bool TranslatorVisitor::AND_asimd(bool Q, Vec Vm, Vec Vn, Vec Vd) {
@@ -827,11 +827,11 @@ bool TranslatorVisitor::CMTST_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SQSHL_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Signed);
+ return SaturatingShiftLeft(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Signed);
}
bool TranslatorVisitor::SRSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Signed);
+ return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Signed);
}
bool TranslatorVisitor::SSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -851,11 +851,11 @@ bool TranslatorVisitor::SSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::UQSHL_reg_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return SaturatingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Unsigned);
+ return SaturatingShiftLeft(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::URSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Unsigned);
+ return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::USHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -875,11 +875,11 @@ bool TranslatorVisitor::USHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::UMAX(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return VectorMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Max, Signedness::Unsigned);
+ return VectorMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Max, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::UMAXP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return PairedMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Max, Signedness::Unsigned);
+ return PairedMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Max, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::UABA(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
@@ -918,11 +918,11 @@ bool TranslatorVisitor::UABD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::UMIN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return VectorMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Min, Signedness::Unsigned);
+ return VectorMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Min, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::UMINP(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
- return PairedMinMaxOperation(*this, Q, size, Vm, Vn, Vd, MinMaxOperation::Min, Signedness::Unsigned);
+ return PairedMinMaxOperationSTS(*this, Q, size, Vm, Vn, Vd, MinMaxOperationSTS::Min, SignednessSTS::Unsigned);
}
bool TranslatorVisitor::FSUB_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
@@ -1104,11 +1104,11 @@ bool TranslatorVisitor::EOR_asimd(bool Q, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FMAX_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPMinMaxOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperation::Max);
+ return FPMinMaxOperationSTS(*this, Q, sz, Vm, Vn, Vd, MinMaxOperationSTS::Max);
}
bool TranslatorVisitor::FMAXNM_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPMinMaxNumericOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperation::Max);
+ return FPMinMaxNumericOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperationSTS::Max);
}
bool TranslatorVisitor::FMAXNMP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
@@ -1120,11 +1120,11 @@ bool TranslatorVisitor::FMAXP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FMIN_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPMinMaxOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperation::Min);
+ return FPMinMaxOperationSTS(*this, Q, sz, Vm, Vn, Vd, MinMaxOperationSTS::Min);
}
bool TranslatorVisitor::FMINNM_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
- return FPMinMaxNumericOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperation::Min);
+ return FPMinMaxNumericOperation(*this, Q, sz, Vm, Vn, Vd, MinMaxOperationSTS::Min);
}
bool TranslatorVisitor::FMINNMP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp
index ca3e3b9591..80a8e531a7 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_two_register_misc.cpp
@@ -8,7 +8,7 @@
namespace Dynarmic::A64 {
namespace {
-enum class ComparisonType {
+enum class ComparisonTypeSTRM {
EQ,
GE,
GT,
@@ -16,7 +16,7 @@ enum class ComparisonType {
LT,
};
-bool CompareAgainstZero(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, ComparisonType type) {
+bool CompareAgainstZero(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, ComparisonTypeSTRM type) {
if (size == 0b11 && !Q) {
return v.ReservedValue();
}
@@ -28,15 +28,15 @@ bool CompareAgainstZero(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec V
const IR::U128 zero = v.ir.ZeroVector();
IR::U128 result = [&] {
switch (type) {
- case ComparisonType::EQ:
+ case ComparisonTypeSTRM::EQ:
return v.ir.VectorEqual(esize, operand, zero);
- case ComparisonType::GE:
+ case ComparisonTypeSTRM::GE:
return v.ir.VectorGreaterEqualSigned(esize, operand, zero);
- case ComparisonType::GT:
+ case ComparisonTypeSTRM::GT:
return v.ir.VectorGreaterSigned(esize, operand, zero);
- case ComparisonType::LE:
+ case ComparisonTypeSTRM::LE:
return v.ir.VectorLessEqualSigned(esize, operand, zero);
- case ComparisonType::LT:
+ case ComparisonTypeSTRM::LT:
default:
return v.ir.VectorLessSigned(esize, operand, zero);
}
@@ -50,7 +50,7 @@ bool CompareAgainstZero(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec V
return true;
}
-bool FPCompareAgainstZero(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, ComparisonType type) {
+bool FPCompareAgainstZero(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, ComparisonTypeSTRM type) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -62,15 +62,15 @@ bool FPCompareAgainstZero(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd,
const IR::U128 zero = v.ir.ZeroVector();
const IR::U128 result = [&] {
switch (type) {
- case ComparisonType::EQ:
+ case ComparisonTypeSTRM::EQ:
return v.ir.FPVectorEqual(esize, operand, zero);
- case ComparisonType::GE:
+ case ComparisonTypeSTRM::GE:
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
- case ComparisonType::GT:
+ case ComparisonTypeSTRM::GT:
return v.ir.FPVectorGreater(esize, operand, zero);
- case ComparisonType::LE:
+ case ComparisonTypeSTRM::LE:
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
- case ComparisonType::LT:
+ case ComparisonTypeSTRM::LT:
return v.ir.FPVectorGreater(esize, zero, operand);
}
@@ -81,12 +81,12 @@ bool FPCompareAgainstZero(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd,
return true;
}
-enum class Signedness {
+enum class SignednessSTRM {
Signed,
Unsigned
};
-bool IntegerConvertToFloat(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, Signedness signedness) {
+bool IntegerConvertToFloat(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, SignednessSTRM SignednessSTRM) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -96,7 +96,7 @@ bool IntegerConvertToFloat(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd
const FP::RoundingMode rounding_mode = v.ir.current_location->FPCR().RMode();
const IR::U128 operand = v.V(datasize, Vn);
- const IR::U128 result = signedness == Signedness::Signed
+ const IR::U128 result = SignednessSTRM == SignednessSTRM::Signed
? v.ir.FPVectorFromSignedFixed(esize, operand, 0, rounding_mode)
: v.ir.FPVectorFromUnsignedFixed(esize, operand, 0, rounding_mode);
@@ -104,7 +104,7 @@ bool IntegerConvertToFloat(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd
return true;
}
-bool FloatConvertToInteger(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, Signedness signedness, FP::RoundingMode rounding_mode) {
+bool FloatConvertToInteger(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd, SignednessSTRM SignednessSTRM, FP::RoundingMode rounding_mode) {
if (sz && !Q) {
return v.ReservedValue();
}
@@ -113,7 +113,7 @@ bool FloatConvertToInteger(TranslatorVisitor& v, bool Q, bool sz, Vec Vn, Vec Vd
const size_t esize = sz ? 64 : 32;
const IR::U128 operand = v.V(datasize, Vn);
- const IR::U128 result = signedness == Signedness::Signed
+ const IR::U128 result = SignednessSTRM == SignednessSTRM::Signed
? v.ir.FPVectorToSignedFixed(esize, operand, 0, rounding_mode)
: v.ir.FPVectorToUnsignedFixed(esize, operand, 0, rounding_mode);
@@ -168,7 +168,7 @@ enum class PairedAddLongExtraBehavior {
Accumulate,
};
-bool PairedAddLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, Signedness sign, PairedAddLongExtraBehavior behavior) {
+bool PairedAddLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, SignednessSTRM sign, PairedAddLongExtraBehavior behavior) {
if (size == 0b11) {
return v.ReservedValue();
}
@@ -178,7 +178,7 @@ bool PairedAddLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vn, Vec Vd, Si
const IR::U128 operand = v.V(datasize, Vn);
IR::U128 result = [&] {
- if (sign == Signedness::Signed) {
+ if (sign == SignednessSTRM::Signed) {
return v.ir.VectorPairedAddSignedWiden(esize, operand);
}
@@ -254,23 +254,23 @@ bool TranslatorVisitor::CNT(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::CMGE_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonType::GE);
+ return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonTypeSTRM::GE);
}
bool TranslatorVisitor::CMGT_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonType::GT);
+ return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonTypeSTRM::GT);
}
bool TranslatorVisitor::CMEQ_zero_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonType::EQ);
+ return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonTypeSTRM::EQ);
}
bool TranslatorVisitor::CMLE_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonType::LE);
+ return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonTypeSTRM::LE);
}
bool TranslatorVisitor::CMLT_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonType::LT);
+ return CompareAgainstZero(*this, Q, size, Vn, Vd, ComparisonTypeSTRM::LT);
}
bool TranslatorVisitor::ABS_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
@@ -341,23 +341,23 @@ bool TranslatorVisitor::FCMEQ_zero_3(bool Q, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCMEQ_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonType::EQ);
+ return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonTypeSTRM::EQ);
}
bool TranslatorVisitor::FCMGE_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonType::GE);
+ return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonTypeSTRM::GE);
}
bool TranslatorVisitor::FCMGT_zero_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonType::GT);
+ return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonTypeSTRM::GT);
}
bool TranslatorVisitor::FCMLE_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonType::LE);
+ return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonTypeSTRM::LE);
}
bool TranslatorVisitor::FCMLT_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonType::LT);
+ return FPCompareAgainstZero(*this, Q, sz, Vn, Vd, ComparisonTypeSTRM::LT);
}
bool TranslatorVisitor::FCVTL(bool Q, bool sz, Vec Vn, Vec Vd) {
@@ -411,19 +411,19 @@ bool TranslatorVisitor::FCVTN(bool Q, bool sz, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCVTNS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Signed, FP::RoundingMode::ToNearest_TieEven);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed, FP::RoundingMode::ToNearest_TieEven);
}
bool TranslatorVisitor::FCVTMS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Signed, FP::RoundingMode::TowardsMinusInfinity);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed, FP::RoundingMode::TowardsMinusInfinity);
}
bool TranslatorVisitor::FCVTAS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Signed, FP::RoundingMode::ToNearest_TieAwayFromZero);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed, FP::RoundingMode::ToNearest_TieAwayFromZero);
}
bool TranslatorVisitor::FCVTPS_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Signed, FP::RoundingMode::TowardsPlusInfinity);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed, FP::RoundingMode::TowardsPlusInfinity);
}
bool TranslatorVisitor::FCVTXN_2(bool Q, bool sz, Vec Vn, Vec Vd) {
@@ -447,27 +447,27 @@ bool TranslatorVisitor::FCVTXN_2(bool Q, bool sz, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::FCVTZS_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Signed, FP::RoundingMode::TowardsZero);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::FCVTNU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::ToNearest_TieEven);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned, FP::RoundingMode::ToNearest_TieEven);
}
bool TranslatorVisitor::FCVTMU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::TowardsMinusInfinity);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned, FP::RoundingMode::TowardsMinusInfinity);
}
bool TranslatorVisitor::FCVTAU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::ToNearest_TieAwayFromZero);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned, FP::RoundingMode::ToNearest_TieAwayFromZero);
}
bool TranslatorVisitor::FCVTPU_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::TowardsPlusInfinity);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned, FP::RoundingMode::TowardsPlusInfinity);
}
bool TranslatorVisitor::FCVTZU_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return FloatConvertToInteger(*this, Q, sz, Vn, Vd, Signedness::Unsigned, FP::RoundingMode::TowardsZero);
+ return FloatConvertToInteger(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::FRINTN_1(bool Q, Vec Vn, Vec Vd) {
@@ -780,19 +780,19 @@ bool TranslatorVisitor::USQADD_2(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SADALP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return PairedAddLong(*this, Q, size, Vn, Vd, Signedness::Signed, PairedAddLongExtraBehavior::Accumulate);
+ return PairedAddLong(*this, Q, size, Vn, Vd, SignednessSTRM::Signed, PairedAddLongExtraBehavior::Accumulate);
}
bool TranslatorVisitor::SADDLP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return PairedAddLong(*this, Q, size, Vn, Vd, Signedness::Signed, PairedAddLongExtraBehavior::None);
+ return PairedAddLong(*this, Q, size, Vn, Vd, SignednessSTRM::Signed, PairedAddLongExtraBehavior::None);
}
bool TranslatorVisitor::UADALP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return PairedAddLong(*this, Q, size, Vn, Vd, Signedness::Unsigned, PairedAddLongExtraBehavior::Accumulate);
+ return PairedAddLong(*this, Q, size, Vn, Vd, SignednessSTRM::Unsigned, PairedAddLongExtraBehavior::Accumulate);
}
bool TranslatorVisitor::UADDLP(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
- return PairedAddLong(*this, Q, size, Vn, Vd, Signedness::Unsigned, PairedAddLongExtraBehavior::None);
+ return PairedAddLong(*this, Q, size, Vn, Vd, SignednessSTRM::Unsigned, PairedAddLongExtraBehavior::None);
}
bool TranslatorVisitor::URECPE(bool Q, bool sz, Vec Vn, Vec Vd) {
@@ -824,11 +824,11 @@ bool TranslatorVisitor::URSQRTE(bool Q, bool sz, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::SCVTF_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return IntegerConvertToFloat(*this, Q, sz, Vn, Vd, Signedness::Signed);
+ return IntegerConvertToFloat(*this, Q, sz, Vn, Vd, SignednessSTRM::Signed);
}
bool TranslatorVisitor::UCVTF_int_4(bool Q, bool sz, Vec Vn, Vec Vd) {
- return IntegerConvertToFloat(*this, Q, sz, Vn, Vd, Signedness::Unsigned);
+ return IntegerConvertToFloat(*this, Q, sz, Vn, Vd, SignednessSTRM::Unsigned);
}
bool TranslatorVisitor::SHLL(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
diff --git a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
index 07234fc61b..d23b5fc144 100644
--- a/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
+++ b/externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
@@ -11,7 +11,7 @@
namespace Dynarmic::A64 {
namespace {
-std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
+std::pair<size_t, Vec> CombineVector(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
if (size == 0b01) {
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
}
@@ -19,19 +19,19 @@ std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4>
return {concatenate(H, L).ZeroExtend(), concatenate(M, Vmlo).ZeroExtend<Vec>()};
}
-enum class ExtraBehavior {
+enum class ExtraBehaviorSVXIE {
None,
Extended,
Accumulate,
Subtract,
};
-bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehavior extra_behavior) {
+bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehaviorSVXIE extra_behavior) {
if (size != 0b01 && size != 0b10) {
return v.ReservedValue();
}
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineVector(size, H, L, M, Vmlo);
const size_t idxdsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend();
const size_t datasize = Q ? 128 : 64;
@@ -41,9 +41,9 @@ bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<
const IR::U128 operand3 = v.V(datasize, Vd);
IR::U128 result = v.ir.VectorMultiply(esize, operand1, operand2);
- if (extra_behavior == ExtraBehavior::Accumulate) {
+ if (extra_behavior == ExtraBehaviorSVXIE::Accumulate) {
result = v.ir.VectorAdd(esize, operand3, result);
- } else if (extra_behavior == ExtraBehavior::Subtract) {
+ } else if (extra_behavior == ExtraBehaviorSVXIE::Subtract) {
result = v.ir.VectorSub(esize, operand3, result);
}
@@ -51,7 +51,7 @@ bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<
return true;
}
-bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehavior extra_behavior) {
+bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehaviorSVXIE extra_behavior) {
if (sz && L == 1) {
return v.ReservedValue();
}
@@ -71,13 +71,13 @@ bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1>
const IR::U128 result = [&] {
switch (extra_behavior) {
- case ExtraBehavior::None:
+ case ExtraBehaviorSVXIE::None:
return v.ir.FPVectorMul(esize, operand1, operand2);
- case ExtraBehavior::Extended:
+ case ExtraBehaviorSVXIE::Extended:
return v.ir.FPVectorMulX(esize, operand1, operand2);
- case ExtraBehavior::Accumulate:
+ case ExtraBehaviorSVXIE::Accumulate:
return v.ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
- case ExtraBehavior::Subtract:
+ case ExtraBehaviorSVXIE::Subtract:
return v.ir.FPVectorMulAdd(esize, operand3, v.ir.FPVectorNeg(esize, operand1), operand2);
}
UNREACHABLE();
@@ -86,7 +86,7 @@ bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1>
return true;
}
-bool FPMultiplyByElementHalfPrecision(TranslatorVisitor& v, bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehavior extra_behavior) {
+bool FPMultiplyByElementHalfPrecision(TranslatorVisitor& v, bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehaviorSVXIE extra_behavior) {
const size_t idxdsize = H == 1 ? 128 : 64;
const size_t index = concatenate(H, L, M).ZeroExtend();
const Vec Vm = Vmlo.ZeroExtend<Vec>();
@@ -101,13 +101,13 @@ bool FPMultiplyByElementHalfPrecision(TranslatorVisitor& v, bool Q, Imm<1> L, Im
// regular multiplies and extended multiplies.
const IR::U128 result = [&] {
switch (extra_behavior) {
- case ExtraBehavior::None:
+ case ExtraBehaviorSVXIE::None:
break;
- case ExtraBehavior::Extended:
+ case ExtraBehaviorSVXIE::Extended:
break;
- case ExtraBehavior::Accumulate:
+ case ExtraBehaviorSVXIE::Accumulate:
return v.ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
- case ExtraBehavior::Subtract:
+ case ExtraBehaviorSVXIE::Subtract:
return v.ir.FPVectorMulAdd(esize, operand3, v.ir.FPVectorNeg(esize, operand1), operand2);
}
UNREACHABLE();
@@ -151,12 +151,12 @@ bool DotProduct(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
return true;
}
-enum class Signedness {
+enum class SignednessSVXIE {
Signed,
Unsigned
};
-bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehavior extra_behavior, Signedness sign) {
+bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, ExtraBehaviorSVXIE extra_behavior, SignednessSVXIE sign) {
if (size == 0b00 || size == 0b11) {
return v.ReservedValue();
}
@@ -164,23 +164,23 @@ bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M,
const size_t idxsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend();
const size_t datasize = 64;
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineVector(size, H, L, M, Vmlo);
const IR::U128 operand1 = v.Vpart(datasize, Vn, Q);
const IR::U128 operand2 = v.V(idxsize, Vm);
const IR::U128 index_vector = v.ir.VectorBroadcastElement(esize, operand2, index);
const IR::U128 result = [&] {
- const IR::U128 product = sign == Signedness::Signed
+ const IR::U128 product = sign == SignednessSVXIE::Signed
? v.ir.VectorMultiplySignedWiden(esize, operand1, index_vector)
: v.ir.VectorMultiplyUnsignedWiden(esize, operand1, index_vector);
- if (extra_behavior == ExtraBehavior::None) {
+ if (extra_behavior == ExtraBehaviorSVXIE::None) {
return product;
}
const IR::U128 operand3 = v.V(2 * datasize, Vd);
- if (extra_behavior == ExtraBehavior::Accumulate) {
+ if (extra_behavior == ExtraBehaviorSVXIE::Accumulate) {
return v.ir.VectorAdd(2 * esize, operand3, product);
}
@@ -193,15 +193,15 @@ bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M,
} // Anonymous namespace
bool TranslatorVisitor::MLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate);
+ return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Accumulate);
}
bool TranslatorVisitor::MLS_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract);
+ return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Subtract);
}
bool TranslatorVisitor::MUL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None);
+ return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::None);
}
bool TranslatorVisitor::FCMLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<2> rot, Imm<1> H, Vec Vn, Vec Vd) {
@@ -292,39 +292,39 @@ bool TranslatorVisitor::FCMLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4
}
bool TranslatorVisitor::FMLA_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElementHalfPrecision(*this, Q, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate);
+ return FPMultiplyByElementHalfPrecision(*this, Q, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Accumulate);
}
bool TranslatorVisitor::FMLA_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate);
+ return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Accumulate);
}
bool TranslatorVisitor::FMLS_elt_3(bool Q, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElementHalfPrecision(*this, Q, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract);
+ return FPMultiplyByElementHalfPrecision(*this, Q, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Subtract);
}
bool TranslatorVisitor::FMLS_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract);
+ return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Subtract);
}
bool TranslatorVisitor::FMUL_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None);
+ return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::None);
}
bool TranslatorVisitor::FMULX_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Extended);
+ return FPMultiplyByElement(*this, Q, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Extended);
}
bool TranslatorVisitor::SMLAL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Accumulate, SignednessSVXIE::Signed);
}
bool TranslatorVisitor::SMLSL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Subtract, SignednessSVXIE::Signed);
}
bool TranslatorVisitor::SMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None, Signedness::Signed);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::None, SignednessSVXIE::Signed);
}
bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
@@ -336,7 +336,7 @@ bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
const size_t idxsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend();
const size_t datasize = 64;
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineVector(size, H, L, M, Vmlo);
const IR::U128 operand1 = Vpart(datasize, Vn, part);
const IR::U128 operand2 = V(idxsize, Vm);
@@ -355,7 +355,7 @@ bool TranslatorVisitor::SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
const size_t idxsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend();
const size_t datasize = Q ? 128 : 64;
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineVector(size, H, L, M, Vmlo);
const IR::U128 operand1 = V(datasize, Vn);
const IR::U128 operand2 = V(idxsize, Vm);
@@ -374,7 +374,7 @@ bool TranslatorVisitor::SQRDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M,
const size_t idxsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend();
const size_t datasize = Q ? 128 : 64;
- const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
+ const auto [index, Vm] = CombineVector(size, H, L, M, Vmlo);
const IR::U128 operand1 = V(datasize, Vn);
const IR::U128 operand2 = V(idxsize, Vm);
@@ -394,15 +394,15 @@ bool TranslatorVisitor::UDOT_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4>
}
bool TranslatorVisitor::UMLAL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Accumulate, SignednessSVXIE::Unsigned);
}
bool TranslatorVisitor::UMLSL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::Subtract, SignednessSVXIE::Unsigned);
}
bool TranslatorVisitor::UMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
- return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None, Signedness::Unsigned);
+ return MultiplyLong(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehaviorSVXIE::None, SignednessSVXIE::Unsigned);
}
} // namespace Dynarmic::A64
diff --git a/externals/dynarmic/src/dynarmic/interface/A32/arch_version.h b/externals/dynarmic/src/dynarmic/interface/A32/arch_version.h
index 240e40ee4c..209bc594f2 100644
--- a/externals/dynarmic/src/dynarmic/interface/A32/arch_version.h
+++ b/externals/dynarmic/src/dynarmic/interface/A32/arch_version.h
@@ -5,10 +5,12 @@
#pragma once
+#include <stdint.h>
+
namespace Dynarmic {
namespace A32 {
-enum class ArchVersion {
+enum class ArchVersion : std::uint8_t {
v3,
v4,
v4T,
diff --git a/externals/dynarmic/src/dynarmic/interface/A32/config.h b/externals/dynarmic/src/dynarmic/interface/A32/config.h
index 360df06e2a..033967dc00 100644
--- a/externals/dynarmic/src/dynarmic/interface/A32/config.h
+++ b/externals/dynarmic/src/dynarmic/interface/A32/config.h
@@ -120,14 +120,32 @@ struct UserCallbacks : public TranslateCallbacks {
};
struct UserConfig {
+ bool HasOptimization(OptimizationFlag f) const {
+ if (!unsafe_optimizations) {
+ f &= all_safe_optimizations;
+ }
+ return (f & optimizations) != no_optimizations;
+ }
+
UserCallbacks* callbacks;
- size_t processor_id = 0;
ExclusiveMonitor* global_monitor = nullptr;
- /// Select the architecture version to use.
- /// There are minor behavioural differences between versions.
- ArchVersion arch_version = ArchVersion::v8;
+ // Page Table
+ // The page table is used for faster memory access. If an entry in the table is nullptr,
+ // the JIT will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
+ static constexpr std::size_t PAGE_BITS = 12;
+ static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS);
+ std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>* page_table = nullptr;
+
+ /// Coprocessors
+ std::array<std::shared_ptr<Coprocessor>, 16> coprocessors{};
+
+ /// Fastmem Pointer
+ /// This should point to the beginning of a 4GB address space which is in arranged just like
+ /// what you wish for emulated memory to be. If the host page faults on an address, the JIT
+ /// will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
+ std::optional<uintptr_t> fastmem_pointer = std::nullopt;
/// This selects other optimizations than can't otherwise be disabled by setting other
/// configuration options. This includes:
@@ -137,12 +155,29 @@ struct UserConfig {
/// This is intended to be used for debugging.
OptimizationFlag optimizations = all_safe_optimizations;
- bool HasOptimization(OptimizationFlag f) const {
- if (!unsafe_optimizations) {
- f &= all_safe_optimizations;
- }
- return (f & optimizations) != no_optimizations;
- }
+ /// Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
+ /// Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
+ std::uint32_t code_cache_size = 128 * 1024 * 1024; // bytes
+
+ /// Processor ID
+ std::uint32_t processor_id = 0;
+
+ /// Masks out the first N bits in host pointers from the page table.
+ /// The intention behind this is to allow users of Dynarmic to pack attributes in the
+ /// same integer and update the pointer attribute pair atomically.
+ /// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
+ std::int32_t page_table_pointer_mask_bits = 0;
+
+ /// Select the architecture version to use.
+ /// There are minor behavioural differences between versions.
+ ArchVersion arch_version = ArchVersion::v8;
+
+ /// Determines if we should detect memory accesses via page_table that straddle are
+ /// misaligned. Accesses that straddle page boundaries will fallback to the relevant
+ /// memory callback.
+ /// This value should be the required access sizes this applies to ORed together.
+ /// To detect any access, use: 8 | 16 | 32 | 64.
+ std::uint8_t detect_misaligned_access_via_page_table = 0;
/// This enables unsafe optimizations that reduce emulation accuracy in favour of speed.
/// For safety, in order to enable unsafe optimizations you have to set BOTH this flag
@@ -150,12 +185,6 @@ struct UserConfig {
/// The prefered and tested mode for this library is with unsafe optimizations disabled.
bool unsafe_optimizations = false;
- // Page Table
- // The page table is used for faster memory access. If an entry in the table is nullptr,
- // the JIT will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
- static constexpr std::size_t PAGE_BITS = 12;
- static constexpr std::size_t NUM_PAGE_TABLE_ENTRIES = 1 << (32 - PAGE_BITS);
- std::array<std::uint8_t*, NUM_PAGE_TABLE_ENTRIES>* page_table = nullptr;
/// Determines if the pointer in the page_table shall be offseted locally or globally.
/// 'false' will access page_table[addr >> bits][addr & mask]
/// 'true' will access page_table[addr >> bits][addr]
@@ -163,26 +192,11 @@ struct UserConfig {
/// So there might be wrongly faulted pages which maps to nullptr.
/// This can be avoided by carefully allocating the memory region.
bool absolute_offset_page_table = false;
- /// Masks out the first N bits in host pointers from the page table.
- /// The intention behind this is to allow users of Dynarmic to pack attributes in the
- /// same integer and update the pointer attribute pair atomically.
- /// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
- int page_table_pointer_mask_bits = 0;
- /// Determines if we should detect memory accesses via page_table that straddle are
- /// misaligned. Accesses that straddle page boundaries will fallback to the relevant
- /// memory callback.
- /// This value should be the required access sizes this applies to ORed together.
- /// To detect any access, use: 8 | 16 | 32 | 64.
- std::uint8_t detect_misaligned_access_via_page_table = 0;
+
/// Determines if the above option only triggers when the misalignment straddles a
/// page boundary.
bool only_detect_misalignment_via_page_table_on_page_boundary = false;
- // Fastmem Pointer
- // This should point to the beginning of a 4GB address space which is in arranged just like
- // what you wish for emulated memory to be. If the host page faults on an address, the JIT
- // will fallback to calling the MemoryRead*/MemoryWrite* callbacks.
- std::optional<uintptr_t> fastmem_pointer = std::nullopt;
/// Determines if instructions that pagefault should cause recompilation of that block
/// with fastmem disabled.
/// Recompiled code will use the page_table if this is available, otherwise memory
@@ -198,9 +212,6 @@ struct UserConfig {
/// callbacks.
bool recompile_on_exclusive_fastmem_failure = true;
- // Coprocessors
- std::array<std::shared_ptr<Coprocessor>, 16> coprocessors{};
-
/// When set to true, UserCallbacks::InstructionSynchronizationBarrierRaised will be
/// called when an ISB instruction is executed.
/// When set to false, ISB will be treated as a NOP instruction.
@@ -234,10 +245,6 @@ struct UserConfig {
/// in unusual behavior.
bool always_little_endian = false;
- // Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
- // Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
- size_t code_cache_size = 128 * 1024 * 1024; // bytes
-
/// Internal use only
bool very_verbose_debugging_output = false;
};
diff --git a/externals/dynarmic/src/dynarmic/interface/A64/config.h b/externals/dynarmic/src/dynarmic/interface/A64/config.h
index c8ed623eb4..3563c0b2f4 100644
--- a/externals/dynarmic/src/dynarmic/interface/A64/config.h
+++ b/externals/dynarmic/src/dynarmic/interface/A64/config.h
@@ -136,11 +136,30 @@ struct UserCallbacks {
};
struct UserConfig {
+ /// Fastmem Pointer
+ /// This should point to the beginning of a 2^page_table_address_space_bits bytes
+ /// address space which is in arranged just like what you wish for emulated memory to
+ /// be. If the host page faults on an address, the JIT will fallback to calling the
+ /// MemoryRead*/MemoryWrite* callbacks.
+ std::optional<std::uintptr_t> fastmem_pointer = std::nullopt;
+
UserCallbacks* callbacks;
- size_t processor_id = 0;
ExclusiveMonitor* global_monitor = nullptr;
+ /// Pointer to where TPIDRRO_EL0 is stored. This pointer will be inserted into
+ /// emitted code.
+ const std::uint64_t* tpidrro_el0 = nullptr;
+
+ /// Pointer to where TPIDR_EL0 is stored. This pointer will be inserted into
+ /// emitted code.
+ std::uint64_t* tpidr_el0 = nullptr;
+
+ /// Pointer to the page table which we can use for direct page table access.
+ /// If an entry in page_table is null, the relevant memory callback will be called.
+ /// If page_table is nullptr, all memory accesses hit the memory callbacks.
+ void** page_table = nullptr;
+
/// This selects other optimizations than can't otherwise be disabled by setting other
/// configuration options. This includes:
/// - IR optimizations
@@ -149,12 +168,50 @@ struct UserConfig {
/// This is intended to be used for debugging.
OptimizationFlag optimizations = all_safe_optimizations;
- bool HasOptimization(OptimizationFlag f) const {
- if (!unsafe_optimizations) {
- f &= all_safe_optimizations;
- }
- return (f & optimizations) != no_optimizations;
- }
+ /// Declares how many valid address bits are there in virtual addresses.
+ /// Determines the size of page_table. Valid values are between 12 and 64 inclusive.
+ /// This is only used if page_table is not nullptr.
+ std::uint32_t page_table_address_space_bits = 36;
+
+ /// Masks out the first N bits in host pointers from the page table.
+ /// The intention behind this is to allow users of Dynarmic to pack attributes in the
+ /// same integer and update the pointer attribute pair atomically.
+ /// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
+ std::int32_t page_table_pointer_mask_bits = 0;
+
+ /// Counter-timer frequency register. The value of the register is not interpreted by
+ /// dynarmic.
+ std::uint32_t cntfrq_el0 = 600000000;
+
+ /// CTR_EL0<27:24> is log2 of the cache writeback granule in words.
+ /// CTR_EL0<23:20> is log2 of the exclusives reservation granule in words.
+ /// CTR_EL0<19:16> is log2 of the smallest data/unified cacheline in words.
+ /// CTR_EL0<15:14> is the level 1 instruction cache policy.
+ /// CTR_EL0<3:0> is log2 of the smallest instruction cacheline in words.
+ std::uint32_t ctr_el0 = 0x8444c004;
+
+ /// DCZID_EL0<3:0> is log2 of the block size in words
+ /// DCZID_EL0<4> is 0 if the DC ZVA instruction is permitted.
+ std::uint32_t dczid_el0 = 4;
+
+ /// Declares how many valid address bits are there in virtual addresses.
+ /// Determines the size of fastmem arena. Valid values are between 12 and 64 inclusive.
+ /// This is only used if fastmem_pointer is set.
+ std::uint32_t fastmem_address_space_bits = 36;
+
+ // Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
+ // Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
+ std::uint32_t code_cache_size = 128 * 1024 * 1024; // bytes
+
+ /// Determines if we should detect memory accesses via page_table that straddle are
+ /// misaligned. Accesses that straddle page boundaries will fallback to the relevant
+ /// memory callback.
+ /// This value should be the required access sizes this applies to ORed together.
+ /// To detect any access, use: 8 | 16 | 32 | 64 | 128.
+ std::uint8_t detect_misaligned_access_via_page_table = 0;
+
+ /// Processor ID
+ std::uint8_t processor_id = 0;
/// This enables unsafe optimizations that reduce emulation accuracy in favour of speed.
/// For safety, in order to enable unsafe optimizations you have to set BOTH this flag
@@ -177,48 +234,13 @@ struct UserConfig {
/// instruction is executed.
bool hook_hint_instructions = false;
- /// Counter-timer frequency register. The value of the register is not interpreted by
- /// dynarmic.
- std::uint32_t cntfrq_el0 = 600000000;
-
- /// CTR_EL0<27:24> is log2 of the cache writeback granule in words.
- /// CTR_EL0<23:20> is log2 of the exclusives reservation granule in words.
- /// CTR_EL0<19:16> is log2 of the smallest data/unified cacheline in words.
- /// CTR_EL0<15:14> is the level 1 instruction cache policy.
- /// CTR_EL0<3:0> is log2 of the smallest instruction cacheline in words.
- std::uint32_t ctr_el0 = 0x8444c004;
-
- /// DCZID_EL0<3:0> is log2 of the block size in words
- /// DCZID_EL0<4> is 0 if the DC ZVA instruction is permitted.
- std::uint32_t dczid_el0 = 4;
-
- /// Pointer to where TPIDRRO_EL0 is stored. This pointer will be inserted into
- /// emitted code.
- const std::uint64_t* tpidrro_el0 = nullptr;
-
- /// Pointer to where TPIDR_EL0 is stored. This pointer will be inserted into
- /// emitted code.
- std::uint64_t* tpidr_el0 = nullptr;
-
- /// Pointer to the page table which we can use for direct page table access.
- /// If an entry in page_table is null, the relevant memory callback will be called.
- /// If page_table is nullptr, all memory accesses hit the memory callbacks.
- void** page_table = nullptr;
- /// Declares how many valid address bits are there in virtual addresses.
- /// Determines the size of page_table. Valid values are between 12 and 64 inclusive.
- /// This is only used if page_table is not nullptr.
- size_t page_table_address_space_bits = 36;
- /// Masks out the first N bits in host pointers from the page table.
- /// The intention behind this is to allow users of Dynarmic to pack attributes in the
- /// same integer and update the pointer attribute pair atomically.
- /// If the configured value is 3, all pointers will be forcefully aligned to 8 bytes.
- int page_table_pointer_mask_bits = 0;
/// Determines what happens if the guest accesses an entry that is off the end of the
/// page table. If true, Dynarmic will silently mirror page_table's address space. If
/// false, accessing memory outside of page_table bounds will result in a call to the
/// relevant memory callback.
/// This is only used if page_table is not nullptr.
bool silently_mirror_page_table = true;
+
/// Determines if the pointer in the page_table shall be offseted locally or globally.
/// 'false' will access page_table[addr >> bits][addr & mask]
/// 'true' will access page_table[addr >> bits][addr]
@@ -226,31 +248,17 @@ struct UserConfig {
/// So there might be wrongly faulted pages which maps to nullptr.
/// This can be avoided by carefully allocating the memory region.
bool absolute_offset_page_table = false;
- /// Determines if we should detect memory accesses via page_table that straddle are
- /// misaligned. Accesses that straddle page boundaries will fallback to the relevant
- /// memory callback.
- /// This value should be the required access sizes this applies to ORed together.
- /// To detect any access, use: 8 | 16 | 32 | 64 | 128.
- std::uint8_t detect_misaligned_access_via_page_table = 0;
+
/// Determines if the above option only triggers when the misalignment straddles a
/// page boundary.
bool only_detect_misalignment_via_page_table_on_page_boundary = false;
- /// Fastmem Pointer
- /// This should point to the beginning of a 2^page_table_address_space_bits bytes
- /// address space which is in arranged just like what you wish for emulated memory to
- /// be. If the host page faults on an address, the JIT will fallback to calling the
- /// MemoryRead*/MemoryWrite* callbacks.
- std::optional<uintptr_t> fastmem_pointer = std::nullopt;
/// Determines if instructions that pagefault should cause recompilation of that block
/// with fastmem disabled.
/// Recompiled code will use the page_table if this is available, otherwise memory
/// accesses will hit the memory callbacks.
bool recompile_on_fastmem_failure = true;
- /// Declares how many valid address bits are there in virtual addresses.
- /// Determines the size of fastmem arena. Valid values are between 12 and 64 inclusive.
- /// This is only used if fastmem_pointer is set.
- size_t fastmem_address_space_bits = 36;
+
/// Determines what happens if the guest accesses an entry that is off the end of the
/// fastmem arena. If true, Dynarmic will silently mirror fastmem's address space. If
/// false, accessing memory outside of fastmem bounds will result in a call to the
@@ -285,12 +293,15 @@ struct UserConfig {
/// AddTicks and GetTicksRemaining are never called, and no cycle counting is done.
bool enable_cycle_counting = true;
- // Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
- // Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
- size_t code_cache_size = 128 * 1024 * 1024; // bytes
-
/// Internal use only
bool very_verbose_debugging_output = false;
+
+ inline bool HasOptimization(OptimizationFlag f) const {
+ if (!unsafe_optimizations) {
+ f &= all_safe_optimizations;
+ }
+ return (f & optimizations) != no_optimizations;
+ }
};
} // namespace A64
diff --git a/externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp b/externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp
index fc4f69b3e0..3734aae4d5 100644
--- a/externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp
+++ b/externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp
@@ -14,2877 +14,5 @@
namespace Dynarmic::IR {
-U1 IREmitter::Imm1(bool imm1) const {
- return U1(Value(imm1));
-}
-
-U8 IREmitter::Imm8(u8 imm8) const {
- return U8(Value(imm8));
-}
-
-U16 IREmitter::Imm16(u16 imm16) const {
- return U16(Value(imm16));
-}
-
-U32 IREmitter::Imm32(u32 imm32) const {
- return U32(Value(imm32));
-}
-
-U64 IREmitter::Imm64(u64 imm64) const {
- return U64(Value(imm64));
-}
-
-void IREmitter::PushRSB(const LocationDescriptor& return_location) {
- Inst(Opcode::PushRSB, IR::Value(return_location.Value()));
-}
-
-U64 IREmitter::Pack2x32To1x64(const U32& lo, const U32& hi) {
- return Inst<U64>(Opcode::Pack2x32To1x64, lo, hi);
-}
-
-U128 IREmitter::Pack2x64To1x128(const U64& lo, const U64& hi) {
- return Inst<U128>(Opcode::Pack2x64To1x128, lo, hi);
-}
-
-UAny IREmitter::LeastSignificant(size_t bitsize, const U32U64& value) {
- switch (bitsize) {
- case 8:
- return LeastSignificantByte(value);
- case 16:
- return LeastSignificantHalf(value);
- case 32:
- if (value.GetType() == Type::U32) {
- return value;
- }
- return LeastSignificantWord(value);
- case 64:
- ASSERT(value.GetType() == Type::U64);
- return value;
- }
- ASSERT_FALSE("Invalid bitsize");
-}
-
-U32 IREmitter::LeastSignificantWord(const U64& value) {
- return Inst<U32>(Opcode::LeastSignificantWord, value);
-}
-
-U16 IREmitter::LeastSignificantHalf(U32U64 value) {
- if (value.GetType() == Type::U64) {
- value = LeastSignificantWord(value);
- }
- return Inst<U16>(Opcode::LeastSignificantHalf, value);
-}
-
-U8 IREmitter::LeastSignificantByte(U32U64 value) {
- if (value.GetType() == Type::U64) {
- value = LeastSignificantWord(value);
- }
- return Inst<U8>(Opcode::LeastSignificantByte, value);
-}
-
-ResultAndCarry<U32> IREmitter::MostSignificantWord(const U64& value) {
- const auto result = Inst<U32>(Opcode::MostSignificantWord, value);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-U1 IREmitter::MostSignificantBit(const U32& value) {
- return Inst<U1>(Opcode::MostSignificantBit, value);
-}
-
-U1 IREmitter::IsZero(const U32& value) {
- return Inst<U1>(Opcode::IsZero32, value);
-}
-
-U1 IREmitter::IsZero(const U64& value) {
- return Inst<U1>(Opcode::IsZero64, value);
-}
-
-U1 IREmitter::IsZero(const U32U64& value) {
- if (value.GetType() == Type::U32) {
- return Inst<U1>(Opcode::IsZero32, value);
- } else {
- return Inst<U1>(Opcode::IsZero64, value);
- }
-}
-
-U1 IREmitter::TestBit(const U32U64& value, const U8& bit) {
- if (value.GetType() == Type::U32) {
- return Inst<U1>(Opcode::TestBit, IndeterminateExtendToLong(value), bit);
- } else {
- return Inst<U1>(Opcode::TestBit, value, bit);
- }
-}
-
-U32 IREmitter::ConditionalSelect(Cond cond, const U32& a, const U32& b) {
- return Inst<U32>(Opcode::ConditionalSelect32, Value{cond}, a, b);
-}
-
-U64 IREmitter::ConditionalSelect(Cond cond, const U64& a, const U64& b) {
- return Inst<U64>(Opcode::ConditionalSelect64, Value{cond}, a, b);
-}
-
-NZCV IREmitter::ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b) {
- return Inst<NZCV>(Opcode::ConditionalSelectNZCV, Value{cond}, a, b);
-}
-
-U32U64 IREmitter::ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::ConditionalSelect32, Value{cond}, a, b);
- } else {
- return Inst<U64>(Opcode::ConditionalSelect64, Value{cond}, a, b);
- }
-}
-
-U1 IREmitter::GetCFlagFromNZCV(const NZCV& nzcv) {
- return Inst<U1>(Opcode::GetCFlagFromNZCV, nzcv);
-}
-
-NZCV IREmitter::NZCVFromPackedFlags(const U32& a) {
- return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
-}
-
-NZCV IREmitter::NZCVFrom(const Value& value) {
- return Inst<NZCV>(Opcode::GetNZCVFromOp, value);
-}
-
-ResultAndCarry<U32> IREmitter::LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
- const auto result = Inst<U32>(Opcode::LogicalShiftLeft32, value_in, shift_amount, carry_in);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-ResultAndCarry<U32> IREmitter::LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
- const auto result = Inst<U32>(Opcode::LogicalShiftRight32, value_in, shift_amount, carry_in);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-ResultAndCarry<U32> IREmitter::ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
- const auto result = Inst<U32>(Opcode::ArithmeticShiftRight32, value_in, shift_amount, carry_in);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-ResultAndCarry<U32> IREmitter::RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
- const auto result = Inst<U32>(Opcode::RotateRight32, value_in, shift_amount, carry_in);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-ResultAndCarry<U32> IREmitter::RotateRightExtended(const U32& value_in, const U1& carry_in) {
- const auto result = Inst<U32>(Opcode::RotateRightExtended, value_in, carry_in);
- const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
- return {result, carry_out};
-}
-
-U32U64 IREmitter::LogicalShiftLeft(const U32U64& value_in, const U8& shift_amount) {
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::LogicalShiftLeft32, value_in, shift_amount, Imm1(0));
- } else {
- return Inst<U64>(Opcode::LogicalShiftLeft64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::LogicalShiftRight(const U32U64& value_in, const U8& shift_amount) {
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::LogicalShiftRight32, value_in, shift_amount, Imm1(0));
- } else {
- return Inst<U64>(Opcode::LogicalShiftRight64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::ArithmeticShiftRight(const U32U64& value_in, const U8& shift_amount) {
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::ArithmeticShiftRight32, value_in, shift_amount, Imm1(0));
- } else {
- return Inst<U64>(Opcode::ArithmeticShiftRight64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::RotateRight(const U32U64& value_in, const U8& shift_amount) {
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::RotateRight32, value_in, shift_amount, Imm1(0));
- } else {
- return Inst<U64>(Opcode::RotateRight64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::LogicalShiftLeftMasked(const U32U64& value_in, const U32U64& shift_amount) {
- ASSERT(value_in.GetType() == shift_amount.GetType());
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::LogicalShiftLeftMasked32, value_in, shift_amount);
- } else {
- return Inst<U64>(Opcode::LogicalShiftLeftMasked64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::LogicalShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
- ASSERT(value_in.GetType() == shift_amount.GetType());
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::LogicalShiftRightMasked32, value_in, shift_amount);
- } else {
- return Inst<U64>(Opcode::LogicalShiftRightMasked64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::ArithmeticShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
- ASSERT(value_in.GetType() == shift_amount.GetType());
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::ArithmeticShiftRightMasked32, value_in, shift_amount);
- } else {
- return Inst<U64>(Opcode::ArithmeticShiftRightMasked64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::RotateRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
- ASSERT(value_in.GetType() == shift_amount.GetType());
- if (value_in.GetType() == Type::U32) {
- return Inst<U32>(Opcode::RotateRightMasked32, value_in, shift_amount);
- } else {
- return Inst<U64>(Opcode::RotateRightMasked64, value_in, shift_amount);
- }
-}
-
-U32U64 IREmitter::AddWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Add32, a, b, carry_in);
- } else {
- return Inst<U64>(Opcode::Add64, a, b, carry_in);
- }
-}
-
-U32U64 IREmitter::Add(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Add32, a, b, Imm1(0));
- } else {
- return Inst<U64>(Opcode::Add64, a, b, Imm1(0));
- }
-}
-
-U32U64 IREmitter::SubWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Sub32, a, b, carry_in);
- } else {
- return Inst<U64>(Opcode::Sub64, a, b, carry_in);
- }
-}
-
-U32U64 IREmitter::Sub(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Sub32, a, b, Imm1(1));
- } else {
- return Inst<U64>(Opcode::Sub64, a, b, Imm1(1));
- }
-}
-
-U32U64 IREmitter::Mul(const U32U64& a, const U32U64& b) {
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Mul32, a, b);
- }
-
- return Inst<U64>(Opcode::Mul64, a, b);
-}
-
-U64 IREmitter::UnsignedMultiplyHigh(const U64& a, const U64& b) {
- return Inst<U64>(Opcode::UnsignedMultiplyHigh64, a, b);
-}
-
-U64 IREmitter::SignedMultiplyHigh(const U64& a, const U64& b) {
- return Inst<U64>(Opcode::SignedMultiplyHigh64, a, b);
-}
-
-U32U64 IREmitter::UnsignedDiv(const U32U64& a, const U32U64& b) {
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::UnsignedDiv32, a, b);
- }
-
- return Inst<U64>(Opcode::UnsignedDiv64, a, b);
-}
-
-U32U64 IREmitter::SignedDiv(const U32U64& a, const U32U64& b) {
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::SignedDiv32, a, b);
- }
-
- return Inst<U64>(Opcode::SignedDiv64, a, b);
-}
-
-U32U64 IREmitter::And(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::And32, a, b);
- } else {
- return Inst<U64>(Opcode::And64, a, b);
- }
-}
-
-U32U64 IREmitter::AndNot(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::AndNot32, a, b);
- } else {
- return Inst<U64>(Opcode::AndNot64, a, b);
- }
-}
-
-U32U64 IREmitter::Eor(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Eor32, a, b);
- } else {
- return Inst<U64>(Opcode::Eor64, a, b);
- }
-}
-
-U32U64 IREmitter::Or(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Or32, a, b);
- } else {
- return Inst<U64>(Opcode::Or64, a, b);
- }
-}
-
-U32U64 IREmitter::Not(const U32U64& a) {
- if (a.GetType() == Type::U32) {
- return Inst<U32>(Opcode::Not32, a);
- } else {
- return Inst<U64>(Opcode::Not64, a);
- }
-}
-
-U64 IREmitter::SignExtendToLong(const UAny& a) {
- switch (a.GetType()) {
- case Type::U8:
- return Inst<U64>(Opcode::SignExtendByteToLong, a);
- case Type::U16:
- return Inst<U64>(Opcode::SignExtendHalfToLong, a);
- case Type::U32:
- return Inst<U64>(Opcode::SignExtendWordToLong, a);
- case Type::U64:
- return U64(a);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::SignExtendToWord(const UAny& a) {
- switch (a.GetType()) {
- case Type::U8:
- return Inst<U32>(Opcode::SignExtendByteToWord, a);
- case Type::U16:
- return Inst<U32>(Opcode::SignExtendHalfToWord, a);
- case Type::U32:
- return U32(a);
- case Type::U64:
- return Inst<U32>(Opcode::LeastSignificantWord, a);
- default:
- UNREACHABLE();
- }
-}
-
-U64 IREmitter::SignExtendWordToLong(const U32& a) {
- return Inst<U64>(Opcode::SignExtendWordToLong, a);
-}
-
-U32 IREmitter::SignExtendHalfToWord(const U16& a) {
- return Inst<U32>(Opcode::SignExtendHalfToWord, a);
-}
-
-U32 IREmitter::SignExtendByteToWord(const U8& a) {
- return Inst<U32>(Opcode::SignExtendByteToWord, a);
-}
-
-U64 IREmitter::ZeroExtendToLong(const UAny& a) {
- switch (a.GetType()) {
- case Type::U8:
- return Inst<U64>(Opcode::ZeroExtendByteToLong, a);
- case Type::U16:
- return Inst<U64>(Opcode::ZeroExtendHalfToLong, a);
- case Type::U32:
- return Inst<U64>(Opcode::ZeroExtendWordToLong, a);
- case Type::U64:
- return U64(a);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::ZeroExtendToWord(const UAny& a) {
- switch (a.GetType()) {
- case Type::U8:
- return Inst<U32>(Opcode::ZeroExtendByteToWord, a);
- case Type::U16:
- return Inst<U32>(Opcode::ZeroExtendHalfToWord, a);
- case Type::U32:
- return U32(a);
- case Type::U64:
- return Inst<U32>(Opcode::LeastSignificantWord, a);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::ZeroExtendToQuad(const UAny& a) {
- return Inst<U128>(Opcode::ZeroExtendLongToQuad, ZeroExtendToLong(a));
-}
-
-U64 IREmitter::ZeroExtendWordToLong(const U32& a) {
- return Inst<U64>(Opcode::ZeroExtendWordToLong, a);
-}
-
-U32 IREmitter::ZeroExtendHalfToWord(const U16& a) {
- return Inst<U32>(Opcode::ZeroExtendHalfToWord, a);
-}
-
-U32 IREmitter::ZeroExtendByteToWord(const U8& a) {
- return Inst<U32>(Opcode::ZeroExtendByteToWord, a);
-}
-
-U32 IREmitter::IndeterminateExtendToWord(const UAny& a) {
- // TODO: Implement properly
- return ZeroExtendToWord(a);
-}
-
-U64 IREmitter::IndeterminateExtendToLong(const UAny& a) {
- // TODO: Implement properly
- return ZeroExtendToLong(a);
-}
-
-U32 IREmitter::ByteReverseWord(const U32& a) {
- return Inst<U32>(Opcode::ByteReverseWord, a);
-}
-
-U16 IREmitter::ByteReverseHalf(const U16& a) {
- return Inst<U16>(Opcode::ByteReverseHalf, a);
-}
-
-U64 IREmitter::ByteReverseDual(const U64& a) {
- return Inst<U64>(Opcode::ByteReverseDual, a);
-}
-
-U32U64 IREmitter::CountLeadingZeros(const U32U64& a) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::CountLeadingZeros32, a);
- }
-
- return Inst<U64>(Opcode::CountLeadingZeros64, a);
-}
-
-U32U64 IREmitter::ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::ExtractRegister32, a, b, lsb);
- }
-
- return Inst<U64>(Opcode::ExtractRegister64, a, b, lsb);
-}
-
-U32U64 IREmitter::ReplicateBit(const U32U64& a, u8 bit) {
- if (a.GetType() == IR::Type::U32) {
- ASSERT(bit < 32);
- return Inst<U32>(Opcode::ReplicateBit32, a, Imm8(bit));
- }
-
- ASSERT(bit < 64);
- return Inst<U64>(Opcode::ReplicateBit64, a, Imm8(bit));
-}
-
-U32U64 IREmitter::MaxSigned(const U32U64& a, const U32U64& b) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::MaxSigned32, a, b);
- }
-
- return Inst<U64>(Opcode::MaxSigned64, a, b);
-}
-
-U32U64 IREmitter::MaxUnsigned(const U32U64& a, const U32U64& b) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::MaxUnsigned32, a, b);
- }
-
- return Inst<U64>(Opcode::MaxUnsigned64, a, b);
-}
-
-U32U64 IREmitter::MinSigned(const U32U64& a, const U32U64& b) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::MinSigned32, a, b);
- }
-
- return Inst<U64>(Opcode::MinSigned64, a, b);
-}
-
-U32U64 IREmitter::MinUnsigned(const U32U64& a, const U32U64& b) {
- if (a.GetType() == IR::Type::U32) {
- return Inst<U32>(Opcode::MinUnsigned32, a, b);
- }
-
- return Inst<U64>(Opcode::MinUnsigned64, a, b);
-}
-
-ResultAndOverflow<U32> IREmitter::SignedSaturatedAddWithFlag(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::SignedSaturatedAddWithFlag32, a, b);
- const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
- return {result, overflow};
-}
-
-ResultAndOverflow<U32> IREmitter::SignedSaturatedSubWithFlag(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::SignedSaturatedSubWithFlag32, a, b);
- const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
- return {result, overflow};
-}
-
-ResultAndOverflow<U32> IREmitter::SignedSaturation(const U32& a, size_t bit_size_to_saturate_to) {
- ASSERT(bit_size_to_saturate_to >= 1 && bit_size_to_saturate_to <= 32);
- const auto result = Inst<U32>(Opcode::SignedSaturation, a, Imm8(static_cast<u8>(bit_size_to_saturate_to)));
- const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
- return {result, overflow};
-}
-
-ResultAndOverflow<U32> IREmitter::UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to) {
- ASSERT(bit_size_to_saturate_to <= 31);
- const auto result = Inst<U32>(Opcode::UnsignedSaturation, a, Imm8(static_cast<u8>(bit_size_to_saturate_to)));
- const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
- return {result, overflow};
-}
-
-UAny IREmitter::SignedSaturatedAdd(const UAny& a, const UAny& b) {
- ASSERT(a.GetType() == b.GetType());
- const auto result = [&]() -> IR::UAny {
- switch (a.GetType()) {
- case IR::Type::U8:
- return Inst<U8>(Opcode::SignedSaturatedAdd8, a, b);
- case IR::Type::U16:
- return Inst<U16>(Opcode::SignedSaturatedAdd16, a, b);
- case IR::Type::U32:
- return Inst<U32>(Opcode::SignedSaturatedAdd32, a, b);
- case IR::Type::U64:
- return Inst<U64>(Opcode::SignedSaturatedAdd64, a, b);
- default:
- return IR::UAny{};
- }
- }();
- return result;
-}
-
-UAny IREmitter::SignedSaturatedDoublingMultiplyReturnHigh(const UAny& a, const UAny& b) {
- ASSERT(a.GetType() == b.GetType());
- const auto result = [&]() -> IR::UAny {
- switch (a.GetType()) {
- case IR::Type::U16:
- return Inst<U16>(Opcode::SignedSaturatedDoublingMultiplyReturnHigh16, a, b);
- case IR::Type::U32:
- return Inst<U32>(Opcode::SignedSaturatedDoublingMultiplyReturnHigh32, a, b);
- default:
- UNREACHABLE();
- }
- }();
- return result;
-}
-
-UAny IREmitter::SignedSaturatedSub(const UAny& a, const UAny& b) {
- ASSERT(a.GetType() == b.GetType());
- const auto result = [&]() -> IR::UAny {
- switch (a.GetType()) {
- case IR::Type::U8:
- return Inst<U8>(Opcode::SignedSaturatedSub8, a, b);
- case IR::Type::U16:
- return Inst<U16>(Opcode::SignedSaturatedSub16, a, b);
- case IR::Type::U32:
- return Inst<U32>(Opcode::SignedSaturatedSub32, a, b);
- case IR::Type::U64:
- return Inst<U64>(Opcode::SignedSaturatedSub64, a, b);
- default:
- return IR::UAny{};
- }
- }();
- return result;
-}
-
-UAny IREmitter::UnsignedSaturatedAdd(const UAny& a, const UAny& b) {
- ASSERT(a.GetType() == b.GetType());
- const auto result = [&]() -> IR::UAny {
- switch (a.GetType()) {
- case IR::Type::U8:
- return Inst<U8>(Opcode::UnsignedSaturatedAdd8, a, b);
- case IR::Type::U16:
- return Inst<U16>(Opcode::UnsignedSaturatedAdd16, a, b);
- case IR::Type::U32:
- return Inst<U32>(Opcode::UnsignedSaturatedAdd32, a, b);
- case IR::Type::U64:
- return Inst<U64>(Opcode::UnsignedSaturatedAdd64, a, b);
- default:
- return IR::UAny{};
- }
- }();
- return result;
-}
-
-UAny IREmitter::UnsignedSaturatedSub(const UAny& a, const UAny& b) {
- ASSERT(a.GetType() == b.GetType());
- const auto result = [&]() -> IR::UAny {
- switch (a.GetType()) {
- case IR::Type::U8:
- return Inst<U8>(Opcode::UnsignedSaturatedSub8, a, b);
- case IR::Type::U16:
- return Inst<U16>(Opcode::UnsignedSaturatedSub16, a, b);
- case IR::Type::U32:
- return Inst<U32>(Opcode::UnsignedSaturatedSub32, a, b);
- case IR::Type::U64:
- return Inst<U64>(Opcode::UnsignedSaturatedSub64, a, b);
- default:
- return IR::UAny{};
- }
- }();
- return result;
-}
-
-U128 IREmitter::VectorSignedSaturatedAdd(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedAdd8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedAdd16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedAdd32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedAdd64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorSignedSaturatedSub(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedSub8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedSub16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedSub32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedSub64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorUnsignedSaturatedAdd(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorUnsignedSaturatedSub(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedSub8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedSub16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedSub32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedSub64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-ResultAndGE<U32> IREmitter::PackedAddU8(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddU8, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedAddS8(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddS8, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedAddU16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddU16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedAddS16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddS16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubU8(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubU8, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubS8(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubS8, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubU16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubU16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubS16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubS16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedAddSubU16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddSubU16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedAddSubS16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedAddSubS16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubAddU16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubAddU16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-ResultAndGE<U32> IREmitter::PackedSubAddS16(const U32& a, const U32& b) {
- const auto result = Inst<U32>(Opcode::PackedSubAddS16, a, b);
- const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
- return {result, ge};
-}
-
-U32 IREmitter::PackedHalvingAddU8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddU8, a, b);
-}
-
-U32 IREmitter::PackedHalvingAddS8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddS8, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubU8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubU8, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubS8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubS8, a, b);
-}
-
-U32 IREmitter::PackedHalvingAddU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddU16, a, b);
-}
-
-U32 IREmitter::PackedHalvingAddS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddS16, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubU16, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubS16, a, b);
-}
-
-U32 IREmitter::PackedHalvingAddSubU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddSubU16, a, b);
-}
-
-U32 IREmitter::PackedHalvingAddSubS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingAddSubS16, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubAddU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubAddU16, a, b);
-}
-
-U32 IREmitter::PackedHalvingSubAddS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedHalvingSubAddS16, a, b);
-}
-
-U32 IREmitter::PackedSaturatedAddU8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedAddU8, a, b);
-}
-
-U32 IREmitter::PackedSaturatedAddS8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedAddS8, a, b);
-}
-
-U32 IREmitter::PackedSaturatedSubU8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedSubU8, a, b);
-}
-
-U32 IREmitter::PackedSaturatedSubS8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedSubS8, a, b);
-}
-
-U32 IREmitter::PackedSaturatedAddU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedAddU16, a, b);
-}
-
-U32 IREmitter::PackedSaturatedAddS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedAddS16, a, b);
-}
-
-U32 IREmitter::PackedSaturatedSubU16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedSubU16, a, b);
-}
-
-U32 IREmitter::PackedSaturatedSubS16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSaturatedSubS16, a, b);
-}
-
-U32 IREmitter::PackedAbsDiffSumU8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedAbsDiffSumU8, a, b);
-}
-
-U32 IREmitter::PackedSelect(const U32& ge, const U32& a, const U32& b) {
- return Inst<U32>(Opcode::PackedSelect, ge, a, b);
-}
-
-U32 IREmitter::CRC32Castagnoli8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32Castagnoli8, a, b);
-}
-
-U32 IREmitter::CRC32Castagnoli16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32Castagnoli16, a, b);
-}
-
-U32 IREmitter::CRC32Castagnoli32(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32Castagnoli32, a, b);
-}
-
-U32 IREmitter::CRC32Castagnoli64(const U32& a, const U64& b) {
- return Inst<U32>(Opcode::CRC32Castagnoli64, a, b);
-}
-
-U32 IREmitter::CRC32ISO8(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32ISO8, a, b);
-}
-
-U32 IREmitter::CRC32ISO16(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32ISO16, a, b);
-}
-
-U32 IREmitter::CRC32ISO32(const U32& a, const U32& b) {
- return Inst<U32>(Opcode::CRC32ISO32, a, b);
-}
-
-U32 IREmitter::CRC32ISO64(const U32& a, const U64& b) {
- return Inst<U32>(Opcode::CRC32ISO64, a, b);
-}
-
-U128 IREmitter::AESDecryptSingleRound(const U128& a) {
- return Inst<U128>(Opcode::AESDecryptSingleRound, a);
-}
-
-U128 IREmitter::AESEncryptSingleRound(const U128& a) {
- return Inst<U128>(Opcode::AESEncryptSingleRound, a);
-}
-
-U128 IREmitter::AESInverseMixColumns(const U128& a) {
- return Inst<U128>(Opcode::AESInverseMixColumns, a);
-}
-
-U128 IREmitter::AESMixColumns(const U128& a) {
- return Inst<U128>(Opcode::AESMixColumns, a);
-}
-
-U8 IREmitter::SM4AccessSubstitutionBox(const U8& a) {
- return Inst<U8>(Opcode::SM4AccessSubstitutionBox, a);
-}
-
-U128 IREmitter::SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1) {
- return Inst<U128>(Opcode::SHA256Hash, x, y, w, Imm1(part1));
-}
-
-U128 IREmitter::SHA256MessageSchedule0(const U128& x, const U128& y) {
- return Inst<U128>(Opcode::SHA256MessageSchedule0, x, y);
-}
-
-U128 IREmitter::SHA256MessageSchedule1(const U128& x, const U128& y, const U128& z) {
- return Inst<U128>(Opcode::SHA256MessageSchedule1, x, y, z);
-}
-
-UAny IREmitter::VectorGetElement(size_t esize, const U128& a, size_t index) {
- ASSERT_MSG(esize * index < 128, "Invalid index");
- switch (esize) {
- case 8:
- return Inst<U8>(Opcode::VectorGetElement8, a, Imm8(static_cast<u8>(index)));
- case 16:
- return Inst<U16>(Opcode::VectorGetElement16, a, Imm8(static_cast<u8>(index)));
- case 32:
- return Inst<U32>(Opcode::VectorGetElement32, a, Imm8(static_cast<u8>(index)));
- case 64:
- return Inst<U64>(Opcode::VectorGetElement64, a, Imm8(static_cast<u8>(index)));
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorSetElement(size_t esize, const U128& a, size_t index, const IR::UAny& elem) {
- ASSERT_MSG(esize * index < 128, "Invalid index");
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSetElement8, a, Imm8(static_cast<u8>(index)), elem);
- case 16:
- return Inst<U128>(Opcode::VectorSetElement16, a, Imm8(static_cast<u8>(index)), elem);
- case 32:
- return Inst<U128>(Opcode::VectorSetElement32, a, Imm8(static_cast<u8>(index)), elem);
- case 64:
- return Inst<U128>(Opcode::VectorSetElement64, a, Imm8(static_cast<u8>(index)), elem);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorAbs(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorAbs8, a);
- case 16:
- return Inst<U128>(Opcode::VectorAbs16, a);
- case 32:
- return Inst<U128>(Opcode::VectorAbs32, a);
- case 64:
- return Inst<U128>(Opcode::VectorAbs64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorAdd(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorAdd8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorAdd16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorAdd32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorAdd64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorAnd(const U128& a, const U128& b) {
- return Inst<U128>(Opcode::VectorAnd, a, b);
-}
-
-U128 IREmitter::VectorAndNot(const U128& a, const U128& b) {
- return Inst<U128>(Opcode::VectorAndNot, a, b);
-}
-
-U128 IREmitter::VectorArithmeticShiftRight(size_t esize, const U128& a, u8 shift_amount) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorArithmeticShiftRight8, a, Imm8(shift_amount));
- case 16:
- return Inst<U128>(Opcode::VectorArithmeticShiftRight16, a, Imm8(shift_amount));
- case 32:
- return Inst<U128>(Opcode::VectorArithmeticShiftRight32, a, Imm8(shift_amount));
- case 64:
- return Inst<U128>(Opcode::VectorArithmeticShiftRight64, a, Imm8(shift_amount));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorArithmeticVShift(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorArithmeticVShift8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorArithmeticVShift16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorArithmeticVShift32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorArithmeticVShift64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorBroadcastLower(size_t esize, const UAny& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorBroadcastLower8, U8(a));
- case 16:
- return Inst<U128>(Opcode::VectorBroadcastLower16, U16(a));
- case 32:
- return Inst<U128>(Opcode::VectorBroadcastLower32, U32(a));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorBroadcast(size_t esize, const UAny& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorBroadcast8, U8(a));
- case 16:
- return Inst<U128>(Opcode::VectorBroadcast16, U16(a));
- case 32:
- return Inst<U128>(Opcode::VectorBroadcast32, U32(a));
- case 64:
- return Inst<U128>(Opcode::VectorBroadcast64, U64(a));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorBroadcastElementLower(size_t esize, const U128& a, size_t index) {
- ASSERT_MSG(esize * index < 128, "Invalid index");
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorBroadcastElementLower8, a, u8(index));
- case 16:
- return Inst<U128>(Opcode::VectorBroadcastElementLower16, a, u8(index));
- case 32:
- return Inst<U128>(Opcode::VectorBroadcastElementLower32, a, u8(index));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorBroadcastElement(size_t esize, const U128& a, size_t index) {
- ASSERT_MSG(esize * index < 128, "Invalid index");
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorBroadcastElement8, a, u8(index));
- case 16:
- return Inst<U128>(Opcode::VectorBroadcastElement16, a, u8(index));
- case 32:
- return Inst<U128>(Opcode::VectorBroadcastElement32, a, u8(index));
- case 64:
- return Inst<U128>(Opcode::VectorBroadcastElement64, a, u8(index));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorCountLeadingZeros(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorCountLeadingZeros8, a);
- case 16:
- return Inst<U128>(Opcode::VectorCountLeadingZeros16, a);
- case 32:
- return Inst<U128>(Opcode::VectorCountLeadingZeros32, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorDeinterleaveEven(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorDeinterleaveEven8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorDeinterleaveEven16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorDeinterleaveEven32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorDeinterleaveEven64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorDeinterleaveOdd(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorDeinterleaveOdd8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorDeinterleaveOdd16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorDeinterleaveOdd32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorDeinterleaveOdd64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorDeinterleaveEvenLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorDeinterleaveEvenLower8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorDeinterleaveEvenLower16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorDeinterleaveEvenLower32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorDeinterleaveOddLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorDeinterleaveOddLower8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorDeinterleaveOddLower16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorDeinterleaveOddLower32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorEor(const U128& a, const U128& b) {
- return Inst<U128>(Opcode::VectorEor, a, b);
-}
-
-U128 IREmitter::VectorEqual(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorEqual8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorEqual16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorEqual32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorEqual64, a, b);
- case 128:
- return Inst<U128>(Opcode::VectorEqual128, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorExtract(const U128& a, const U128& b, size_t position) {
- ASSERT(position <= 128);
- return Inst<U128>(Opcode::VectorExtract, a, b, Imm8(static_cast<u8>(position)));
-}
-
-U128 IREmitter::VectorExtractLower(const U128& a, const U128& b, size_t position) {
- ASSERT(position <= 64);
- return Inst<U128>(Opcode::VectorExtractLower, a, b, Imm8(static_cast<u8>(position)));
-}
-
-U128 IREmitter::VectorGreaterSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorGreaterS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorGreaterS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorGreaterS32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorGreaterS64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorGreaterEqualSigned(size_t esize, const U128& a, const U128& b) {
- return VectorOr(VectorGreaterSigned(esize, a, b), VectorEqual(esize, a, b));
-}
-
-U128 IREmitter::VectorGreaterEqualUnsigned(size_t esize, const U128& a, const U128& b) {
- return VectorEqual(esize, VectorMaxUnsigned(esize, a, b), a);
-}
-
-U128 IREmitter::VectorGreaterUnsigned(size_t esize, const U128& a, const U128& b) {
- return VectorNot(VectorEqual(esize, VectorMinUnsigned(esize, a, b), a));
-}
-
-U128 IREmitter::VectorHalvingAddSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorHalvingAddS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorHalvingAddS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorHalvingAddS32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorHalvingAddU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorHalvingAddU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorHalvingAddU32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorHalvingSubSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorHalvingSubS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorHalvingSubS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorHalvingSubS32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorHalvingSubUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorHalvingSubU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorHalvingSubU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorHalvingSubU32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorInterleaveLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorInterleaveLower8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorInterleaveLower16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorInterleaveLower32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorInterleaveLower64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorInterleaveUpper(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorInterleaveUpper8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorInterleaveUpper16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorInterleaveUpper32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorInterleaveUpper64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorLessEqualSigned(size_t esize, const U128& a, const U128& b) {
- return VectorNot(VectorGreaterSigned(esize, a, b));
-}
-
-U128 IREmitter::VectorLessEqualUnsigned(size_t esize, const U128& a, const U128& b) {
- return VectorEqual(esize, VectorMinUnsigned(esize, a, b), a);
-}
-
-U128 IREmitter::VectorLessSigned(size_t esize, const U128& a, const U128& b) {
- return VectorNot(VectorOr(VectorGreaterSigned(esize, a, b), VectorEqual(esize, a, b)));
-}
-
-U128 IREmitter::VectorLessUnsigned(size_t esize, const U128& a, const U128& b) {
- return VectorNot(VectorEqual(esize, VectorMaxUnsigned(esize, a, b), a));
-}
-
-U128 IREmitter::VectorLogicalShiftLeft(size_t esize, const U128& a, u8 shift_amount) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorLogicalShiftLeft8, a, Imm8(shift_amount));
- case 16:
- return Inst<U128>(Opcode::VectorLogicalShiftLeft16, a, Imm8(shift_amount));
- case 32:
- return Inst<U128>(Opcode::VectorLogicalShiftLeft32, a, Imm8(shift_amount));
- case 64:
- return Inst<U128>(Opcode::VectorLogicalShiftLeft64, a, Imm8(shift_amount));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorLogicalShiftRight(size_t esize, const U128& a, u8 shift_amount) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorLogicalShiftRight8, a, Imm8(shift_amount));
- case 16:
- return Inst<U128>(Opcode::VectorLogicalShiftRight16, a, Imm8(shift_amount));
- case 32:
- return Inst<U128>(Opcode::VectorLogicalShiftRight32, a, Imm8(shift_amount));
- case 64:
- return Inst<U128>(Opcode::VectorLogicalShiftRight64, a, Imm8(shift_amount));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorLogicalVShift(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorLogicalVShift8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorLogicalVShift16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorLogicalVShift32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorLogicalVShift64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMaxSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMaxS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMaxS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMaxS32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorMaxS64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMaxUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMaxU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMaxU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMaxU32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorMaxU64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMinSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMinS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMinS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMinS32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorMinS64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMinUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMinU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMinU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMinU32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorMinU64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMultiply(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMultiply8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMultiply16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMultiply32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorMultiply64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMultiplySignedWiden(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMultiplySignedWiden8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMultiplySignedWiden16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMultiplySignedWiden32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorMultiplyUnsignedWiden(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorNarrow(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 16:
- return Inst<U128>(Opcode::VectorNarrow16, a);
- case 32:
- return Inst<U128>(Opcode::VectorNarrow32, a);
- case 64:
- return Inst<U128>(Opcode::VectorNarrow64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorNot(const U128& a) {
- return Inst<U128>(Opcode::VectorNot, a);
-}
-
-U128 IREmitter::VectorOr(const U128& a, const U128& b) {
- return Inst<U128>(Opcode::VectorOr, a, b);
-}
-
-U128 IREmitter::VectorPairedAdd(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedAdd8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedAdd16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedAdd32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorPairedAdd64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorPairedAddLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedAddLower8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedAddLower16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedAddLower32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorPairedAddSignedWiden(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedAddSignedWiden8, a);
- case 16:
- return Inst<U128>(Opcode::VectorPairedAddSignedWiden16, a);
- case 32:
- return Inst<U128>(Opcode::VectorPairedAddSignedWiden32, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorPairedAddUnsignedWiden(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden8, a);
- case 16:
- return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden16, a);
- case 32:
- return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden32, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorPairedMaxSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMaxS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMaxS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMaxS32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMaxUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMaxU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMaxU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMaxU32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMinSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMinS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMinS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMinS32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMinUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMinU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMinU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMinU32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMaxSignedLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMaxLowerS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMaxLowerS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMaxLowerS32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMaxUnsignedLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMaxLowerU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMaxLowerU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMaxLowerU32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMinSignedLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMinLowerS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMinLowerS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMinLowerS32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPairedMinUnsignedLower(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPairedMinLowerU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorPairedMinLowerU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorPairedMinLowerU32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPolynomialMultiply(const U128& a, const U128& b) {
- return Inst<U128>(Opcode::VectorPolynomialMultiply8, a, b);
-}
-
-U128 IREmitter::VectorPolynomialMultiplyLong(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorPolynomialMultiplyLong8, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorPolynomialMultiplyLong64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorPopulationCount(const U128& a) {
- return Inst<U128>(Opcode::VectorPopulationCount, a);
-}
-
-U128 IREmitter::VectorReverseBits(const U128& a) {
- return Inst<U128>(Opcode::VectorReverseBits, a);
-}
-
-U128 IREmitter::VectorReverseElementsInHalfGroups(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorReverseElementsInHalfGroups8, a);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorReverseElementsInWordGroups(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorReverseElementsInWordGroups8, a);
- case 16:
- return Inst<U128>(Opcode::VectorReverseElementsInWordGroups16, a);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorReverseElementsInLongGroups(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorReverseElementsInLongGroups8, a);
- case 16:
- return Inst<U128>(Opcode::VectorReverseElementsInLongGroups16, a);
- case 32:
- return Inst<U128>(Opcode::VectorReverseElementsInLongGroups32, a);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorReduceAdd(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorReduceAdd8, a);
- case 16:
- return Inst<U128>(Opcode::VectorReduceAdd16, a);
- case 32:
- return Inst<U128>(Opcode::VectorReduceAdd32, a);
- case 64:
- return Inst<U128>(Opcode::VectorReduceAdd64, a);
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorRotateLeft(size_t esize, const U128& a, u8 amount) {
- ASSERT(amount < esize);
-
- if (amount == 0) {
- return a;
- }
-
- return VectorOr(VectorLogicalShiftLeft(esize, a, amount),
- VectorLogicalShiftRight(esize, a, static_cast<u8>(esize - amount)));
-}
-
-U128 IREmitter::VectorRotateRight(size_t esize, const U128& a, u8 amount) {
- ASSERT(amount < esize);
-
- if (amount == 0) {
- return a;
- }
-
- return VectorOr(VectorLogicalShiftRight(esize, a, amount),
- VectorLogicalShiftLeft(esize, a, static_cast<u8>(esize - amount)));
-}
-
-U128 IREmitter::VectorRotateWholeVectorRight(const U128& a, u8 amount) {
- ASSERT(amount % 32 == 0);
- return Inst<U128>(Opcode::VectorRotateWholeVectorRight, a, Imm8(amount));
-}
-
-U128 IREmitter::VectorRoundingHalvingAddSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddS32, a, b);
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorRoundingHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorRoundingHalvingAddU32, a, b);
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorRoundingShiftLeftSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftS8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftS16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftS32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftS64, a, b);
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorRoundingShiftLeftUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftU8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftU16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftU32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorRoundingShiftLeftU64, a, b);
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignExtend(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignExtend8, a);
- case 16:
- return Inst<U128>(Opcode::VectorSignExtend16, a);
- case 32:
- return Inst<U128>(Opcode::VectorSignExtend32, a);
- case 64:
- return Inst<U128>(Opcode::VectorSignExtend64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedAbsoluteDifference8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSignedAbsoluteDifference16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedAbsoluteDifference32, a, b);
- }
- UNREACHABLE();
-}
-
-UpperAndLower IREmitter::VectorSignedMultiply(size_t esize, const U128& a, const U128& b) {
- const Value multiply = [&] {
- switch (esize) {
- case 16:
- return Inst(Opcode::VectorSignedMultiply16, a, b);
- case 32:
- return Inst(Opcode::VectorSignedMultiply32, a, b);
- }
- UNREACHABLE();
- }();
-
- return {
- Inst<U128>(Opcode::GetUpperFromOp, multiply),
- Inst<U128>(Opcode::GetLowerFromOp, multiply),
- };
-}
-
-U128 IREmitter::VectorSignedSaturatedAbs(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedAbs8, a);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedAbs16, a);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedAbs32, a);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedAbs64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedAccumulateUnsigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedDoublingMultiplyHigh(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHigh16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHigh32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorSignedSaturatedDoublingMultiplyHighRounding(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding32, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::VectorSignedSaturatedDoublingMultiplyLong(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyLong16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyLong32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned16, a);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned32, a);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned16, a);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned32, a);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedNeg(size_t esize, const U128& a) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedNeg8, a);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedNeg16, a);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedNeg32, a);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedNeg64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSignedSaturatedShiftLeftUnsigned(size_t esize, const U128& a, u8 shift_amount) {
- ASSERT(shift_amount < esize);
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned8, a, Imm8(shift_amount));
- case 16:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned16, a, Imm8(shift_amount));
- case 32:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned32, a, Imm8(shift_amount));
- case 64:
- return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned64, a, Imm8(shift_amount));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorSub(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorSub8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorSub16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorSub32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorSub64, a, b);
- }
- UNREACHABLE();
-}
-
-Table IREmitter::VectorTable(std::vector<U64> values) {
- ASSERT(values.size() >= 1 && values.size() <= 4);
- values.resize(4);
- return Inst<Table>(Opcode::VectorTable, values[0], values[1], values[2], values[3]);
-}
-
-Table IREmitter::VectorTable(std::vector<U128> values) {
- ASSERT(values.size() >= 1 && values.size() <= 4);
- values.resize(4);
- return Inst<Table>(Opcode::VectorTable, values[0], values[1], values[2], values[3]);
-}
-
-U64 IREmitter::VectorTableLookup(const U64& defaults, const Table& table, const U64& indices) {
- ASSERT(table.GetInst()->GetArg(0).GetType() == Type::U64);
- return Inst<U64>(Opcode::VectorTableLookup64, defaults, table, indices);
-}
-
-U128 IREmitter::VectorTableLookup(const U128& defaults, const Table& table, const U128& indices) {
- ASSERT(table.GetInst()->GetArg(0).GetType() == Type::U128);
- return Inst<U128>(Opcode::VectorTableLookup128, defaults, table, indices);
-}
-
-U128 IREmitter::VectorTranspose(size_t esize, const U128& a, const U128& b, bool part) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorTranspose8, a, b, Imm1(part));
- case 16:
- return Inst<U128>(Opcode::VectorTranspose16, a, b, Imm1(part));
- case 32:
- return Inst<U128>(Opcode::VectorTranspose32, a, b, Imm1(part));
- case 64:
- return Inst<U128>(Opcode::VectorTranspose64, a, b, Imm1(part));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorUnsignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference32, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorUnsignedRecipEstimate(const U128& a) {
- return Inst<U128>(Opcode::VectorUnsignedRecipEstimate, a);
-}
-
-U128 IREmitter::VectorUnsignedRecipSqrtEstimate(const U128& a) {
- return Inst<U128>(Opcode::VectorUnsignedRecipSqrtEstimate, a);
-}
-
-U128 IREmitter::VectorUnsignedSaturatedAccumulateSigned(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorUnsignedSaturatedNarrow(size_t esize, const U128& a) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow16, a);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow32, a);
- case 64:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorUnsignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) {
- switch (esize) {
- case 8:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft8, a, b);
- case 16:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft16, a, b);
- case 32:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft32, a, b);
- case 64:
- return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft64, a, b);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorZeroExtend(size_t original_esize, const U128& a) {
- switch (original_esize) {
- case 8:
- return Inst<U128>(Opcode::VectorZeroExtend8, a);
- case 16:
- return Inst<U128>(Opcode::VectorZeroExtend16, a);
- case 32:
- return Inst<U128>(Opcode::VectorZeroExtend32, a);
- case 64:
- return Inst<U128>(Opcode::VectorZeroExtend64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::VectorZeroUpper(const U128& a) {
- return Inst<U128>(Opcode::VectorZeroUpper, a);
-}
-
-U128 IREmitter::ZeroVector() {
- return Inst<U128>(Opcode::ZeroVector);
-}
-
-U16U32U64 IREmitter::FPAbs(const U16U32U64& a) {
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPAbs16, a);
- case Type::U32:
- return Inst<U32>(Opcode::FPAbs32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPAbs64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPAdd(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPAdd32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPAdd64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-NZCV IREmitter::FPCompare(const U32U64& a, const U32U64& b, bool exc_on_qnan) {
- ASSERT(a.GetType() == b.GetType());
-
- const IR::U1 exc_on_qnan_imm = Imm1(exc_on_qnan);
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<NZCV>(Opcode::FPCompare32, a, b, exc_on_qnan_imm);
- case Type::U64:
- return Inst<NZCV>(Opcode::FPCompare64, a, b, exc_on_qnan_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPDiv(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPDiv32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPDiv64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMax(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMax32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMax64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMaxNumeric(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMaxNumeric32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMaxNumeric64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMin(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMin32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMin64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMinNumeric(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMinNumeric32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMinNumeric64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMul(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMul32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMul64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPMulAdd(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPMulAdd16, a, b, c);
- case Type::U32:
- return Inst<U32>(Opcode::FPMulAdd32, a, b, c);
- case Type::U64:
- return Inst<U64>(Opcode::FPMulAdd64, a, b, c);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPMulSub(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPMulSub16, a, b, c);
- case Type::U32:
- return Inst<U32>(Opcode::FPMulSub32, a, b, c);
- case Type::U64:
- return Inst<U64>(Opcode::FPMulSub64, a, b, c);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPMulX(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPMulX32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPMulX64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPNeg(const U16U32U64& a) {
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPNeg16, a);
- case Type::U32:
- return Inst<U32>(Opcode::FPNeg32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPNeg64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRecipEstimate(const U16U32U64& a) {
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRecipEstimate16, a);
- case Type::U32:
- return Inst<U32>(Opcode::FPRecipEstimate32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPRecipEstimate64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRecipExponent(const U16U32U64& a) {
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRecipExponent16, a);
- case Type::U32:
- return Inst<U32>(Opcode::FPRecipExponent32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPRecipExponent64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRecipStepFused(const U16U32U64& a, const U16U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRecipStepFused16, a, b);
- case Type::U32:
- return Inst<U32>(Opcode::FPRecipStepFused32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPRecipStepFused64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact) {
- const u8 rounding_value = static_cast<u8>(rounding);
- const IR::U1 exact_imm = Imm1(exact);
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRoundInt16, a, rounding_value, exact_imm);
- case Type::U32:
- return Inst<U32>(Opcode::FPRoundInt32, a, rounding_value, exact_imm);
- case Type::U64:
- return Inst<U64>(Opcode::FPRoundInt64, a, rounding_value, exact_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRSqrtEstimate(const U16U32U64& a) {
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRSqrtEstimate16, a);
- case Type::U32:
- return Inst<U32>(Opcode::FPRSqrtEstimate32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPRSqrtEstimate64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U16U32U64 IREmitter::FPRSqrtStepFused(const U16U32U64& a, const U16U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPRSqrtStepFused16, a, b);
- case Type::U32:
- return Inst<U32>(Opcode::FPRSqrtStepFused32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPRSqrtStepFused64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPSqrt(const U32U64& a) {
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPSqrt32, a);
- case Type::U64:
- return Inst<U64>(Opcode::FPSqrt64, a);
- default:
- UNREACHABLE();
- }
-}
-
-U32U64 IREmitter::FPSub(const U32U64& a, const U32U64& b) {
- ASSERT(a.GetType() == b.GetType());
-
- switch (a.GetType()) {
- case Type::U32:
- return Inst<U32>(Opcode::FPSub32, a, b);
- case Type::U64:
- return Inst<U64>(Opcode::FPSub64, a, b);
- default:
- UNREACHABLE();
- }
-}
-
-U16 IREmitter::FPDoubleToHalf(const U64& a, FP::RoundingMode rounding) {
- return Inst<U16>(Opcode::FPDoubleToHalf, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U32 IREmitter::FPDoubleToSingle(const U64& a, FP::RoundingMode rounding) {
- return Inst<U32>(Opcode::FPDoubleToSingle, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U64 IREmitter::FPHalfToDouble(const U16& a, FP::RoundingMode rounding) {
- return Inst<U64>(Opcode::FPHalfToDouble, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U32 IREmitter::FPHalfToSingle(const U16& a, FP::RoundingMode rounding) {
- return Inst<U32>(Opcode::FPHalfToSingle, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U64 IREmitter::FPSingleToDouble(const U32& a, FP::RoundingMode rounding) {
- return Inst<U64>(Opcode::FPSingleToDouble, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U16 IREmitter::FPSingleToHalf(const U32& a, FP::RoundingMode rounding) {
- return Inst<U16>(Opcode::FPSingleToHalf, a, Imm8(static_cast<u8>(rounding)));
-}
-
-U16 IREmitter::FPToFixedS16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 16);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPHalfToFixedS16, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U16>(Opcode::FPSingleToFixedS16, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U16>(Opcode::FPDoubleToFixedS16, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::FPToFixedS32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 32);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U32>(Opcode::FPHalfToFixedS32, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U32>(Opcode::FPSingleToFixedS32, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U32>(Opcode::FPDoubleToFixedS32, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U64 IREmitter::FPToFixedS64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 64);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U64>(Opcode::FPHalfToFixedS64, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U64>(Opcode::FPSingleToFixedS64, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U64>(Opcode::FPDoubleToFixedS64, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U16 IREmitter::FPToFixedU16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 16);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U16>(Opcode::FPHalfToFixedU16, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U16>(Opcode::FPSingleToFixedU16, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U16>(Opcode::FPDoubleToFixedU16, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::FPToFixedU32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 32);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U32>(Opcode::FPHalfToFixedU32, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U32>(Opcode::FPSingleToFixedU32, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U32>(Opcode::FPDoubleToFixedU32, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U64 IREmitter::FPToFixedU64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= 64);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U64>(Opcode::FPHalfToFixedU64, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U64>(Opcode::FPSingleToFixedU64, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U64>(Opcode::FPDoubleToFixedU64, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::FPSignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
-
- const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U32>(Opcode::FPFixedS16ToSingle, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U32>(Opcode::FPFixedS32ToSingle, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U32>(Opcode::FPFixedS64ToSingle, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U32 IREmitter::FPUnsignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
-
- const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U32>(Opcode::FPFixedU16ToSingle, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U32>(Opcode::FPFixedU32ToSingle, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U32>(Opcode::FPFixedU64ToSingle, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U64 IREmitter::FPSignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
-
- const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U64>(Opcode::FPFixedS16ToDouble, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U64>(Opcode::FPFixedS32ToDouble, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U64>(Opcode::FPFixedS64ToDouble, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U64 IREmitter::FPUnsignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
- ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
-
- const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (a.GetType()) {
- case Type::U16:
- return Inst<U64>(Opcode::FPFixedU16ToDouble, a, fbits_imm, rounding_imm);
- case Type::U32:
- return Inst<U64>(Opcode::FPFixedU32ToDouble, a, fbits_imm, rounding_imm);
- case Type::U64:
- return Inst<U64>(Opcode::FPFixedU64ToDouble, a, fbits_imm, rounding_imm);
- default:
- UNREACHABLE();
- }
-}
-
-U128 IREmitter::FPVectorAbs(size_t esize, const U128& a) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorAbs16, a);
- case 32:
- return Inst<U128>(Opcode::FPVectorAbs32, a);
- case 64:
- return Inst<U128>(Opcode::FPVectorAbs64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorAdd32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorAdd64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorDiv(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorDiv32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorDiv64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorEqual16, a, b, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorEqual32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorEqual64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorFromHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(esize == 32);
- return Inst<U128>(Opcode::FPVectorFromHalf32, a, Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
-}
-
-U128 IREmitter::FPVectorFromSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(fbits <= esize);
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorFromSignedFixed32, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorFromSignedFixed64, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorFromUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(fbits <= esize);
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorFromUnsignedFixed32, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorFromUnsignedFixed64, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorGreater(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorGreater32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorGreater64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorGreaterEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorGreaterEqual32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorGreaterEqual64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMax(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMax32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMax64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMaxNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMaxNumeric32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMaxNumeric64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMin(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMin32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMin64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMinNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMinNumeric32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMinNumeric64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMul(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMul32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMul64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMulAdd(size_t esize, const U128& a, const U128& b, const U128& c, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorMulAdd16, a, b, c, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorMulAdd32, a, b, c, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMulAdd64, a, b, c, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorMulX(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorMulX32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorMulX64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorNeg(size_t esize, const U128& a) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorNeg16, a);
- case 32:
- return Inst<U128>(Opcode::FPVectorNeg32, a);
- case 64:
- return Inst<U128>(Opcode::FPVectorNeg64, a);
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorPairedAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorPairedAdd32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorPairedAdd64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorPairedAddLower(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorPairedAddLower32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorPairedAddLower64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorRecipEstimate(size_t esize, const U128& a, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorRecipEstimate16, a, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorRecipEstimate32, a, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorRecipEstimate64, a, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorRecipStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorRecipStepFused16, a, b, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorRecipStepFused32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorRecipStepFused64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorRoundInt(size_t esize, const U128& operand, FP::RoundingMode rounding, bool exact, bool fpcr_controlled) {
- const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
- const IR::U1 exact_imm = Imm1(exact);
-
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorRoundInt16, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorRoundInt32, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorRoundInt64, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorRSqrtEstimate(size_t esize, const U128& a, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorRSqrtEstimate16, a, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorRSqrtEstimate32, a, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorRSqrtEstimate64, a, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorRSqrtStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorRSqrtStepFused16, a, b, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorRSqrtStepFused32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorRSqrtStepFused64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorSqrt(size_t esize, const U128& a, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorSqrt32, a, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorSqrt64, a, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorSub(size_t esize, const U128& a, const U128& b, bool fpcr_controlled) {
- switch (esize) {
- case 32:
- return Inst<U128>(Opcode::FPVectorSub32, a, b, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorSub64, a, b, Imm1(fpcr_controlled));
- }
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorToHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(esize == 32);
- return Inst<U128>(Opcode::FPVectorToHalf32, a, Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
-}
-
-U128 IREmitter::FPVectorToSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(fbits <= esize);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorToSignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorToSignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorToSignedFixed64, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- }
-
- UNREACHABLE();
-}
-
-U128 IREmitter::FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled) {
- ASSERT(fbits <= esize);
-
- const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
- const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
-
- switch (esize) {
- case 16:
- return Inst<U128>(Opcode::FPVectorToUnsignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- case 32:
- return Inst<U128>(Opcode::FPVectorToUnsignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- case 64:
- return Inst<U128>(Opcode::FPVectorToUnsignedFixed64, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
- }
-
- UNREACHABLE();
-}
-
-void IREmitter::Breakpoint() {
- Inst(Opcode::Breakpoint);
-}
-
-void IREmitter::CallHostFunction(void (*fn)(void)) {
- Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), Value{}, Value{}, Value{});
-}
-
-void IREmitter::CallHostFunction(void (*fn)(u64), const U64& arg1) {
- Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, Value{}, Value{});
-}
-
-void IREmitter::CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) {
- Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, Value{});
-}
-
-void IREmitter::CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3) {
- Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, arg3);
-}
-
-void IREmitter::SetTerm(const Terminal& terminal) {
- block.SetTerminal(terminal);
-}
} // namespace Dynarmic::IR
diff --git a/externals/dynarmic/src/dynarmic/ir/ir_emitter.h b/externals/dynarmic/src/dynarmic/ir/ir_emitter.h
index d37df24572..23cfb47498 100644
--- a/externals/dynarmic/src/dynarmic/ir/ir_emitter.h
+++ b/externals/dynarmic/src/dynarmic/ir/ir_emitter.h
@@ -5,8 +5,13 @@
#pragma once
+#include <vector>
+
#include <mcl/stdint.hpp>
+#include <mcl/assert.hpp>
+#include <mcl/bit_cast.hpp>
+#include "dynarmic/ir/opcodes.h"
#include "dynarmic/ir/acc_type.h"
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/location_descriptor.h"
@@ -69,337 +74,2878 @@ public:
Block& block;
- U1 Imm1(bool value) const;
- U8 Imm8(u8 value) const;
- U16 Imm16(u16 value) const;
- U32 Imm32(u32 value) const;
- U64 Imm64(u64 value) const;
-
- void PushRSB(const LocationDescriptor& return_location);
-
- U64 Pack2x32To1x64(const U32& lo, const U32& hi);
- U128 Pack2x64To1x128(const U64& lo, const U64& hi);
- UAny LeastSignificant(size_t bitsize, const U32U64& value);
- U32 LeastSignificantWord(const U64& value);
- U16 LeastSignificantHalf(U32U64 value);
- U8 LeastSignificantByte(U32U64 value);
- ResultAndCarry<U32> MostSignificantWord(const U64& value);
- U1 MostSignificantBit(const U32& value);
- U1 IsZero(const U32& value);
- U1 IsZero(const U64& value);
- U1 IsZero(const U32U64& value);
- U1 TestBit(const U32U64& value, const U8& bit);
- U32 ConditionalSelect(Cond cond, const U32& a, const U32& b);
- U64 ConditionalSelect(Cond cond, const U64& a, const U64& b);
- NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b);
- U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b);
-
- U1 GetCFlagFromNZCV(const NZCV& nzcv);
- NZCV NZCVFromPackedFlags(const U32& a);
- // This pseudo-instruction may only be added to instructions that support it.
- NZCV NZCVFrom(const Value& value);
-
- ResultAndCarry<U32> LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in);
- ResultAndCarry<U32> LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in);
- ResultAndCarry<U32> ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in);
- ResultAndCarry<U32> RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in);
- U32U64 LogicalShiftLeft(const U32U64& value_in, const U8& shift_amount);
- U32U64 LogicalShiftRight(const U32U64& value_in, const U8& shift_amount);
- U32U64 ArithmeticShiftRight(const U32U64& value_in, const U8& shift_amount);
- U32U64 RotateRight(const U32U64& value_in, const U8& shift_amount);
- U32U64 LogicalShiftLeftMasked(const U32U64& value_in, const U32U64& shift_amount);
- U32U64 LogicalShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount);
- U32U64 ArithmeticShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount);
- U32U64 RotateRightMasked(const U32U64& value_in, const U32U64& shift_amount);
- ResultAndCarry<U32> RotateRightExtended(const U32& value_in, const U1& carry_in);
- U32U64 AddWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in);
- U32U64 SubWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in);
- U32U64 Add(const U32U64& a, const U32U64& b);
- U32U64 Sub(const U32U64& a, const U32U64& b);
- U32U64 Mul(const U32U64& a, const U32U64& b);
- U64 UnsignedMultiplyHigh(const U64& a, const U64& b);
- U64 SignedMultiplyHigh(const U64& a, const U64& b);
- U32U64 UnsignedDiv(const U32U64& a, const U32U64& b);
- U32U64 SignedDiv(const U32U64& a, const U32U64& b);
- U32U64 And(const U32U64& a, const U32U64& b);
- U32U64 AndNot(const U32U64& a, const U32U64& b);
- U32U64 Eor(const U32U64& a, const U32U64& b);
- U32U64 Or(const U32U64& a, const U32U64& b);
- U32U64 Not(const U32U64& a);
- U32 SignExtendToWord(const UAny& a);
- U64 SignExtendToLong(const UAny& a);
- U32 SignExtendByteToWord(const U8& a);
- U32 SignExtendHalfToWord(const U16& a);
- U64 SignExtendWordToLong(const U32& a);
- U32 ZeroExtendToWord(const UAny& a);
- U64 ZeroExtendToLong(const UAny& a);
- U128 ZeroExtendToQuad(const UAny& a);
- U32 ZeroExtendByteToWord(const U8& a);
- U32 ZeroExtendHalfToWord(const U16& a);
- U64 ZeroExtendWordToLong(const U32& a);
- U32 IndeterminateExtendToWord(const UAny& a);
- U64 IndeterminateExtendToLong(const UAny& a);
- U32 ByteReverseWord(const U32& a);
- U16 ByteReverseHalf(const U16& a);
- U64 ByteReverseDual(const U64& a);
- U32U64 CountLeadingZeros(const U32U64& a);
- U32U64 ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb);
- U32U64 ReplicateBit(const U32U64& a, u8 bit);
- U32U64 MaxSigned(const U32U64& a, const U32U64& b);
- U32U64 MaxUnsigned(const U32U64& a, const U32U64& b);
- U32U64 MinSigned(const U32U64& a, const U32U64& b);
- U32U64 MinUnsigned(const U32U64& a, const U32U64& b);
-
- ResultAndOverflow<U32> SignedSaturatedAddWithFlag(const U32& a, const U32& b);
- ResultAndOverflow<U32> SignedSaturatedSubWithFlag(const U32& a, const U32& b);
- ResultAndOverflow<U32> SignedSaturation(const U32& a, size_t bit_size_to_saturate_to);
- ResultAndOverflow<U32> UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to);
-
- UAny SignedSaturatedAdd(const UAny& a, const UAny& b);
- UAny SignedSaturatedDoublingMultiplyReturnHigh(const UAny& a, const UAny& b);
- UAny SignedSaturatedSub(const UAny& a, const UAny& b);
- UAny UnsignedSaturatedAdd(const UAny& a, const UAny& b);
- UAny UnsignedSaturatedSub(const UAny& a, const UAny& b);
-
- U128 VectorSignedSaturatedAdd(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedSub(size_t esize, const U128& a, const U128& b);
- U128 VectorUnsignedSaturatedAdd(size_t esize, const U128& a, const U128& b);
- U128 VectorUnsignedSaturatedSub(size_t esize, const U128& a, const U128& b);
-
- ResultAndGE<U32> PackedAddU8(const U32& a, const U32& b);
- ResultAndGE<U32> PackedAddS8(const U32& a, const U32& b);
- ResultAndGE<U32> PackedAddU16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedAddS16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubU8(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubS8(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubU16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubS16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedAddSubU16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedAddSubS16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubAddU16(const U32& a, const U32& b);
- ResultAndGE<U32> PackedSubAddS16(const U32& a, const U32& b);
- U32 PackedHalvingAddU8(const U32& a, const U32& b);
- U32 PackedHalvingAddS8(const U32& a, const U32& b);
- U32 PackedHalvingSubU8(const U32& a, const U32& b);
- U32 PackedHalvingSubS8(const U32& a, const U32& b);
- U32 PackedHalvingAddU16(const U32& a, const U32& b);
- U32 PackedHalvingAddS16(const U32& a, const U32& b);
- U32 PackedHalvingSubU16(const U32& a, const U32& b);
- U32 PackedHalvingSubS16(const U32& a, const U32& b);
- U32 PackedHalvingAddSubU16(const U32& a, const U32& b);
- U32 PackedHalvingAddSubS16(const U32& a, const U32& b);
- U32 PackedHalvingSubAddU16(const U32& a, const U32& b);
- U32 PackedHalvingSubAddS16(const U32& a, const U32& b);
- U32 PackedSaturatedAddU8(const U32& a, const U32& b);
- U32 PackedSaturatedAddS8(const U32& a, const U32& b);
- U32 PackedSaturatedSubU8(const U32& a, const U32& b);
- U32 PackedSaturatedSubS8(const U32& a, const U32& b);
- U32 PackedSaturatedAddU16(const U32& a, const U32& b);
- U32 PackedSaturatedAddS16(const U32& a, const U32& b);
- U32 PackedSaturatedSubU16(const U32& a, const U32& b);
- U32 PackedSaturatedSubS16(const U32& a, const U32& b);
- U32 PackedAbsDiffSumU8(const U32& a, const U32& b);
- U32 PackedSelect(const U32& ge, const U32& a, const U32& b);
-
- U32 CRC32Castagnoli8(const U32& a, const U32& b);
- U32 CRC32Castagnoli16(const U32& a, const U32& b);
- U32 CRC32Castagnoli32(const U32& a, const U32& b);
- U32 CRC32Castagnoli64(const U32& a, const U64& b);
- U32 CRC32ISO8(const U32& a, const U32& b);
- U32 CRC32ISO16(const U32& a, const U32& b);
- U32 CRC32ISO32(const U32& a, const U32& b);
- U32 CRC32ISO64(const U32& a, const U64& b);
-
- U128 AESDecryptSingleRound(const U128& a);
- U128 AESEncryptSingleRound(const U128& a);
- U128 AESInverseMixColumns(const U128& a);
- U128 AESMixColumns(const U128& a);
-
- U8 SM4AccessSubstitutionBox(const U8& a);
-
- U128 SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1);
- U128 SHA256MessageSchedule0(const U128& x, const U128& y);
- U128 SHA256MessageSchedule1(const U128& x, const U128& y, const U128& z);
-
- UAny VectorGetElement(size_t esize, const U128& a, size_t index);
- U128 VectorSetElement(size_t esize, const U128& a, size_t index, const UAny& elem);
- U128 VectorAbs(size_t esize, const U128& a);
- U128 VectorAdd(size_t esize, const U128& a, const U128& b);
- U128 VectorAnd(const U128& a, const U128& b);
- U128 VectorAndNot(const U128& a, const U128& b);
- U128 VectorArithmeticShiftRight(size_t esize, const U128& a, u8 shift_amount);
- U128 VectorArithmeticVShift(size_t esize, const U128& a, const U128& b);
- U128 VectorBroadcast(size_t esize, const UAny& a);
- U128 VectorBroadcastLower(size_t esize, const UAny& a);
- U128 VectorBroadcastElement(size_t esize, const U128& a, size_t index);
- U128 VectorBroadcastElementLower(size_t esize, const U128& a, size_t index);
- U128 VectorCountLeadingZeros(size_t esize, const U128& a);
- U128 VectorEor(const U128& a, const U128& b);
- U128 VectorDeinterleaveEven(size_t esize, const U128& a, const U128& b);
- U128 VectorDeinterleaveEvenLower(size_t esize, const U128& a, const U128& b);
- U128 VectorDeinterleaveOdd(size_t esize, const U128& a, const U128& b);
- U128 VectorDeinterleaveOddLower(size_t esize, const U128& a, const U128& b);
- U128 VectorEqual(size_t esize, const U128& a, const U128& b);
- U128 VectorExtract(const U128& a, const U128& b, size_t position);
- U128 VectorExtractLower(const U128& a, const U128& b, size_t position);
- U128 VectorGreaterEqualSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorGreaterEqualUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorGreaterSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorGreaterUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorHalvingAddSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorHalvingAddUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorHalvingSubSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorHalvingSubUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorInterleaveLower(size_t esize, const U128& a, const U128& b);
- U128 VectorInterleaveUpper(size_t esize, const U128& a, const U128& b);
- U128 VectorLessEqualSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorLessEqualUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorLessSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorLessUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorLogicalShiftLeft(size_t esize, const U128& a, u8 shift_amount);
- U128 VectorLogicalShiftRight(size_t esize, const U128& a, u8 shift_amount);
- U128 VectorLogicalVShift(size_t esize, const U128& a, const U128& b);
- U128 VectorMaxSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorMaxUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorMinSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorMinUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorMultiply(size_t esize, const U128& a, const U128& b);
- U128 VectorMultiplySignedWiden(size_t esize, const U128& a, const U128& b);
- U128 VectorMultiplyUnsignedWiden(size_t esize, const U128& a, const U128& b);
- U128 VectorNarrow(size_t original_esize, const U128& a);
- U128 VectorNot(const U128& a);
- U128 VectorOr(const U128& a, const U128& b);
- U128 VectorPairedAdd(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedAddLower(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedAddSignedWiden(size_t original_esize, const U128& a);
- U128 VectorPairedAddUnsignedWiden(size_t original_esize, const U128& a);
- U128 VectorPairedMaxSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMaxUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMinSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMinUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMaxSignedLower(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMaxUnsignedLower(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMinSignedLower(size_t esize, const U128& a, const U128& b);
- U128 VectorPairedMinUnsignedLower(size_t esize, const U128& a, const U128& b);
- U128 VectorPolynomialMultiply(const U128& a, const U128& b);
- U128 VectorPolynomialMultiplyLong(size_t esize, const U128& a, const U128& b);
- U128 VectorPopulationCount(const U128& a);
- U128 VectorReverseBits(const U128& a);
- U128 VectorReverseElementsInHalfGroups(size_t esize, const U128& a);
- U128 VectorReverseElementsInWordGroups(size_t esize, const U128& a);
- U128 VectorReverseElementsInLongGroups(size_t esize, const U128& a);
- U128 VectorReduceAdd(size_t esize, const U128& a);
- U128 VectorRotateLeft(size_t esize, const U128& a, u8 amount);
- U128 VectorRotateRight(size_t esize, const U128& a, u8 amount);
- U128 VectorRotateWholeVectorRight(const U128& a, u8 amount);
- U128 VectorRoundingHalvingAddSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorRoundingHalvingAddUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorRoundingShiftLeftSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorRoundingShiftLeftUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorSignExtend(size_t original_esize, const U128& a);
- U128 VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b);
- UpperAndLower VectorSignedMultiply(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedAbs(size_t esize, const U128& a);
- U128 VectorSignedSaturatedAccumulateUnsigned(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedDoublingMultiplyHigh(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedDoublingMultiplyHighRounding(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedDoublingMultiplyLong(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a);
- U128 VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a);
- U128 VectorSignedSaturatedNeg(size_t esize, const U128& a);
- U128 VectorSignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b);
- U128 VectorSignedSaturatedShiftLeftUnsigned(size_t esize, const U128& a, u8 shift_amount);
- U128 VectorSub(size_t esize, const U128& a, const U128& b);
- Table VectorTable(std::vector<U64> values);
- Table VectorTable(std::vector<U128> values);
- U64 VectorTableLookup(const U64& defaults, const Table& table, const U64& indices);
- U128 VectorTableLookup(const U128& defaults, const Table& table, const U128& indices);
- U128 VectorTranspose(size_t esize, const U128& a, const U128& b, bool part);
- U128 VectorUnsignedAbsoluteDifference(size_t esize, const U128& a, const U128& b);
- U128 VectorUnsignedRecipEstimate(const U128& a);
- U128 VectorUnsignedRecipSqrtEstimate(const U128& a);
- U128 VectorUnsignedSaturatedAccumulateSigned(size_t esize, const U128& a, const U128& b);
- U128 VectorUnsignedSaturatedNarrow(size_t esize, const U128& a);
- U128 VectorUnsignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b);
- U128 VectorZeroExtend(size_t original_esize, const U128& a);
- U128 VectorZeroUpper(const U128& a);
- U128 ZeroVector();
-
- U16U32U64 FPAbs(const U16U32U64& a);
- U32U64 FPAdd(const U32U64& a, const U32U64& b);
- NZCV FPCompare(const U32U64& a, const U32U64& b, bool exc_on_qnan);
- U32U64 FPDiv(const U32U64& a, const U32U64& b);
- U32U64 FPMax(const U32U64& a, const U32U64& b);
- U32U64 FPMaxNumeric(const U32U64& a, const U32U64& b);
- U32U64 FPMin(const U32U64& a, const U32U64& b);
- U32U64 FPMinNumeric(const U32U64& a, const U32U64& b);
- U32U64 FPMul(const U32U64& a, const U32U64& b);
- U16U32U64 FPMulAdd(const U16U32U64& addend, const U16U32U64& op1, const U16U32U64& op2);
- U16U32U64 FPMulSub(const U16U32U64& minuend, const U16U32U64& op1, const U16U32U64& op2);
- U32U64 FPMulX(const U32U64& a, const U32U64& b);
- U16U32U64 FPNeg(const U16U32U64& a);
- U16U32U64 FPRecipEstimate(const U16U32U64& a);
- U16U32U64 FPRecipExponent(const U16U32U64& a);
- U16U32U64 FPRecipStepFused(const U16U32U64& a, const U16U32U64& b);
- U16U32U64 FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact);
- U16U32U64 FPRSqrtEstimate(const U16U32U64& a);
- U16U32U64 FPRSqrtStepFused(const U16U32U64& a, const U16U32U64& b);
- U32U64 FPSqrt(const U32U64& a);
- U32U64 FPSub(const U32U64& a, const U32U64& b);
- U16 FPDoubleToHalf(const U64& a, FP::RoundingMode rounding);
- U32 FPDoubleToSingle(const U64& a, FP::RoundingMode rounding);
- U64 FPHalfToDouble(const U16& a, FP::RoundingMode rounding);
- U32 FPHalfToSingle(const U16& a, FP::RoundingMode rounding);
- U16 FPSingleToHalf(const U32& a, FP::RoundingMode rounding);
- U64 FPSingleToDouble(const U32& a, FP::RoundingMode rounding);
- U16 FPToFixedS16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U32 FPToFixedS32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U64 FPToFixedS64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U16 FPToFixedU16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U32 FPToFixedU32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U64 FPToFixedU64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U32 FPSignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U32 FPUnsignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U64 FPSignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
- U64 FPUnsignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding);
-
- U128 FPVectorAbs(size_t esize, const U128& a);
- U128 FPVectorAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorDiv(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorFromHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled = true);
- U128 FPVectorFromSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
- U128 FPVectorFromUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
- U128 FPVectorGreater(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorGreaterEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMax(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMaxNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMin(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMinNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMul(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorMulAdd(size_t esize, const U128& addend, const U128& op1, const U128& op2, bool fpcr_controlled = true);
- U128 FPVectorMulX(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorNeg(size_t esize, const U128& a);
- U128 FPVectorPairedAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorPairedAddLower(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorRecipEstimate(size_t esize, const U128& a, bool fpcr_controlled = true);
- U128 FPVectorRecipStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorRoundInt(size_t esize, const U128& operand, FP::RoundingMode rounding, bool exact, bool fpcr_controlled = true);
- U128 FPVectorRSqrtEstimate(size_t esize, const U128& a, bool fpcr_controlled = true);
- U128 FPVectorRSqrtStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorSqrt(size_t esize, const U128& a, bool fpcr_controlled = true);
- U128 FPVectorSub(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true);
- U128 FPVectorToHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled = true);
- U128 FPVectorToSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
- U128 FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
-
- void Breakpoint();
- void CallHostFunction(void (*fn)(void));
- void CallHostFunction(void (*fn)(u64), const U64& arg1);
- void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2);
- void CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3);
-
- void SetTerm(const Terminal& terminal);
+ U1 Imm1(bool imm1) const {
+ return U1(Value(imm1));
+ }
+
+ U8 Imm8(u8 imm8) const {
+ return U8(Value(imm8));
+ }
+
+ U16 Imm16(u16 imm16) const {
+ return U16(Value(imm16));
+ }
+
+ U32 Imm32(u32 imm32) const {
+ return U32(Value(imm32));
+ }
+
+ U64 Imm64(u64 imm64) const {
+ return U64(Value(imm64));
+ }
+
+ void PushRSB(const LocationDescriptor& return_location) {
+ Inst(Opcode::PushRSB, IR::Value(return_location.Value()));
+ }
+
+ U64 Pack2x32To1x64(const U32& lo, const U32& hi) {
+ return Inst<U64>(Opcode::Pack2x32To1x64, lo, hi);
+ }
+
+ U128 Pack2x64To1x128(const U64& lo, const U64& hi) {
+ return Inst<U128>(Opcode::Pack2x64To1x128, lo, hi);
+ }
+
+ UAny LeastSignificant(size_t bitsize, const U32U64& value) {
+ switch (bitsize) {
+ case 8:
+ return LeastSignificantByte(value);
+ case 16:
+ return LeastSignificantHalf(value);
+ case 32:
+ if (value.GetType() == Type::U32) {
+ return value;
+ }
+ return LeastSignificantWord(value);
+ case 64:
+ ASSERT(value.GetType() == Type::U64);
+ return value;
+ }
+ ASSERT_FALSE("Invalid bitsize");
+ }
+
+ U32 LeastSignificantWord(const U64& value) {
+ return Inst<U32>(Opcode::LeastSignificantWord, value);
+ }
+
+ U16 LeastSignificantHalf(U32U64 value) {
+ if (value.GetType() == Type::U64) {
+ value = LeastSignificantWord(value);
+ }
+ return Inst<U16>(Opcode::LeastSignificantHalf, value);
+ }
+
+ U8 LeastSignificantByte(U32U64 value) {
+ if (value.GetType() == Type::U64) {
+ value = LeastSignificantWord(value);
+ }
+ return Inst<U8>(Opcode::LeastSignificantByte, value);
+ }
+
+ ResultAndCarry<U32> MostSignificantWord(const U64& value) {
+ const auto result = Inst<U32>(Opcode::MostSignificantWord, value);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ U1 MostSignificantBit(const U32& value) {
+ return Inst<U1>(Opcode::MostSignificantBit, value);
+ }
+
+ U1 IsZero(const U32& value) {
+ return Inst<U1>(Opcode::IsZero32, value);
+ }
+
+ U1 IsZero(const U64& value) {
+ return Inst<U1>(Opcode::IsZero64, value);
+ }
+
+ U1 IsZero(const U32U64& value) {
+ if (value.GetType() == Type::U32) {
+ return Inst<U1>(Opcode::IsZero32, value);
+ } else {
+ return Inst<U1>(Opcode::IsZero64, value);
+ }
+ }
+
+ U1 TestBit(const U32U64& value, const U8& bit) {
+ if (value.GetType() == Type::U32) {
+ return Inst<U1>(Opcode::TestBit, IndeterminateExtendToLong(value), bit);
+ } else {
+ return Inst<U1>(Opcode::TestBit, value, bit);
+ }
+ }
+
+ U32 ConditionalSelect(Cond cond, const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::ConditionalSelect32, Value{cond}, a, b);
+ }
+
+ U64 ConditionalSelect(Cond cond, const U64& a, const U64& b) {
+ return Inst<U64>(Opcode::ConditionalSelect64, Value{cond}, a, b);
+ }
+
+ NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b) {
+ return Inst<NZCV>(Opcode::ConditionalSelectNZCV, Value{cond}, a, b);
+ }
+
+ U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::ConditionalSelect32, Value{cond}, a, b);
+ } else {
+ return Inst<U64>(Opcode::ConditionalSelect64, Value{cond}, a, b);
+ }
+ }
+
+ U1 GetCFlagFromNZCV(const NZCV& nzcv) {
+ return Inst<U1>(Opcode::GetCFlagFromNZCV, nzcv);
+ }
+
+ NZCV NZCVFromPackedFlags(const U32& a) {
+ return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
+ }
+
+ NZCV NZCVFrom(const Value& value) {
+ return Inst<NZCV>(Opcode::GetNZCVFromOp, value);
+ }
+
+ ResultAndCarry<U32> LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
+ const auto result = Inst<U32>(Opcode::LogicalShiftLeft32, value_in, shift_amount, carry_in);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ ResultAndCarry<U32> LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
+ const auto result = Inst<U32>(Opcode::LogicalShiftRight32, value_in, shift_amount, carry_in);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ ResultAndCarry<U32> ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
+ const auto result = Inst<U32>(Opcode::ArithmeticShiftRight32, value_in, shift_amount, carry_in);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ ResultAndCarry<U32> RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) {
+ const auto result = Inst<U32>(Opcode::RotateRight32, value_in, shift_amount, carry_in);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ ResultAndCarry<U32> RotateRightExtended(const U32& value_in, const U1& carry_in) {
+ const auto result = Inst<U32>(Opcode::RotateRightExtended, value_in, carry_in);
+ const auto carry_out = Inst<U1>(Opcode::GetCarryFromOp, result);
+ return {result, carry_out};
+ }
+
+ U32U64 LogicalShiftLeft(const U32U64& value_in, const U8& shift_amount) {
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::LogicalShiftLeft32, value_in, shift_amount, Imm1(0));
+ } else {
+ return Inst<U64>(Opcode::LogicalShiftLeft64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 LogicalShiftRight(const U32U64& value_in, const U8& shift_amount) {
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::LogicalShiftRight32, value_in, shift_amount, Imm1(0));
+ } else {
+ return Inst<U64>(Opcode::LogicalShiftRight64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 ArithmeticShiftRight(const U32U64& value_in, const U8& shift_amount) {
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::ArithmeticShiftRight32, value_in, shift_amount, Imm1(0));
+ } else {
+ return Inst<U64>(Opcode::ArithmeticShiftRight64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 RotateRight(const U32U64& value_in, const U8& shift_amount) {
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::RotateRight32, value_in, shift_amount, Imm1(0));
+ } else {
+ return Inst<U64>(Opcode::RotateRight64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 LogicalShiftLeftMasked(const U32U64& value_in, const U32U64& shift_amount) {
+ ASSERT(value_in.GetType() == shift_amount.GetType());
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::LogicalShiftLeftMasked32, value_in, shift_amount);
+ } else {
+ return Inst<U64>(Opcode::LogicalShiftLeftMasked64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 LogicalShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
+ ASSERT(value_in.GetType() == shift_amount.GetType());
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::LogicalShiftRightMasked32, value_in, shift_amount);
+ } else {
+ return Inst<U64>(Opcode::LogicalShiftRightMasked64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 ArithmeticShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
+ ASSERT(value_in.GetType() == shift_amount.GetType());
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::ArithmeticShiftRightMasked32, value_in, shift_amount);
+ } else {
+ return Inst<U64>(Opcode::ArithmeticShiftRightMasked64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 RotateRightMasked(const U32U64& value_in, const U32U64& shift_amount) {
+ ASSERT(value_in.GetType() == shift_amount.GetType());
+ if (value_in.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::RotateRightMasked32, value_in, shift_amount);
+ } else {
+ return Inst<U64>(Opcode::RotateRightMasked64, value_in, shift_amount);
+ }
+ }
+
+ U32U64 AddWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Add32, a, b, carry_in);
+ } else {
+ return Inst<U64>(Opcode::Add64, a, b, carry_in);
+ }
+ }
+
+ U32U64 Add(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Add32, a, b, Imm1(0));
+ } else {
+ return Inst<U64>(Opcode::Add64, a, b, Imm1(0));
+ }
+ }
+
+ U32U64 SubWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Sub32, a, b, carry_in);
+ } else {
+ return Inst<U64>(Opcode::Sub64, a, b, carry_in);
+ }
+ }
+
+ U32U64 Sub(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Sub32, a, b, Imm1(1));
+ } else {
+ return Inst<U64>(Opcode::Sub64, a, b, Imm1(1));
+ }
+ }
+
+ U32U64 Mul(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Mul32, a, b);
+ }
+
+ return Inst<U64>(Opcode::Mul64, a, b);
+ }
+
+ U64 UnsignedMultiplyHigh(const U64& a, const U64& b) {
+ return Inst<U64>(Opcode::UnsignedMultiplyHigh64, a, b);
+ }
+
+ U64 SignedMultiplyHigh(const U64& a, const U64& b) {
+ return Inst<U64>(Opcode::SignedMultiplyHigh64, a, b);
+ }
+
+ U32U64 UnsignedDiv(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::UnsignedDiv32, a, b);
+ }
+
+ return Inst<U64>(Opcode::UnsignedDiv64, a, b);
+ }
+
+ U32U64 SignedDiv(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::SignedDiv32, a, b);
+ }
+
+ return Inst<U64>(Opcode::SignedDiv64, a, b);
+ }
+
+ U32U64 And(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::And32, a, b);
+ } else {
+ return Inst<U64>(Opcode::And64, a, b);
+ }
+ }
+
+ U32U64 AndNot(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::AndNot32, a, b);
+ } else {
+ return Inst<U64>(Opcode::AndNot64, a, b);
+ }
+ }
+
+ U32U64 Eor(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Eor32, a, b);
+ } else {
+ return Inst<U64>(Opcode::Eor64, a, b);
+ }
+ }
+
+ U32U64 Or(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Or32, a, b);
+ } else {
+ return Inst<U64>(Opcode::Or64, a, b);
+ }
+ }
+
+ U32U64 Not(const U32U64& a) {
+ if (a.GetType() == Type::U32) {
+ return Inst<U32>(Opcode::Not32, a);
+ } else {
+ return Inst<U64>(Opcode::Not64, a);
+ }
+ }
+
+ U64 SignExtendToLong(const UAny& a) {
+ switch (a.GetType()) {
+ case Type::U8:
+ return Inst<U64>(Opcode::SignExtendByteToLong, a);
+ case Type::U16:
+ return Inst<U64>(Opcode::SignExtendHalfToLong, a);
+ case Type::U32:
+ return Inst<U64>(Opcode::SignExtendWordToLong, a);
+ case Type::U64:
+ return U64(a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 SignExtendToWord(const UAny& a) {
+ switch (a.GetType()) {
+ case Type::U8:
+ return Inst<U32>(Opcode::SignExtendByteToWord, a);
+ case Type::U16:
+ return Inst<U32>(Opcode::SignExtendHalfToWord, a);
+ case Type::U32:
+ return U32(a);
+ case Type::U64:
+ return Inst<U32>(Opcode::LeastSignificantWord, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U64 SignExtendWordToLong(const U32& a) {
+ return Inst<U64>(Opcode::SignExtendWordToLong, a);
+ }
+
+ U32 SignExtendHalfToWord(const U16& a) {
+ return Inst<U32>(Opcode::SignExtendHalfToWord, a);
+ }
+
+ U32 SignExtendByteToWord(const U8& a) {
+ return Inst<U32>(Opcode::SignExtendByteToWord, a);
+ }
+
+ U64 ZeroExtendToLong(const UAny& a) {
+ switch (a.GetType()) {
+ case Type::U8:
+ return Inst<U64>(Opcode::ZeroExtendByteToLong, a);
+ case Type::U16:
+ return Inst<U64>(Opcode::ZeroExtendHalfToLong, a);
+ case Type::U32:
+ return Inst<U64>(Opcode::ZeroExtendWordToLong, a);
+ case Type::U64:
+ return U64(a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 ZeroExtendToWord(const UAny& a) {
+ switch (a.GetType()) {
+ case Type::U8:
+ return Inst<U32>(Opcode::ZeroExtendByteToWord, a);
+ case Type::U16:
+ return Inst<U32>(Opcode::ZeroExtendHalfToWord, a);
+ case Type::U32:
+ return U32(a);
+ case Type::U64:
+ return Inst<U32>(Opcode::LeastSignificantWord, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 ZeroExtendToQuad(const UAny& a) {
+ return Inst<U128>(Opcode::ZeroExtendLongToQuad, ZeroExtendToLong(a));
+ }
+
+ U64 ZeroExtendWordToLong(const U32& a) {
+ return Inst<U64>(Opcode::ZeroExtendWordToLong, a);
+ }
+
+ U32 ZeroExtendHalfToWord(const U16& a) {
+ return Inst<U32>(Opcode::ZeroExtendHalfToWord, a);
+ }
+
+ U32 ZeroExtendByteToWord(const U8& a) {
+ return Inst<U32>(Opcode::ZeroExtendByteToWord, a);
+ }
+
+ U32 IndeterminateExtendToWord(const UAny& a) {
+ // TODO: Implement properly
+ return ZeroExtendToWord(a);
+ }
+
+ U64 IndeterminateExtendToLong(const UAny& a) {
+ // TODO: Implement properly
+ return ZeroExtendToLong(a);
+ }
+
+ U32 ByteReverseWord(const U32& a) {
+ return Inst<U32>(Opcode::ByteReverseWord, a);
+ }
+
+ U16 ByteReverseHalf(const U16& a) {
+ return Inst<U16>(Opcode::ByteReverseHalf, a);
+ }
+
+ U64 ByteReverseDual(const U64& a) {
+ return Inst<U64>(Opcode::ByteReverseDual, a);
+ }
+
+ U32U64 CountLeadingZeros(const U32U64& a) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::CountLeadingZeros32, a);
+ }
+
+ return Inst<U64>(Opcode::CountLeadingZeros64, a);
+ }
+
+ U32U64 ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::ExtractRegister32, a, b, lsb);
+ }
+
+ return Inst<U64>(Opcode::ExtractRegister64, a, b, lsb);
+ }
+
+ U32U64 ReplicateBit(const U32U64& a, u8 bit) {
+ if (a.GetType() == IR::Type::U32) {
+ ASSERT(bit < 32);
+ return Inst<U32>(Opcode::ReplicateBit32, a, Imm8(bit));
+ }
+
+ ASSERT(bit < 64);
+ return Inst<U64>(Opcode::ReplicateBit64, a, Imm8(bit));
+ }
+
+ U32U64 MaxSigned(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::MaxSigned32, a, b);
+ }
+
+ return Inst<U64>(Opcode::MaxSigned64, a, b);
+ }
+
+ U32U64 MaxUnsigned(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::MaxUnsigned32, a, b);
+ }
+
+ return Inst<U64>(Opcode::MaxUnsigned64, a, b);
+ }
+
+ U32U64 MinSigned(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::MinSigned32, a, b);
+ }
+
+ return Inst<U64>(Opcode::MinSigned64, a, b);
+ }
+
+ U32U64 MinUnsigned(const U32U64& a, const U32U64& b) {
+ if (a.GetType() == IR::Type::U32) {
+ return Inst<U32>(Opcode::MinUnsigned32, a, b);
+ }
+
+ return Inst<U64>(Opcode::MinUnsigned64, a, b);
+ }
+
+ ResultAndOverflow<U32> SignedSaturatedAddWithFlag(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::SignedSaturatedAddWithFlag32, a, b);
+ const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
+ return {result, overflow};
+ }
+
+ ResultAndOverflow<U32> SignedSaturatedSubWithFlag(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::SignedSaturatedSubWithFlag32, a, b);
+ const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
+ return {result, overflow};
+ }
+
+ ResultAndOverflow<U32> SignedSaturation(const U32& a, size_t bit_size_to_saturate_to) {
+ ASSERT(bit_size_to_saturate_to >= 1 && bit_size_to_saturate_to <= 32);
+ const auto result = Inst<U32>(Opcode::SignedSaturation, a, Imm8(static_cast<u8>(bit_size_to_saturate_to)));
+ const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
+ return {result, overflow};
+ }
+
+ ResultAndOverflow<U32> UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to) {
+ ASSERT(bit_size_to_saturate_to <= 31);
+ const auto result = Inst<U32>(Opcode::UnsignedSaturation, a, Imm8(static_cast<u8>(bit_size_to_saturate_to)));
+ const auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);
+ return {result, overflow};
+ }
+
+ UAny SignedSaturatedAdd(const UAny& a, const UAny& b) {
+ ASSERT(a.GetType() == b.GetType());
+ const auto result = [&]() -> IR::UAny {
+ switch (a.GetType()) {
+ case IR::Type::U8:
+ return Inst<U8>(Opcode::SignedSaturatedAdd8, a, b);
+ case IR::Type::U16:
+ return Inst<U16>(Opcode::SignedSaturatedAdd16, a, b);
+ case IR::Type::U32:
+ return Inst<U32>(Opcode::SignedSaturatedAdd32, a, b);
+ case IR::Type::U64:
+ return Inst<U64>(Opcode::SignedSaturatedAdd64, a, b);
+ default:
+ return IR::UAny{};
+ }
+ }();
+ return result;
+ }
+
+ UAny SignedSaturatedDoublingMultiplyReturnHigh(const UAny& a, const UAny& b) {
+ ASSERT(a.GetType() == b.GetType());
+ const auto result = [&]() -> IR::UAny {
+ switch (a.GetType()) {
+ case IR::Type::U16:
+ return Inst<U16>(Opcode::SignedSaturatedDoublingMultiplyReturnHigh16, a, b);
+ case IR::Type::U32:
+ return Inst<U32>(Opcode::SignedSaturatedDoublingMultiplyReturnHigh32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }();
+ return result;
+ }
+
+ UAny SignedSaturatedSub(const UAny& a, const UAny& b) {
+ ASSERT(a.GetType() == b.GetType());
+ const auto result = [&]() -> IR::UAny {
+ switch (a.GetType()) {
+ case IR::Type::U8:
+ return Inst<U8>(Opcode::SignedSaturatedSub8, a, b);
+ case IR::Type::U16:
+ return Inst<U16>(Opcode::SignedSaturatedSub16, a, b);
+ case IR::Type::U32:
+ return Inst<U32>(Opcode::SignedSaturatedSub32, a, b);
+ case IR::Type::U64:
+ return Inst<U64>(Opcode::SignedSaturatedSub64, a, b);
+ default:
+ return IR::UAny{};
+ }
+ }();
+ return result;
+ }
+
+ UAny UnsignedSaturatedAdd(const UAny& a, const UAny& b) {
+ ASSERT(a.GetType() == b.GetType());
+ const auto result = [&]() -> IR::UAny {
+ switch (a.GetType()) {
+ case IR::Type::U8:
+ return Inst<U8>(Opcode::UnsignedSaturatedAdd8, a, b);
+ case IR::Type::U16:
+ return Inst<U16>(Opcode::UnsignedSaturatedAdd16, a, b);
+ case IR::Type::U32:
+ return Inst<U32>(Opcode::UnsignedSaturatedAdd32, a, b);
+ case IR::Type::U64:
+ return Inst<U64>(Opcode::UnsignedSaturatedAdd64, a, b);
+ default:
+ return IR::UAny{};
+ }
+ }();
+ return result;
+ }
+
+ UAny UnsignedSaturatedSub(const UAny& a, const UAny& b) {
+ ASSERT(a.GetType() == b.GetType());
+ const auto result = [&]() -> IR::UAny {
+ switch (a.GetType()) {
+ case IR::Type::U8:
+ return Inst<U8>(Opcode::UnsignedSaturatedSub8, a, b);
+ case IR::Type::U16:
+ return Inst<U16>(Opcode::UnsignedSaturatedSub16, a, b);
+ case IR::Type::U32:
+ return Inst<U32>(Opcode::UnsignedSaturatedSub32, a, b);
+ case IR::Type::U64:
+ return Inst<U64>(Opcode::UnsignedSaturatedSub64, a, b);
+ default:
+ return IR::UAny{};
+ }
+ }();
+ return result;
+ }
+
+ U128 VectorSignedSaturatedAdd(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAdd8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAdd16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAdd32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAdd64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorSignedSaturatedSub(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedSub8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedSub16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedSub32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedSub64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorUnsignedSaturatedAdd(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAdd64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorUnsignedSaturatedSub(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedSub8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedSub16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedSub32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedSub64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ ResultAndGE<U32> PackedAddU8(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddU8, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedAddS8(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddS8, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedAddU16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddU16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedAddS16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddS16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubU8(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubU8, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubS8(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubS8, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubU16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubU16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubS16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubS16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedAddSubU16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddSubU16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedAddSubS16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedAddSubS16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubAddU16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubAddU16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ ResultAndGE<U32> PackedSubAddS16(const U32& a, const U32& b) {
+ const auto result = Inst<U32>(Opcode::PackedSubAddS16, a, b);
+ const auto ge = Inst<U32>(Opcode::GetGEFromOp, result);
+ return {result, ge};
+ }
+
+ U32 PackedHalvingAddU8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddU8, a, b);
+ }
+
+ U32 PackedHalvingAddS8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddS8, a, b);
+ }
+
+ U32 PackedHalvingSubU8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubU8, a, b);
+ }
+
+ U32 PackedHalvingSubS8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubS8, a, b);
+ }
+
+ U32 PackedHalvingAddU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddU16, a, b);
+ }
+
+ U32 PackedHalvingAddS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddS16, a, b);
+ }
+
+ U32 PackedHalvingSubU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubU16, a, b);
+ }
+
+ U32 PackedHalvingSubS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubS16, a, b);
+ }
+
+ U32 PackedHalvingAddSubU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddSubU16, a, b);
+ }
+
+ U32 PackedHalvingAddSubS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingAddSubS16, a, b);
+ }
+
+ U32 PackedHalvingSubAddU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubAddU16, a, b);
+ }
+
+ U32 PackedHalvingSubAddS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedHalvingSubAddS16, a, b);
+ }
+
+ U32 PackedSaturatedAddU8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedAddU8, a, b);
+ }
+
+ U32 PackedSaturatedAddS8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedAddS8, a, b);
+ }
+
+ U32 PackedSaturatedSubU8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedSubU8, a, b);
+ }
+
+ U32 PackedSaturatedSubS8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedSubS8, a, b);
+ }
+
+ U32 PackedSaturatedAddU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedAddU16, a, b);
+ }
+
+ U32 PackedSaturatedAddS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedAddS16, a, b);
+ }
+
+ U32 PackedSaturatedSubU16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedSubU16, a, b);
+ }
+
+ U32 PackedSaturatedSubS16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSaturatedSubS16, a, b);
+ }
+
+ U32 PackedAbsDiffSumU8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedAbsDiffSumU8, a, b);
+ }
+
+ U32 PackedSelect(const U32& ge, const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::PackedSelect, ge, a, b);
+ }
+
+ U32 CRC32Castagnoli8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32Castagnoli8, a, b);
+ }
+
+ U32 CRC32Castagnoli16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32Castagnoli16, a, b);
+ }
+
+ U32 CRC32Castagnoli32(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32Castagnoli32, a, b);
+ }
+
+ U32 CRC32Castagnoli64(const U32& a, const U64& b) {
+ return Inst<U32>(Opcode::CRC32Castagnoli64, a, b);
+ }
+
+ U32 CRC32ISO8(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32ISO8, a, b);
+ }
+
+ U32 CRC32ISO16(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32ISO16, a, b);
+ }
+
+ U32 CRC32ISO32(const U32& a, const U32& b) {
+ return Inst<U32>(Opcode::CRC32ISO32, a, b);
+ }
+
+ U32 CRC32ISO64(const U32& a, const U64& b) {
+ return Inst<U32>(Opcode::CRC32ISO64, a, b);
+ }
+
+ U128 AESDecryptSingleRound(const U128& a) {
+ return Inst<U128>(Opcode::AESDecryptSingleRound, a);
+ }
+
+ U128 AESEncryptSingleRound(const U128& a) {
+ return Inst<U128>(Opcode::AESEncryptSingleRound, a);
+ }
+
+ U128 AESInverseMixColumns(const U128& a) {
+ return Inst<U128>(Opcode::AESInverseMixColumns, a);
+ }
+
+ U128 AESMixColumns(const U128& a) {
+ return Inst<U128>(Opcode::AESMixColumns, a);
+ }
+
+ U8 SM4AccessSubstitutionBox(const U8& a) {
+ return Inst<U8>(Opcode::SM4AccessSubstitutionBox, a);
+ }
+
+ U128 SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1) {
+ return Inst<U128>(Opcode::SHA256Hash, x, y, w, Imm1(part1));
+ }
+
+ U128 SHA256MessageSchedule0(const U128& x, const U128& y) {
+ return Inst<U128>(Opcode::SHA256MessageSchedule0, x, y);
+ }
+
+ U128 SHA256MessageSchedule1(const U128& x, const U128& y, const U128& z) {
+ return Inst<U128>(Opcode::SHA256MessageSchedule1, x, y, z);
+ }
+
+ UAny VectorGetElement(size_t esize, const U128& a, size_t index) {
+ ASSERT_MSG(esize * index < 128, "Invalid index");
+ switch (esize) {
+ case 8:
+ return Inst<U8>(Opcode::VectorGetElement8, a, Imm8(static_cast<u8>(index)));
+ case 16:
+ return Inst<U16>(Opcode::VectorGetElement16, a, Imm8(static_cast<u8>(index)));
+ case 32:
+ return Inst<U32>(Opcode::VectorGetElement32, a, Imm8(static_cast<u8>(index)));
+ case 64:
+ return Inst<U64>(Opcode::VectorGetElement64, a, Imm8(static_cast<u8>(index)));
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorSetElement(size_t esize, const U128& a, size_t index, const IR::UAny& elem) {
+ ASSERT_MSG(esize * index < 128, "Invalid index");
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSetElement8, a, Imm8(static_cast<u8>(index)), elem);
+ case 16:
+ return Inst<U128>(Opcode::VectorSetElement16, a, Imm8(static_cast<u8>(index)), elem);
+ case 32:
+ return Inst<U128>(Opcode::VectorSetElement32, a, Imm8(static_cast<u8>(index)), elem);
+ case 64:
+ return Inst<U128>(Opcode::VectorSetElement64, a, Imm8(static_cast<u8>(index)), elem);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorAbs(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorAbs8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorAbs16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorAbs32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorAbs64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorAdd(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorAdd8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorAdd16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorAdd32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorAdd64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorAnd(const U128& a, const U128& b) {
+ return Inst<U128>(Opcode::VectorAnd, a, b);
+ }
+
+ U128 VectorAndNot(const U128& a, const U128& b) {
+ return Inst<U128>(Opcode::VectorAndNot, a, b);
+ }
+
+ U128 VectorArithmeticShiftRight(size_t esize, const U128& a, u8 shift_amount) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorArithmeticShiftRight8, a, Imm8(shift_amount));
+ case 16:
+ return Inst<U128>(Opcode::VectorArithmeticShiftRight16, a, Imm8(shift_amount));
+ case 32:
+ return Inst<U128>(Opcode::VectorArithmeticShiftRight32, a, Imm8(shift_amount));
+ case 64:
+ return Inst<U128>(Opcode::VectorArithmeticShiftRight64, a, Imm8(shift_amount));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorArithmeticVShift(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorArithmeticVShift8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorArithmeticVShift16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorArithmeticVShift32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorArithmeticVShift64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorBroadcastLower(size_t esize, const UAny& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorBroadcastLower8, U8(a));
+ case 16:
+ return Inst<U128>(Opcode::VectorBroadcastLower16, U16(a));
+ case 32:
+ return Inst<U128>(Opcode::VectorBroadcastLower32, U32(a));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorBroadcast(size_t esize, const UAny& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorBroadcast8, U8(a));
+ case 16:
+ return Inst<U128>(Opcode::VectorBroadcast16, U16(a));
+ case 32:
+ return Inst<U128>(Opcode::VectorBroadcast32, U32(a));
+ case 64:
+ return Inst<U128>(Opcode::VectorBroadcast64, U64(a));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorBroadcastElementLower(size_t esize, const U128& a, size_t index) {
+ ASSERT_MSG(esize * index < 128, "Invalid index");
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorBroadcastElementLower8, a, u8(index));
+ case 16:
+ return Inst<U128>(Opcode::VectorBroadcastElementLower16, a, u8(index));
+ case 32:
+ return Inst<U128>(Opcode::VectorBroadcastElementLower32, a, u8(index));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorBroadcastElement(size_t esize, const U128& a, size_t index) {
+ ASSERT_MSG(esize * index < 128, "Invalid index");
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorBroadcastElement8, a, u8(index));
+ case 16:
+ return Inst<U128>(Opcode::VectorBroadcastElement16, a, u8(index));
+ case 32:
+ return Inst<U128>(Opcode::VectorBroadcastElement32, a, u8(index));
+ case 64:
+ return Inst<U128>(Opcode::VectorBroadcastElement64, a, u8(index));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorCountLeadingZeros(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorCountLeadingZeros8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorCountLeadingZeros16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorCountLeadingZeros32, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorDeinterleaveEven(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorDeinterleaveEven8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorDeinterleaveEven16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorDeinterleaveEven32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorDeinterleaveEven64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorDeinterleaveOdd(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorDeinterleaveOdd8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorDeinterleaveOdd16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorDeinterleaveOdd32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorDeinterleaveOdd64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorDeinterleaveEvenLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorDeinterleaveEvenLower8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorDeinterleaveEvenLower16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorDeinterleaveEvenLower32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorDeinterleaveOddLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorDeinterleaveOddLower8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorDeinterleaveOddLower16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorDeinterleaveOddLower32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorEor(const U128& a, const U128& b) {
+ return Inst<U128>(Opcode::VectorEor, a, b);
+ }
+
+ U128 VectorEqual(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorEqual8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorEqual16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorEqual32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorEqual64, a, b);
+ case 128:
+ return Inst<U128>(Opcode::VectorEqual128, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorExtract(const U128& a, const U128& b, size_t position) {
+ ASSERT(position <= 128);
+ return Inst<U128>(Opcode::VectorExtract, a, b, Imm8(static_cast<u8>(position)));
+ }
+
+ U128 VectorExtractLower(const U128& a, const U128& b, size_t position) {
+ ASSERT(position <= 64);
+ return Inst<U128>(Opcode::VectorExtractLower, a, b, Imm8(static_cast<u8>(position)));
+ }
+
+ U128 VectorGreaterSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorGreaterS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorGreaterS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorGreaterS32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorGreaterS64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorGreaterEqualSigned(size_t esize, const U128& a, const U128& b) {
+ return VectorOr(VectorGreaterSigned(esize, a, b), VectorEqual(esize, a, b));
+ }
+
+ U128 VectorGreaterEqualUnsigned(size_t esize, const U128& a, const U128& b) {
+ return VectorEqual(esize, VectorMaxUnsigned(esize, a, b), a);
+ }
+
+ U128 VectorGreaterUnsigned(size_t esize, const U128& a, const U128& b) {
+ return VectorNot(VectorEqual(esize, VectorMinUnsigned(esize, a, b), a));
+ }
+
+ U128 VectorHalvingAddSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorHalvingAddS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorHalvingAddS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorHalvingAddS32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorHalvingAddU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorHalvingAddU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorHalvingAddU32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorHalvingSubSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorHalvingSubS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorHalvingSubS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorHalvingSubS32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorHalvingSubUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorHalvingSubU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorHalvingSubU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorHalvingSubU32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorInterleaveLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorInterleaveLower8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorInterleaveLower16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorInterleaveLower32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorInterleaveLower64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorInterleaveUpper(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorInterleaveUpper8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorInterleaveUpper16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorInterleaveUpper32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorInterleaveUpper64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorLessEqualSigned(size_t esize, const U128& a, const U128& b) {
+ return VectorNot(VectorGreaterSigned(esize, a, b));
+ }
+
+ U128 VectorLessEqualUnsigned(size_t esize, const U128& a, const U128& b) {
+ return VectorEqual(esize, VectorMinUnsigned(esize, a, b), a);
+ }
+
+ U128 VectorLessSigned(size_t esize, const U128& a, const U128& b) {
+ return VectorNot(VectorOr(VectorGreaterSigned(esize, a, b), VectorEqual(esize, a, b)));
+ }
+
+ U128 VectorLessUnsigned(size_t esize, const U128& a, const U128& b) {
+ return VectorNot(VectorEqual(esize, VectorMaxUnsigned(esize, a, b), a));
+ }
+
+ U128 VectorLogicalShiftLeft(size_t esize, const U128& a, u8 shift_amount) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorLogicalShiftLeft8, a, Imm8(shift_amount));
+ case 16:
+ return Inst<U128>(Opcode::VectorLogicalShiftLeft16, a, Imm8(shift_amount));
+ case 32:
+ return Inst<U128>(Opcode::VectorLogicalShiftLeft32, a, Imm8(shift_amount));
+ case 64:
+ return Inst<U128>(Opcode::VectorLogicalShiftLeft64, a, Imm8(shift_amount));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorLogicalShiftRight(size_t esize, const U128& a, u8 shift_amount) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorLogicalShiftRight8, a, Imm8(shift_amount));
+ case 16:
+ return Inst<U128>(Opcode::VectorLogicalShiftRight16, a, Imm8(shift_amount));
+ case 32:
+ return Inst<U128>(Opcode::VectorLogicalShiftRight32, a, Imm8(shift_amount));
+ case 64:
+ return Inst<U128>(Opcode::VectorLogicalShiftRight64, a, Imm8(shift_amount));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorLogicalVShift(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorLogicalVShift8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorLogicalVShift16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorLogicalVShift32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorLogicalVShift64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMaxSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMaxS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMaxS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMaxS32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorMaxS64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMaxUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMaxU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMaxU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMaxU32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorMaxU64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMinSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMinS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMinS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMinS32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorMinS64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMinUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMinU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMinU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMinU32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorMinU64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMultiply(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMultiply8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMultiply16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMultiply32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorMultiply64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMultiplySignedWiden(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMultiplySignedWiden8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMultiplySignedWiden16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMultiplySignedWiden32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorMultiplyUnsignedWiden(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorMultiplyUnsignedWiden32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorNarrow(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorNarrow16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorNarrow32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorNarrow64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorNot(const U128& a) {
+ return Inst<U128>(Opcode::VectorNot, a);
+ }
+
+ U128 VectorOr(const U128& a, const U128& b) {
+ return Inst<U128>(Opcode::VectorOr, a, b);
+ }
+
+ U128 VectorPairedAdd(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedAdd8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedAdd16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedAdd32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorPairedAdd64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorPairedAddLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedAddLower8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedAddLower16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedAddLower32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorPairedAddSignedWiden(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedAddSignedWiden8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedAddSignedWiden16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedAddSignedWiden32, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorPairedAddUnsignedWiden(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedAddUnsignedWiden32, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorPairedMaxSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMaxS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMaxS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMaxS32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMaxUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMaxU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMaxU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMaxU32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMinSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMinS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMinS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMinS32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMinUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMinU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMinU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMinU32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMaxSignedLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerS32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMaxUnsignedLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMaxLowerU32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMinSignedLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMinLowerS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMinLowerS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMinLowerS32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPairedMinUnsignedLower(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPairedMinLowerU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorPairedMinLowerU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorPairedMinLowerU32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPolynomialMultiply(const U128& a, const U128& b) {
+ return Inst<U128>(Opcode::VectorPolynomialMultiply8, a, b);
+ }
+
+ U128 VectorPolynomialMultiplyLong(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorPolynomialMultiplyLong8, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorPolynomialMultiplyLong64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorPopulationCount(const U128& a) {
+ return Inst<U128>(Opcode::VectorPopulationCount, a);
+ }
+
+ U128 VectorReverseBits(const U128& a) {
+ return Inst<U128>(Opcode::VectorReverseBits, a);
+ }
+
+ U128 VectorReverseElementsInHalfGroups(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorReverseElementsInHalfGroups8, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorReverseElementsInWordGroups(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorReverseElementsInWordGroups8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorReverseElementsInWordGroups16, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorReverseElementsInLongGroups(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorReverseElementsInLongGroups8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorReverseElementsInLongGroups16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorReverseElementsInLongGroups32, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorReduceAdd(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorReduceAdd8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorReduceAdd16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorReduceAdd32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorReduceAdd64, a);
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 VectorRotateLeft(size_t esize, const U128& a, u8 amount) {
+ ASSERT(amount < esize);
+
+ if (amount == 0) {
+ return a;
+ }
+
+ return VectorOr(VectorLogicalShiftLeft(esize, a, amount),
+ VectorLogicalShiftRight(esize, a, static_cast<u8>(esize - amount)));
+ }
+
+ U128 VectorRotateRight(size_t esize, const U128& a, u8 amount) {
+ ASSERT(amount < esize);
+
+ if (amount == 0) {
+ return a;
+ }
+
+ return VectorOr(VectorLogicalShiftRight(esize, a, amount),
+ VectorLogicalShiftLeft(esize, a, static_cast<u8>(esize - amount)));
+ }
+
+ U128 VectorRotateWholeVectorRight(const U128& a, u8 amount) {
+ ASSERT(amount % 32 == 0);
+ return Inst<U128>(Opcode::VectorRotateWholeVectorRight, a, Imm8(amount));
+ }
+
+ U128 VectorRoundingHalvingAddSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddS32, a, b);
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 VectorRoundingHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorRoundingHalvingAddU32, a, b);
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 VectorRoundingShiftLeftSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftS8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftS16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftS32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftS64, a, b);
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 VectorRoundingShiftLeftUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftU8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftU16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftU32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorRoundingShiftLeftU64, a, b);
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 VectorSignExtend(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignExtend8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignExtend16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignExtend32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignExtend64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedAbsoluteDifference8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedAbsoluteDifference16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedAbsoluteDifference32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ UpperAndLower VectorSignedMultiply(size_t esize, const U128& a, const U128& b) {
+ const Value multiply = [&] {
+ switch (esize) {
+ case 16:
+ return Inst(Opcode::VectorSignedMultiply16, a, b);
+ case 32:
+ return Inst(Opcode::VectorSignedMultiply32, a, b);
+ }
+ UNREACHABLE();
+ }();
+
+ return {
+ Inst<U128>(Opcode::GetUpperFromOp, multiply),
+ Inst<U128>(Opcode::GetLowerFromOp, multiply),
+ };
+ }
+
+ U128 VectorSignedSaturatedAbs(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAbs8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAbs16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAbs32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAbs64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedAccumulateUnsigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedAccumulateUnsigned64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedDoublingMultiplyHigh(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHigh16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHigh32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorSignedSaturatedDoublingMultiplyHighRounding(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding32, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 VectorSignedSaturatedDoublingMultiplyLong(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyLong16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedDoublingMultiplyLong32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToSigned64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNarrowToUnsigned64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedNeg(size_t esize, const U128& a) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNeg8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNeg16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNeg32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedNeg64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeft64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSignedSaturatedShiftLeftUnsigned(size_t esize, const U128& a, u8 shift_amount) {
+ ASSERT(shift_amount < esize);
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned8, a, Imm8(shift_amount));
+ case 16:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned16, a, Imm8(shift_amount));
+ case 32:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned32, a, Imm8(shift_amount));
+ case 64:
+ return Inst<U128>(Opcode::VectorSignedSaturatedShiftLeftUnsigned64, a, Imm8(shift_amount));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorSub(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorSub8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorSub16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorSub32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorSub64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ Table VectorTable(std::vector<U64> values) {
+ ASSERT(values.size() >= 1 && values.size() <= 4);
+ values.resize(4);
+ return Inst<Table>(Opcode::VectorTable, values[0], values[1], values[2], values[3]);
+ }
+
+ Table VectorTable(std::vector<U128> values) {
+ ASSERT(values.size() >= 1 && values.size() <= 4);
+ values.resize(4);
+ return Inst<Table>(Opcode::VectorTable, values[0], values[1], values[2], values[3]);
+ }
+
+ U64 VectorTableLookup(const U64& defaults, const Table& table, const U64& indices) {
+ ASSERT(table.GetInst()->GetArg(0).GetType() == Type::U64);
+ return Inst<U64>(Opcode::VectorTableLookup64, defaults, table, indices);
+ }
+
+ U128 VectorTableLookup(const U128& defaults, const Table& table, const U128& indices) {
+ ASSERT(table.GetInst()->GetArg(0).GetType() == Type::U128);
+ return Inst<U128>(Opcode::VectorTableLookup128, defaults, table, indices);
+ }
+
+ U128 VectorTranspose(size_t esize, const U128& a, const U128& b, bool part) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorTranspose8, a, b, Imm1(part));
+ case 16:
+ return Inst<U128>(Opcode::VectorTranspose16, a, b, Imm1(part));
+ case 32:
+ return Inst<U128>(Opcode::VectorTranspose32, a, b, Imm1(part));
+ case 64:
+ return Inst<U128>(Opcode::VectorTranspose64, a, b, Imm1(part));
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorUnsignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedAbsoluteDifference32, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorUnsignedRecipEstimate(const U128& a) {
+ return Inst<U128>(Opcode::VectorUnsignedRecipEstimate, a);
+ }
+
+ U128 VectorUnsignedRecipSqrtEstimate(const U128& a) {
+ return Inst<U128>(Opcode::VectorUnsignedRecipSqrtEstimate, a);
+ }
+
+ U128 VectorUnsignedSaturatedAccumulateSigned(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedAccumulateSigned64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorUnsignedSaturatedNarrow(size_t esize, const U128& a) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedNarrow64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorUnsignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) {
+ switch (esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft8, a, b);
+ case 16:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft16, a, b);
+ case 32:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft32, a, b);
+ case 64:
+ return Inst<U128>(Opcode::VectorUnsignedSaturatedShiftLeft64, a, b);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorZeroExtend(size_t original_esize, const U128& a) {
+ switch (original_esize) {
+ case 8:
+ return Inst<U128>(Opcode::VectorZeroExtend8, a);
+ case 16:
+ return Inst<U128>(Opcode::VectorZeroExtend16, a);
+ case 32:
+ return Inst<U128>(Opcode::VectorZeroExtend32, a);
+ case 64:
+ return Inst<U128>(Opcode::VectorZeroExtend64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 VectorZeroUpper(const U128& a) {
+ return Inst<U128>(Opcode::VectorZeroUpper, a);
+ }
+
+ U128 ZeroVector() {
+ return Inst<U128>(Opcode::ZeroVector);
+ }
+
+ U16U32U64 FPAbs(const U16U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPAbs16, a);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPAbs32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPAbs64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPAdd(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPAdd32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPAdd64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ NZCV FPCompare(const U32U64& a, const U32U64& b, bool exc_on_qnan) {
+ ASSERT(a.GetType() == b.GetType());
+
+ const IR::U1 exc_on_qnan_imm = Imm1(exc_on_qnan);
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<NZCV>(Opcode::FPCompare32, a, b, exc_on_qnan_imm);
+ case Type::U64:
+ return Inst<NZCV>(Opcode::FPCompare64, a, b, exc_on_qnan_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPDiv(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPDiv32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPDiv64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMax(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMax32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMax64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMaxNumeric(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMaxNumeric32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMaxNumeric64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMin(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMin32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMin64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMinNumeric(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMinNumeric32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMinNumeric64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMul(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMul32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMul64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPMulAdd(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPMulAdd16, a, b, c);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMulAdd32, a, b, c);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMulAdd64, a, b, c);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPMulSub(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPMulSub16, a, b, c);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMulSub32, a, b, c);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMulSub64, a, b, c);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPMulX(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPMulX32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPMulX64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPNeg(const U16U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPNeg16, a);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPNeg32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPNeg64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRecipEstimate(const U16U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRecipEstimate16, a);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRecipEstimate32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRecipEstimate64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRecipExponent(const U16U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRecipExponent16, a);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRecipExponent32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRecipExponent64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRecipStepFused(const U16U32U64& a, const U16U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRecipStepFused16, a, b);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRecipStepFused32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRecipStepFused64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact) {
+ const u8 rounding_value = static_cast<u8>(rounding);
+ const IR::U1 exact_imm = Imm1(exact);
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRoundInt16, a, rounding_value, exact_imm);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRoundInt32, a, rounding_value, exact_imm);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRoundInt64, a, rounding_value, exact_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRSqrtEstimate(const U16U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRSqrtEstimate16, a);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRSqrtEstimate32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRSqrtEstimate64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16U32U64 FPRSqrtStepFused(const U16U32U64& a, const U16U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPRSqrtStepFused16, a, b);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPRSqrtStepFused32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPRSqrtStepFused64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPSqrt(const U32U64& a) {
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPSqrt32, a);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPSqrt64, a);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32U64 FPSub(const U32U64& a, const U32U64& b) {
+ ASSERT(a.GetType() == b.GetType());
+
+ switch (a.GetType()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::FPSub32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPSub64, a, b);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16 FPDoubleToHalf(const U64& a, FP::RoundingMode rounding) {
+ return Inst<U16>(Opcode::FPDoubleToHalf, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U32 FPDoubleToSingle(const U64& a, FP::RoundingMode rounding) {
+ return Inst<U32>(Opcode::FPDoubleToSingle, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U64 FPHalfToDouble(const U16& a, FP::RoundingMode rounding) {
+ return Inst<U64>(Opcode::FPHalfToDouble, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U32 FPHalfToSingle(const U16& a, FP::RoundingMode rounding) {
+ return Inst<U32>(Opcode::FPHalfToSingle, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U64 FPSingleToDouble(const U32& a, FP::RoundingMode rounding) {
+ return Inst<U64>(Opcode::FPSingleToDouble, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U16 FPSingleToHalf(const U32& a, FP::RoundingMode rounding) {
+ return Inst<U16>(Opcode::FPSingleToHalf, a, Imm8(static_cast<u8>(rounding)));
+ }
+
+ U16 FPToFixedS16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 16);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPHalfToFixedS16, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U16>(Opcode::FPSingleToFixedS16, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U16>(Opcode::FPDoubleToFixedS16, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 FPToFixedS32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 32);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U32>(Opcode::FPHalfToFixedS32, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPSingleToFixedS32, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U32>(Opcode::FPDoubleToFixedS32, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U64 FPToFixedS64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 64);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U64>(Opcode::FPHalfToFixedS64, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U64>(Opcode::FPSingleToFixedS64, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPDoubleToFixedS64, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U16 FPToFixedU16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 16);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U16>(Opcode::FPHalfToFixedU16, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U16>(Opcode::FPSingleToFixedU16, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U16>(Opcode::FPDoubleToFixedU16, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 FPToFixedU32(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 32);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U32>(Opcode::FPHalfToFixedU32, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPSingleToFixedU32, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U32>(Opcode::FPDoubleToFixedU32, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U64 FPToFixedU64(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= 64);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U64>(Opcode::FPHalfToFixedU64, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U64>(Opcode::FPSingleToFixedU64, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPDoubleToFixedU64, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 FPSignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
+
+ const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U32>(Opcode::FPFixedS16ToSingle, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPFixedS32ToSingle, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U32>(Opcode::FPFixedS64ToSingle, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U32 FPUnsignedFixedToSingle(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
+
+ const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U32>(Opcode::FPFixedU16ToSingle, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U32>(Opcode::FPFixedU32ToSingle, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U32>(Opcode::FPFixedU64ToSingle, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U64 FPSignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
+
+ const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U64>(Opcode::FPFixedS16ToDouble, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U64>(Opcode::FPFixedS32ToDouble, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPFixedS64ToDouble, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U64 FPUnsignedFixedToDouble(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) {
+ ASSERT(fbits <= (a.GetType() == Type::U16 ? 16 : (a.GetType() == Type::U32 ? 32 : 64)));
+
+ const IR::U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (a.GetType()) {
+ case Type::U16:
+ return Inst<U64>(Opcode::FPFixedU16ToDouble, a, fbits_imm, rounding_imm);
+ case Type::U32:
+ return Inst<U64>(Opcode::FPFixedU32ToDouble, a, fbits_imm, rounding_imm);
+ case Type::U64:
+ return Inst<U64>(Opcode::FPFixedU64ToDouble, a, fbits_imm, rounding_imm);
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ U128 FPVectorAbs(size_t esize, const U128& a) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorAbs16, a);
+ case 32:
+ return Inst<U128>(Opcode::FPVectorAbs32, a);
+ case 64:
+ return Inst<U128>(Opcode::FPVectorAbs64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorAdd32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorAdd64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorDiv(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorDiv32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorDiv64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorEqual16, a, b, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorEqual32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorEqual64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorFromHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(esize == 32);
+ return Inst<U128>(Opcode::FPVectorFromHalf32, a, Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ }
+
+ U128 FPVectorFromSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(fbits <= esize);
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorFromSignedFixed32, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorFromSignedFixed64, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorFromUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(fbits <= esize);
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorFromUnsignedFixed32, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorFromUnsignedFixed64, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorGreater(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorGreater32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorGreater64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorGreaterEqual(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorGreaterEqual32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorGreaterEqual64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMax(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMax32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMax64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMaxNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMaxNumeric32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMaxNumeric64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMin(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMin32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMin64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMinNumeric(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMinNumeric32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMinNumeric64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMul(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMul32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMul64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMulAdd(size_t esize, const U128& a, const U128& b, const U128& c, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorMulAdd16, a, b, c, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMulAdd32, a, b, c, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMulAdd64, a, b, c, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorMulX(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorMulX32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorMulX64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorNeg(size_t esize, const U128& a) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorNeg16, a);
+ case 32:
+ return Inst<U128>(Opcode::FPVectorNeg32, a);
+ case 64:
+ return Inst<U128>(Opcode::FPVectorNeg64, a);
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorPairedAdd(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorPairedAdd32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorPairedAdd64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorPairedAddLower(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorPairedAddLower32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorPairedAddLower64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorRecipEstimate(size_t esize, const U128& a, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorRecipEstimate16, a, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorRecipEstimate32, a, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorRecipEstimate64, a, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorRecipStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorRecipStepFused16, a, b, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorRecipStepFused32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorRecipStepFused64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorRoundInt(size_t esize, const U128& operand, FP::RoundingMode rounding, bool exact, bool fpcr_controlled = true) {
+ const IR::U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+ const IR::U1 exact_imm = Imm1(exact);
+
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorRoundInt16, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorRoundInt32, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorRoundInt64, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorRSqrtEstimate(size_t esize, const U128& a, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorRSqrtEstimate16, a, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorRSqrtEstimate32, a, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorRSqrtEstimate64, a, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorRSqrtStepFused(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorRSqrtStepFused16, a, b, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorRSqrtStepFused32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorRSqrtStepFused64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorSqrt(size_t esize, const U128& a, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorSqrt32, a, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorSqrt64, a, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorSub(size_t esize, const U128& a, const U128& b, bool fpcr_controlled = true) {
+ switch (esize) {
+ case 32:
+ return Inst<U128>(Opcode::FPVectorSub32, a, b, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorSub64, a, b, Imm1(fpcr_controlled));
+ }
+ UNREACHABLE();
+ }
+
+ U128 FPVectorToHalf(size_t esize, const U128& a, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(esize == 32);
+ return Inst<U128>(Opcode::FPVectorToHalf32, a, Imm8(static_cast<u8>(rounding)), Imm1(fpcr_controlled));
+ }
+
+ U128 FPVectorToSignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(fbits <= esize);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorToSignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorToSignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorToSignedFixed64, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ }
+
+ UNREACHABLE();
+ }
+
+ U128 FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true) {
+ ASSERT(fbits <= esize);
+
+ const U8 fbits_imm = Imm8(static_cast<u8>(fbits));
+ const U8 rounding_imm = Imm8(static_cast<u8>(rounding));
+
+ switch (esize) {
+ case 16:
+ return Inst<U128>(Opcode::FPVectorToUnsignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ case 32:
+ return Inst<U128>(Opcode::FPVectorToUnsignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ case 64:
+ return Inst<U128>(Opcode::FPVectorToUnsignedFixed64, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled));
+ }
+
+ UNREACHABLE();
+ }
+
+ void Breakpoint() {
+ Inst(Opcode::Breakpoint);
+ }
+
+ void CallHostFunction(void (*fn)(void)) {
+ Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), Value{}, Value{}, Value{});
+ }
+
+ void CallHostFunction(void (*fn)(u64), const U64& arg1) {
+ Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, Value{}, Value{});
+ }
+
+ void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) {
+ Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, Value{});
+ }
+
+ void CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3) {
+ Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, arg3);
+ }
+
+ void SetTerm(const Terminal& terminal) {
+ block.SetTerminal(terminal);
+ }
void SetInsertionPointBefore(IR::Inst* new_insertion_point) {
insertion_point = IR::Block::iterator{*new_insertion_point};