From fe4f5a3860fcb2941f2dabe1327c7bd2eb229ca6 Mon Sep 17 00:00:00 2001 From: Ghost <> Date: Sun, 13 Jul 2025 23:03:26 +0200 Subject: [PATCH] [dynarmic] lea over mov and other stuff (#24) Co-authored-by: Esther1024 Co-authored-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/24 Co-authored-by: Ghost <> Co-committed-by: Ghost <> --- .gitignore | 1 + externals/dynarmic/CMakeLists.txt | 6 +- .../dynarmic/src/dynarmic/CMakeLists.txt | 105 - .../dynarmic/src/dynarmic/backend/arm64/abi.h | 3 +- .../src/dynarmic/backend/riscv64/code_block.h | 13 +- .../src/dynarmic/backend/x64/a32_emit_x64.cpp | 47 +- .../src/dynarmic/backend/x64/a64_emit_x64.cpp | 7 +- .../backend/x64/a64_emit_x64_memory.cpp | 16 +- .../dynarmic/backend/x64/block_of_code.cpp | 9 +- .../src/dynarmic/backend/x64/emit_x64.cpp | 9 +- .../backend/x64/emit_x64_data_processing.cpp | 1 - .../backend/x64/emit_x64_floating_point.cpp | 80 +- .../dynarmic/backend/x64/emit_x64_memory.h | 7 +- .../x64/emit_x64_vector_floating_point.cpp | 39 +- .../x64/emit_x64_vector_saturation.cpp | 3 + .../backend/x64/exception_handler_windows.cpp | 2 +- .../dynarmic/frontend/A32/a32_ir_emitter.h | 12 +- .../src/dynarmic/frontend/A32/decoder/arm.h | 11 +- .../frontend/A32/translate/a32_translate.cpp | 48 + .../A32/translate/impl/a32_translate_impl.cpp | 4 + .../A32/translate/impl/a32_translate_impl.h | 2 +- .../A32/translate/impl/asimd_three_regs.cpp | 6 +- .../translate/impl/asimd_two_regs_misc.cpp | 30 +- .../translate/impl/asimd_two_regs_shift.cpp | 36 +- .../frontend/A32/translate/impl/common.h | 31 + .../frontend/A32/translate/impl/extension.cpp | 6 +- .../frontend/A32/translate/impl/saturated.cpp | 9 +- ...data_processing_plain_binary_immediate.cpp | 8 +- .../impl/thumb32_data_processing_register.cpp | 5 +- .../A32/translate/impl/thumb32_load_byte.cpp | 8 +- .../translate/impl/thumb32_load_halfword.cpp | 9 +- .../impl/thumb32_load_store_dual.cpp | 4 +- .../impl/thumb32_load_store_multiple.cpp | 4 +- .../A32/translate/impl/thumb32_load_word.cpp | 4 +- .../A32/translate/impl/thumb32_parallel.cpp | 8 +- .../dynarmic/frontend/A64/a64_ir_emitter.cpp | 254 -- .../dynarmic/frontend/A64/a64_ir_emitter.h | 313 +- .../src/dynarmic/frontend/A64/decoder/a64.h | 16 +- .../frontend/A64/translate/a64_translate.cpp | 61 + .../translate/impl/simd_scalar_pairwise.cpp | 20 +- .../impl/simd_scalar_shift_by_immediate.cpp | 58 +- .../translate/impl/simd_scalar_three_same.cpp | 10 +- .../impl/simd_scalar_two_register_misc.cpp | 52 +- .../impl/simd_scalar_x_indexed_element.cpp | 8 +- .../impl/simd_shift_by_immediate.cpp | 98 +- .../translate/impl/simd_three_different.cpp | 54 +- .../A64/translate/impl/simd_three_same.cpp | 140 +- .../translate/impl/simd_two_register_misc.cpp | 92 +- .../impl/simd_vector_x_indexed_element.cpp | 80 +- .../src/dynarmic/interface/A32/arch_version.h | 4 +- .../src/dynarmic/interface/A32/config.h | 85 +- .../src/dynarmic/interface/A64/config.h | 137 +- .../dynarmic/src/dynarmic/ir/ir_emitter.cpp | 2872 --------------- .../dynarmic/src/dynarmic/ir/ir_emitter.h | 3176 +++++++++++++++-- 54 files changed, 3874 insertions(+), 4249 deletions(-) create mode 100644 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h 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 - T ptr() const { + T ptr() const noexcept { static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(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(); 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(); 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(); #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(); #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(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(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(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 void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list to_daz) { if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) { @@ -473,7 +473,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } template -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; constexpr FPT default_nan = FP::FPInfo::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::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(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional 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(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 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(stack_space + ABI_SHADOW_SPACE)); + code.lea(rsp, ptr[rsp - static_cast(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(code, ctx, result, xmm_a, xmm_b, xmm_c, EmitFPVectorMulAddFallback, 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(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(&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 -ArmDecodeTable GetArmDecodeTable() { +constexpr ArmDecodeTable GetArmDecodeTable() { std::vector> 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 GetArmDecodeTable() { template std::optional>> DecodeArm(u32 instruction) { - static const auto table = GetArmDecodeTable(); - - const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); }; + alignas(64) static const auto table = GetArmDecodeTable(); + 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 #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 #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 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(shift_amount)) : v.ir.VectorArithmeticShiftRight(esize, reg_m, static_cast(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(static_cast(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(static_cast(rotate) * 8); - return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result; -} - // SXTAB , , {, } 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 , #, {, } 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 #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 (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(static_cast(rotate) * 8); - return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result; -} using ShiftFunction = IR::ResultAndCarry (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 #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 #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 - -#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(pc - pc % alignment); -} - -void IREmitter::SetCheckBit(const IR::U1& value) { - Inst(Opcode::A64SetCheckBit, value); -} - -IR::U1 IREmitter::GetCFlag() { - return Inst(Opcode::A64GetCFlag); -} - -IR::U32 IREmitter::GetNZCVRaw() { - return Inst(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(exception))); -} - -void IREmitter::DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) { - Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast(op)), value); -} - -void IREmitter::InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) { - Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast(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(Opcode::A64GetCNTFRQ); -} - -IR::U64 IREmitter::GetCNTPCT() { - return Inst(Opcode::A64GetCNTPCT); -} - -IR::U32 IREmitter::GetCTR() { - return Inst(Opcode::A64GetCTR); -} - -IR::U32 IREmitter::GetDCZID() { - return Inst(Opcode::A64GetDCZID); -} - -IR::U64 IREmitter::GetTPIDR() { - return Inst(Opcode::A64GetTPIDR); -} - -void IREmitter::SetTPIDR(const IR::U64& value) { - Inst(Opcode::A64SetTPIDR, value); -} - -IR::U64 IREmitter::GetTPIDRRO() { - return Inst(Opcode::A64GetTPIDRRO); -} - -void IREmitter::ClearExclusive() { - Inst(Opcode::A64ClearExclusive); -} - -IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); -} - -IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) { - return Inst(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(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(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(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(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(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type}); -} - -IR::U32 IREmitter::GetW(Reg reg) { - if (reg == Reg::ZR) - return Imm32(0); - return Inst(Opcode::A64GetW, IR::Value(reg)); -} - -IR::U64 IREmitter::GetX(Reg reg) { - if (reg == Reg::ZR) - return Imm64(0); - return Inst(Opcode::A64GetX, IR::Value(reg)); -} - -IR::U128 IREmitter::GetS(Vec vec) { - return Inst(Opcode::A64GetS, IR::Value(vec)); -} - -IR::U128 IREmitter::GetD(Vec vec) { - return Inst(Opcode::A64GetD, IR::Value(vec)); -} - -IR::U128 IREmitter::GetQ(Vec vec) { - return Inst(Opcode::A64GetQ, IR::Value(vec)); -} - -IR::U64 IREmitter::GetSP() { - return Inst(Opcode::A64GetSP); -} - -IR::U32 IREmitter::GetFPCR() { - return Inst(Opcode::A64GetFPCR); -} - -IR::U32 IREmitter::GetFPSR() { - return Inst(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 #include +#include #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 current_location; - u64 PC() const; - u64 AlignPC(size_t alignment) const; + using Opcode = IR::Opcode; - void SetCheckBit(const IR::U1& value); - IR::U1 GetCFlag(); - IR::U32 GetNZCVRaw(); - void SetNZCVRaw(IR::U32 value); - void SetNZCV(const IR::NZCV& nzcv); + u64 PC() const noexcept { + return current_location->PC(); + } - 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); + u64 AlignPC(size_t alignment) const noexcept { + const u64 pc = PC(); + return static_cast(pc - pc % alignment); + } - 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); + void SetCheckBit(const IR::U1& value) noexcept { + Inst(Opcode::A64SetCheckBit, value); + } - 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); + IR::U1 GetCFlag() noexcept { + return Inst(Opcode::A64GetCFlag); + } + + IR::U32 GetNZCVRaw() noexcept { + return Inst(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(exception))); + } + + void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) noexcept { + Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast(op)), value); + } + + void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) noexcept { + Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast(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(Opcode::A64GetCNTFRQ); + } + + IR::U64 GetCNTPCT() noexcept { + return Inst(Opcode::A64GetCNTPCT); + } + + IR::U32 GetCTR() noexcept { + return Inst(Opcode::A64GetCTR); + } + + IR::U32 GetDCZID() noexcept { + return Inst(Opcode::A64GetDCZID); + } + + IR::U64 GetTPIDR() noexcept { + return Inst(Opcode::A64GetTPIDR); + } + + void SetTPIDR(const IR::U64& value) noexcept { + Inst(Opcode::A64SetTPIDR, value); + } + + IR::U64 GetTPIDRRO() noexcept { + return Inst(Opcode::A64GetTPIDRRO); + } + + void ClearExclusive() noexcept { + Inst(Opcode::A64ClearExclusive); + } + + IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type}); + } + + IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept { + return Inst(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(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(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(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(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(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type}); + } + + IR::U32 GetW(Reg reg) noexcept { + if (reg == Reg::ZR) + return Imm32(0); + return Inst(Opcode::A64GetW, IR::Value(reg)); + } + + IR::U64 GetX(Reg reg) noexcept { + if (reg == Reg::ZR) + return Imm64(0); + return Inst(Opcode::A64GetX, IR::Value(reg)); + } + + IR::U128 GetS(Vec vec) noexcept { + return Inst(Opcode::A64GetS, IR::Value(vec)); + } + + IR::U128 GetD(Vec vec) noexcept { + return Inst(Opcode::A64GetD, IR::Value(vec)); + } + + IR::U128 GetQ(Vec vec) noexcept { + return Inst(Opcode::A64GetQ, IR::Value(vec)); + } + + IR::U64 GetSP() noexcept { + return Inst(Opcode::A64GetSP); + } + + IR::U32 GetFPCR() noexcept { + return Inst(Opcode::A64GetFPCR); + } + + IR::U32 GetFPSR() noexcept { + return Inst(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 -DecodeTable GetDecodeTable() { +constexpr DecodeTable GetDecodeTable() { std::vector> 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 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{ + "MOVI, MVNI, ORR, BIC (vector, immediate)", + "FMOV (vector, immediate)", + "Unallocated SIMD modified immediate", + }.count(matcher.GetName()) > 0; }); DecodeTable table{}; @@ -75,7 +74,6 @@ std::optional>> 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>>(*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 Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) { +std::pair 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()}; } @@ -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 Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) { +std::pair 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()}; } @@ -19,19 +19,19 @@ std::pair Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> return {concatenate(H, L).ZeroExtend(), concatenate(M, Vmlo).ZeroExtend()}; } -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(); @@ -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 + 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* page_table = nullptr; + + /// Coprocessors + std::array, 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 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* 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 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, 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 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 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(Opcode::Pack2x32To1x64, lo, hi); -} - -U128 IREmitter::Pack2x64To1x128(const U64& lo, const U64& hi) { - return Inst(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(Opcode::LeastSignificantWord, value); -} - -U16 IREmitter::LeastSignificantHalf(U32U64 value) { - if (value.GetType() == Type::U64) { - value = LeastSignificantWord(value); - } - return Inst(Opcode::LeastSignificantHalf, value); -} - -U8 IREmitter::LeastSignificantByte(U32U64 value) { - if (value.GetType() == Type::U64) { - value = LeastSignificantWord(value); - } - return Inst(Opcode::LeastSignificantByte, value); -} - -ResultAndCarry IREmitter::MostSignificantWord(const U64& value) { - const auto result = Inst(Opcode::MostSignificantWord, value); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - return {result, carry_out}; -} - -U1 IREmitter::MostSignificantBit(const U32& value) { - return Inst(Opcode::MostSignificantBit, value); -} - -U1 IREmitter::IsZero(const U32& value) { - return Inst(Opcode::IsZero32, value); -} - -U1 IREmitter::IsZero(const U64& value) { - return Inst(Opcode::IsZero64, value); -} - -U1 IREmitter::IsZero(const U32U64& value) { - if (value.GetType() == Type::U32) { - return Inst(Opcode::IsZero32, value); - } else { - return Inst(Opcode::IsZero64, value); - } -} - -U1 IREmitter::TestBit(const U32U64& value, const U8& bit) { - if (value.GetType() == Type::U32) { - return Inst(Opcode::TestBit, IndeterminateExtendToLong(value), bit); - } else { - return Inst(Opcode::TestBit, value, bit); - } -} - -U32 IREmitter::ConditionalSelect(Cond cond, const U32& a, const U32& b) { - return Inst(Opcode::ConditionalSelect32, Value{cond}, a, b); -} - -U64 IREmitter::ConditionalSelect(Cond cond, const U64& a, const U64& b) { - return Inst(Opcode::ConditionalSelect64, Value{cond}, a, b); -} - -NZCV IREmitter::ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b) { - return Inst(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(Opcode::ConditionalSelect32, Value{cond}, a, b); - } else { - return Inst(Opcode::ConditionalSelect64, Value{cond}, a, b); - } -} - -U1 IREmitter::GetCFlagFromNZCV(const NZCV& nzcv) { - return Inst(Opcode::GetCFlagFromNZCV, nzcv); -} - -NZCV IREmitter::NZCVFromPackedFlags(const U32& a) { - return Inst(Opcode::NZCVFromPackedFlags, a); -} - -NZCV IREmitter::NZCVFrom(const Value& value) { - return Inst(Opcode::GetNZCVFromOp, value); -} - -ResultAndCarry IREmitter::LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in) { - const auto result = Inst(Opcode::LogicalShiftLeft32, value_in, shift_amount, carry_in); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - return {result, carry_out}; -} - -ResultAndCarry IREmitter::LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { - const auto result = Inst(Opcode::LogicalShiftRight32, value_in, shift_amount, carry_in); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - return {result, carry_out}; -} - -ResultAndCarry IREmitter::ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { - const auto result = Inst(Opcode::ArithmeticShiftRight32, value_in, shift_amount, carry_in); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - return {result, carry_out}; -} - -ResultAndCarry IREmitter::RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { - const auto result = Inst(Opcode::RotateRight32, value_in, shift_amount, carry_in); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - return {result, carry_out}; -} - -ResultAndCarry IREmitter::RotateRightExtended(const U32& value_in, const U1& carry_in) { - const auto result = Inst(Opcode::RotateRightExtended, value_in, carry_in); - const auto carry_out = Inst(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(Opcode::LogicalShiftLeft32, value_in, shift_amount, Imm1(0)); - } else { - return Inst(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(Opcode::LogicalShiftRight32, value_in, shift_amount, Imm1(0)); - } else { - return Inst(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(Opcode::ArithmeticShiftRight32, value_in, shift_amount, Imm1(0)); - } else { - return Inst(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(Opcode::RotateRight32, value_in, shift_amount, Imm1(0)); - } else { - return Inst(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(Opcode::LogicalShiftLeftMasked32, value_in, shift_amount); - } else { - return Inst(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(Opcode::LogicalShiftRightMasked32, value_in, shift_amount); - } else { - return Inst(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(Opcode::ArithmeticShiftRightMasked32, value_in, shift_amount); - } else { - return Inst(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(Opcode::RotateRightMasked32, value_in, shift_amount); - } else { - return Inst(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(Opcode::Add32, a, b, carry_in); - } else { - return Inst(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(Opcode::Add32, a, b, Imm1(0)); - } else { - return Inst(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(Opcode::Sub32, a, b, carry_in); - } else { - return Inst(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(Opcode::Sub32, a, b, Imm1(1)); - } else { - return Inst(Opcode::Sub64, a, b, Imm1(1)); - } -} - -U32U64 IREmitter::Mul(const U32U64& a, const U32U64& b) { - if (a.GetType() == Type::U32) { - return Inst(Opcode::Mul32, a, b); - } - - return Inst(Opcode::Mul64, a, b); -} - -U64 IREmitter::UnsignedMultiplyHigh(const U64& a, const U64& b) { - return Inst(Opcode::UnsignedMultiplyHigh64, a, b); -} - -U64 IREmitter::SignedMultiplyHigh(const U64& a, const U64& b) { - return Inst(Opcode::SignedMultiplyHigh64, a, b); -} - -U32U64 IREmitter::UnsignedDiv(const U32U64& a, const U32U64& b) { - if (a.GetType() == Type::U32) { - return Inst(Opcode::UnsignedDiv32, a, b); - } - - return Inst(Opcode::UnsignedDiv64, a, b); -} - -U32U64 IREmitter::SignedDiv(const U32U64& a, const U32U64& b) { - if (a.GetType() == Type::U32) { - return Inst(Opcode::SignedDiv32, a, b); - } - - return Inst(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(Opcode::And32, a, b); - } else { - return Inst(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(Opcode::AndNot32, a, b); - } else { - return Inst(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(Opcode::Eor32, a, b); - } else { - return Inst(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(Opcode::Or32, a, b); - } else { - return Inst(Opcode::Or64, a, b); - } -} - -U32U64 IREmitter::Not(const U32U64& a) { - if (a.GetType() == Type::U32) { - return Inst(Opcode::Not32, a); - } else { - return Inst(Opcode::Not64, a); - } -} - -U64 IREmitter::SignExtendToLong(const UAny& a) { - switch (a.GetType()) { - case Type::U8: - return Inst(Opcode::SignExtendByteToLong, a); - case Type::U16: - return Inst(Opcode::SignExtendHalfToLong, a); - case Type::U32: - return Inst(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(Opcode::SignExtendByteToWord, a); - case Type::U16: - return Inst(Opcode::SignExtendHalfToWord, a); - case Type::U32: - return U32(a); - case Type::U64: - return Inst(Opcode::LeastSignificantWord, a); - default: - UNREACHABLE(); - } -} - -U64 IREmitter::SignExtendWordToLong(const U32& a) { - return Inst(Opcode::SignExtendWordToLong, a); -} - -U32 IREmitter::SignExtendHalfToWord(const U16& a) { - return Inst(Opcode::SignExtendHalfToWord, a); -} - -U32 IREmitter::SignExtendByteToWord(const U8& a) { - return Inst(Opcode::SignExtendByteToWord, a); -} - -U64 IREmitter::ZeroExtendToLong(const UAny& a) { - switch (a.GetType()) { - case Type::U8: - return Inst(Opcode::ZeroExtendByteToLong, a); - case Type::U16: - return Inst(Opcode::ZeroExtendHalfToLong, a); - case Type::U32: - return Inst(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(Opcode::ZeroExtendByteToWord, a); - case Type::U16: - return Inst(Opcode::ZeroExtendHalfToWord, a); - case Type::U32: - return U32(a); - case Type::U64: - return Inst(Opcode::LeastSignificantWord, a); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::ZeroExtendToQuad(const UAny& a) { - return Inst(Opcode::ZeroExtendLongToQuad, ZeroExtendToLong(a)); -} - -U64 IREmitter::ZeroExtendWordToLong(const U32& a) { - return Inst(Opcode::ZeroExtendWordToLong, a); -} - -U32 IREmitter::ZeroExtendHalfToWord(const U16& a) { - return Inst(Opcode::ZeroExtendHalfToWord, a); -} - -U32 IREmitter::ZeroExtendByteToWord(const U8& a) { - return Inst(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(Opcode::ByteReverseWord, a); -} - -U16 IREmitter::ByteReverseHalf(const U16& a) { - return Inst(Opcode::ByteReverseHalf, a); -} - -U64 IREmitter::ByteReverseDual(const U64& a) { - return Inst(Opcode::ByteReverseDual, a); -} - -U32U64 IREmitter::CountLeadingZeros(const U32U64& a) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::CountLeadingZeros32, a); - } - - return Inst(Opcode::CountLeadingZeros64, a); -} - -U32U64 IREmitter::ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::ExtractRegister32, a, b, lsb); - } - - return Inst(Opcode::ExtractRegister64, a, b, lsb); -} - -U32U64 IREmitter::ReplicateBit(const U32U64& a, u8 bit) { - if (a.GetType() == IR::Type::U32) { - ASSERT(bit < 32); - return Inst(Opcode::ReplicateBit32, a, Imm8(bit)); - } - - ASSERT(bit < 64); - return Inst(Opcode::ReplicateBit64, a, Imm8(bit)); -} - -U32U64 IREmitter::MaxSigned(const U32U64& a, const U32U64& b) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::MaxSigned32, a, b); - } - - return Inst(Opcode::MaxSigned64, a, b); -} - -U32U64 IREmitter::MaxUnsigned(const U32U64& a, const U32U64& b) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::MaxUnsigned32, a, b); - } - - return Inst(Opcode::MaxUnsigned64, a, b); -} - -U32U64 IREmitter::MinSigned(const U32U64& a, const U32U64& b) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::MinSigned32, a, b); - } - - return Inst(Opcode::MinSigned64, a, b); -} - -U32U64 IREmitter::MinUnsigned(const U32U64& a, const U32U64& b) { - if (a.GetType() == IR::Type::U32) { - return Inst(Opcode::MinUnsigned32, a, b); - } - - return Inst(Opcode::MinUnsigned64, a, b); -} - -ResultAndOverflow IREmitter::SignedSaturatedAddWithFlag(const U32& a, const U32& b) { - const auto result = Inst(Opcode::SignedSaturatedAddWithFlag32, a, b); - const auto overflow = Inst(Opcode::GetOverflowFromOp, result); - return {result, overflow}; -} - -ResultAndOverflow IREmitter::SignedSaturatedSubWithFlag(const U32& a, const U32& b) { - const auto result = Inst(Opcode::SignedSaturatedSubWithFlag32, a, b); - const auto overflow = Inst(Opcode::GetOverflowFromOp, result); - return {result, overflow}; -} - -ResultAndOverflow 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(Opcode::SignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); - const auto overflow = Inst(Opcode::GetOverflowFromOp, result); - return {result, overflow}; -} - -ResultAndOverflow IREmitter::UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to) { - ASSERT(bit_size_to_saturate_to <= 31); - const auto result = Inst(Opcode::UnsignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); - const auto overflow = Inst(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(Opcode::SignedSaturatedAdd8, a, b); - case IR::Type::U16: - return Inst(Opcode::SignedSaturatedAdd16, a, b); - case IR::Type::U32: - return Inst(Opcode::SignedSaturatedAdd32, a, b); - case IR::Type::U64: - return Inst(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(Opcode::SignedSaturatedDoublingMultiplyReturnHigh16, a, b); - case IR::Type::U32: - return Inst(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(Opcode::SignedSaturatedSub8, a, b); - case IR::Type::U16: - return Inst(Opcode::SignedSaturatedSub16, a, b); - case IR::Type::U32: - return Inst(Opcode::SignedSaturatedSub32, a, b); - case IR::Type::U64: - return Inst(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(Opcode::UnsignedSaturatedAdd8, a, b); - case IR::Type::U16: - return Inst(Opcode::UnsignedSaturatedAdd16, a, b); - case IR::Type::U32: - return Inst(Opcode::UnsignedSaturatedAdd32, a, b); - case IR::Type::U64: - return Inst(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(Opcode::UnsignedSaturatedSub8, a, b); - case IR::Type::U16: - return Inst(Opcode::UnsignedSaturatedSub16, a, b); - case IR::Type::U32: - return Inst(Opcode::UnsignedSaturatedSub32, a, b); - case IR::Type::U64: - return Inst(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(Opcode::VectorSignedSaturatedAdd8, a, b); - case 16: - return Inst(Opcode::VectorSignedSaturatedAdd16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedAdd32, a, b); - case 64: - return Inst(Opcode::VectorSignedSaturatedAdd64, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorSignedSaturatedSub(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedSaturatedSub8, a, b); - case 16: - return Inst(Opcode::VectorSignedSaturatedSub16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedSub32, a, b); - case 64: - return Inst(Opcode::VectorSignedSaturatedSub64, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorUnsignedSaturatedAdd(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorUnsignedSaturatedAdd8, a, b); - case 16: - return Inst(Opcode::VectorUnsignedSaturatedAdd16, a, b); - case 32: - return Inst(Opcode::VectorUnsignedSaturatedAdd32, a, b); - case 64: - return Inst(Opcode::VectorUnsignedSaturatedAdd64, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorUnsignedSaturatedSub(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorUnsignedSaturatedSub8, a, b); - case 16: - return Inst(Opcode::VectorUnsignedSaturatedSub16, a, b); - case 32: - return Inst(Opcode::VectorUnsignedSaturatedSub32, a, b); - case 64: - return Inst(Opcode::VectorUnsignedSaturatedSub64, a, b); - default: - UNREACHABLE(); - } -} - -ResultAndGE IREmitter::PackedAddU8(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddU8, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedAddS8(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddS8, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedAddU16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddU16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedAddS16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddS16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubU8(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubU8, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubS8(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubS8, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubU16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubU16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubS16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubS16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedAddSubU16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddSubU16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedAddSubS16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedAddSubS16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubAddU16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubAddU16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -ResultAndGE IREmitter::PackedSubAddS16(const U32& a, const U32& b) { - const auto result = Inst(Opcode::PackedSubAddS16, a, b); - const auto ge = Inst(Opcode::GetGEFromOp, result); - return {result, ge}; -} - -U32 IREmitter::PackedHalvingAddU8(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddU8, a, b); -} - -U32 IREmitter::PackedHalvingAddS8(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddS8, a, b); -} - -U32 IREmitter::PackedHalvingSubU8(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubU8, a, b); -} - -U32 IREmitter::PackedHalvingSubS8(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubS8, a, b); -} - -U32 IREmitter::PackedHalvingAddU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddU16, a, b); -} - -U32 IREmitter::PackedHalvingAddS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddS16, a, b); -} - -U32 IREmitter::PackedHalvingSubU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubU16, a, b); -} - -U32 IREmitter::PackedHalvingSubS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubS16, a, b); -} - -U32 IREmitter::PackedHalvingAddSubU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddSubU16, a, b); -} - -U32 IREmitter::PackedHalvingAddSubS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingAddSubS16, a, b); -} - -U32 IREmitter::PackedHalvingSubAddU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubAddU16, a, b); -} - -U32 IREmitter::PackedHalvingSubAddS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedHalvingSubAddS16, a, b); -} - -U32 IREmitter::PackedSaturatedAddU8(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedAddU8, a, b); -} - -U32 IREmitter::PackedSaturatedAddS8(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedAddS8, a, b); -} - -U32 IREmitter::PackedSaturatedSubU8(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedSubU8, a, b); -} - -U32 IREmitter::PackedSaturatedSubS8(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedSubS8, a, b); -} - -U32 IREmitter::PackedSaturatedAddU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedAddU16, a, b); -} - -U32 IREmitter::PackedSaturatedAddS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedAddS16, a, b); -} - -U32 IREmitter::PackedSaturatedSubU16(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedSubU16, a, b); -} - -U32 IREmitter::PackedSaturatedSubS16(const U32& a, const U32& b) { - return Inst(Opcode::PackedSaturatedSubS16, a, b); -} - -U32 IREmitter::PackedAbsDiffSumU8(const U32& a, const U32& b) { - return Inst(Opcode::PackedAbsDiffSumU8, a, b); -} - -U32 IREmitter::PackedSelect(const U32& ge, const U32& a, const U32& b) { - return Inst(Opcode::PackedSelect, ge, a, b); -} - -U32 IREmitter::CRC32Castagnoli8(const U32& a, const U32& b) { - return Inst(Opcode::CRC32Castagnoli8, a, b); -} - -U32 IREmitter::CRC32Castagnoli16(const U32& a, const U32& b) { - return Inst(Opcode::CRC32Castagnoli16, a, b); -} - -U32 IREmitter::CRC32Castagnoli32(const U32& a, const U32& b) { - return Inst(Opcode::CRC32Castagnoli32, a, b); -} - -U32 IREmitter::CRC32Castagnoli64(const U32& a, const U64& b) { - return Inst(Opcode::CRC32Castagnoli64, a, b); -} - -U32 IREmitter::CRC32ISO8(const U32& a, const U32& b) { - return Inst(Opcode::CRC32ISO8, a, b); -} - -U32 IREmitter::CRC32ISO16(const U32& a, const U32& b) { - return Inst(Opcode::CRC32ISO16, a, b); -} - -U32 IREmitter::CRC32ISO32(const U32& a, const U32& b) { - return Inst(Opcode::CRC32ISO32, a, b); -} - -U32 IREmitter::CRC32ISO64(const U32& a, const U64& b) { - return Inst(Opcode::CRC32ISO64, a, b); -} - -U128 IREmitter::AESDecryptSingleRound(const U128& a) { - return Inst(Opcode::AESDecryptSingleRound, a); -} - -U128 IREmitter::AESEncryptSingleRound(const U128& a) { - return Inst(Opcode::AESEncryptSingleRound, a); -} - -U128 IREmitter::AESInverseMixColumns(const U128& a) { - return Inst(Opcode::AESInverseMixColumns, a); -} - -U128 IREmitter::AESMixColumns(const U128& a) { - return Inst(Opcode::AESMixColumns, a); -} - -U8 IREmitter::SM4AccessSubstitutionBox(const U8& a) { - return Inst(Opcode::SM4AccessSubstitutionBox, a); -} - -U128 IREmitter::SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1) { - return Inst(Opcode::SHA256Hash, x, y, w, Imm1(part1)); -} - -U128 IREmitter::SHA256MessageSchedule0(const U128& x, const U128& y) { - return Inst(Opcode::SHA256MessageSchedule0, x, y); -} - -U128 IREmitter::SHA256MessageSchedule1(const U128& x, const U128& y, const U128& z) { - return Inst(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(Opcode::VectorGetElement8, a, Imm8(static_cast(index))); - case 16: - return Inst(Opcode::VectorGetElement16, a, Imm8(static_cast(index))); - case 32: - return Inst(Opcode::VectorGetElement32, a, Imm8(static_cast(index))); - case 64: - return Inst(Opcode::VectorGetElement64, a, Imm8(static_cast(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(Opcode::VectorSetElement8, a, Imm8(static_cast(index)), elem); - case 16: - return Inst(Opcode::VectorSetElement16, a, Imm8(static_cast(index)), elem); - case 32: - return Inst(Opcode::VectorSetElement32, a, Imm8(static_cast(index)), elem); - case 64: - return Inst(Opcode::VectorSetElement64, a, Imm8(static_cast(index)), elem); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorAbs(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorAbs8, a); - case 16: - return Inst(Opcode::VectorAbs16, a); - case 32: - return Inst(Opcode::VectorAbs32, a); - case 64: - return Inst(Opcode::VectorAbs64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorAdd(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorAdd8, a, b); - case 16: - return Inst(Opcode::VectorAdd16, a, b); - case 32: - return Inst(Opcode::VectorAdd32, a, b); - case 64: - return Inst(Opcode::VectorAdd64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorAnd(const U128& a, const U128& b) { - return Inst(Opcode::VectorAnd, a, b); -} - -U128 IREmitter::VectorAndNot(const U128& a, const U128& b) { - return Inst(Opcode::VectorAndNot, a, b); -} - -U128 IREmitter::VectorArithmeticShiftRight(size_t esize, const U128& a, u8 shift_amount) { - switch (esize) { - case 8: - return Inst(Opcode::VectorArithmeticShiftRight8, a, Imm8(shift_amount)); - case 16: - return Inst(Opcode::VectorArithmeticShiftRight16, a, Imm8(shift_amount)); - case 32: - return Inst(Opcode::VectorArithmeticShiftRight32, a, Imm8(shift_amount)); - case 64: - return Inst(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(Opcode::VectorArithmeticVShift8, a, b); - case 16: - return Inst(Opcode::VectorArithmeticVShift16, a, b); - case 32: - return Inst(Opcode::VectorArithmeticVShift32, a, b); - case 64: - return Inst(Opcode::VectorArithmeticVShift64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorBroadcastLower(size_t esize, const UAny& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorBroadcastLower8, U8(a)); - case 16: - return Inst(Opcode::VectorBroadcastLower16, U16(a)); - case 32: - return Inst(Opcode::VectorBroadcastLower32, U32(a)); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorBroadcast(size_t esize, const UAny& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorBroadcast8, U8(a)); - case 16: - return Inst(Opcode::VectorBroadcast16, U16(a)); - case 32: - return Inst(Opcode::VectorBroadcast32, U32(a)); - case 64: - return Inst(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(Opcode::VectorBroadcastElementLower8, a, u8(index)); - case 16: - return Inst(Opcode::VectorBroadcastElementLower16, a, u8(index)); - case 32: - return Inst(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(Opcode::VectorBroadcastElement8, a, u8(index)); - case 16: - return Inst(Opcode::VectorBroadcastElement16, a, u8(index)); - case 32: - return Inst(Opcode::VectorBroadcastElement32, a, u8(index)); - case 64: - return Inst(Opcode::VectorBroadcastElement64, a, u8(index)); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorCountLeadingZeros(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorCountLeadingZeros8, a); - case 16: - return Inst(Opcode::VectorCountLeadingZeros16, a); - case 32: - return Inst(Opcode::VectorCountLeadingZeros32, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorDeinterleaveEven(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorDeinterleaveEven8, a, b); - case 16: - return Inst(Opcode::VectorDeinterleaveEven16, a, b); - case 32: - return Inst(Opcode::VectorDeinterleaveEven32, a, b); - case 64: - return Inst(Opcode::VectorDeinterleaveEven64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorDeinterleaveOdd(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorDeinterleaveOdd8, a, b); - case 16: - return Inst(Opcode::VectorDeinterleaveOdd16, a, b); - case 32: - return Inst(Opcode::VectorDeinterleaveOdd32, a, b); - case 64: - return Inst(Opcode::VectorDeinterleaveOdd64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorDeinterleaveEvenLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorDeinterleaveEvenLower8, a, b); - case 16: - return Inst(Opcode::VectorDeinterleaveEvenLower16, a, b); - case 32: - return Inst(Opcode::VectorDeinterleaveEvenLower32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorDeinterleaveOddLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorDeinterleaveOddLower8, a, b); - case 16: - return Inst(Opcode::VectorDeinterleaveOddLower16, a, b); - case 32: - return Inst(Opcode::VectorDeinterleaveOddLower32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorEor(const U128& a, const U128& b) { - return Inst(Opcode::VectorEor, a, b); -} - -U128 IREmitter::VectorEqual(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorEqual8, a, b); - case 16: - return Inst(Opcode::VectorEqual16, a, b); - case 32: - return Inst(Opcode::VectorEqual32, a, b); - case 64: - return Inst(Opcode::VectorEqual64, a, b); - case 128: - return Inst(Opcode::VectorEqual128, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorExtract(const U128& a, const U128& b, size_t position) { - ASSERT(position <= 128); - return Inst(Opcode::VectorExtract, a, b, Imm8(static_cast(position))); -} - -U128 IREmitter::VectorExtractLower(const U128& a, const U128& b, size_t position) { - ASSERT(position <= 64); - return Inst(Opcode::VectorExtractLower, a, b, Imm8(static_cast(position))); -} - -U128 IREmitter::VectorGreaterSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorGreaterS8, a, b); - case 16: - return Inst(Opcode::VectorGreaterS16, a, b); - case 32: - return Inst(Opcode::VectorGreaterS32, a, b); - case 64: - return Inst(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(Opcode::VectorHalvingAddS8, a, b); - case 16: - return Inst(Opcode::VectorHalvingAddS16, a, b); - case 32: - return Inst(Opcode::VectorHalvingAddS32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorHalvingAddU8, a, b); - case 16: - return Inst(Opcode::VectorHalvingAddU16, a, b); - case 32: - return Inst(Opcode::VectorHalvingAddU32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorHalvingSubSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorHalvingSubS8, a, b); - case 16: - return Inst(Opcode::VectorHalvingSubS16, a, b); - case 32: - return Inst(Opcode::VectorHalvingSubS32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorHalvingSubUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorHalvingSubU8, a, b); - case 16: - return Inst(Opcode::VectorHalvingSubU16, a, b); - case 32: - return Inst(Opcode::VectorHalvingSubU32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorInterleaveLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorInterleaveLower8, a, b); - case 16: - return Inst(Opcode::VectorInterleaveLower16, a, b); - case 32: - return Inst(Opcode::VectorInterleaveLower32, a, b); - case 64: - return Inst(Opcode::VectorInterleaveLower64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorInterleaveUpper(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorInterleaveUpper8, a, b); - case 16: - return Inst(Opcode::VectorInterleaveUpper16, a, b); - case 32: - return Inst(Opcode::VectorInterleaveUpper32, a, b); - case 64: - return Inst(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(Opcode::VectorLogicalShiftLeft8, a, Imm8(shift_amount)); - case 16: - return Inst(Opcode::VectorLogicalShiftLeft16, a, Imm8(shift_amount)); - case 32: - return Inst(Opcode::VectorLogicalShiftLeft32, a, Imm8(shift_amount)); - case 64: - return Inst(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(Opcode::VectorLogicalShiftRight8, a, Imm8(shift_amount)); - case 16: - return Inst(Opcode::VectorLogicalShiftRight16, a, Imm8(shift_amount)); - case 32: - return Inst(Opcode::VectorLogicalShiftRight32, a, Imm8(shift_amount)); - case 64: - return Inst(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(Opcode::VectorLogicalVShift8, a, b); - case 16: - return Inst(Opcode::VectorLogicalVShift16, a, b); - case 32: - return Inst(Opcode::VectorLogicalVShift32, a, b); - case 64: - return Inst(Opcode::VectorLogicalVShift64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMaxSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMaxS8, a, b); - case 16: - return Inst(Opcode::VectorMaxS16, a, b); - case 32: - return Inst(Opcode::VectorMaxS32, a, b); - case 64: - return Inst(Opcode::VectorMaxS64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMaxUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMaxU8, a, b); - case 16: - return Inst(Opcode::VectorMaxU16, a, b); - case 32: - return Inst(Opcode::VectorMaxU32, a, b); - case 64: - return Inst(Opcode::VectorMaxU64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMinSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMinS8, a, b); - case 16: - return Inst(Opcode::VectorMinS16, a, b); - case 32: - return Inst(Opcode::VectorMinS32, a, b); - case 64: - return Inst(Opcode::VectorMinS64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMinUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMinU8, a, b); - case 16: - return Inst(Opcode::VectorMinU16, a, b); - case 32: - return Inst(Opcode::VectorMinU32, a, b); - case 64: - return Inst(Opcode::VectorMinU64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMultiply(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMultiply8, a, b); - case 16: - return Inst(Opcode::VectorMultiply16, a, b); - case 32: - return Inst(Opcode::VectorMultiply32, a, b); - case 64: - return Inst(Opcode::VectorMultiply64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMultiplySignedWiden(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMultiplySignedWiden8, a, b); - case 16: - return Inst(Opcode::VectorMultiplySignedWiden16, a, b); - case 32: - return Inst(Opcode::VectorMultiplySignedWiden32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorMultiplyUnsignedWiden(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorMultiplyUnsignedWiden8, a, b); - case 16: - return Inst(Opcode::VectorMultiplyUnsignedWiden16, a, b); - case 32: - return Inst(Opcode::VectorMultiplyUnsignedWiden32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorNarrow(size_t original_esize, const U128& a) { - switch (original_esize) { - case 16: - return Inst(Opcode::VectorNarrow16, a); - case 32: - return Inst(Opcode::VectorNarrow32, a); - case 64: - return Inst(Opcode::VectorNarrow64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorNot(const U128& a) { - return Inst(Opcode::VectorNot, a); -} - -U128 IREmitter::VectorOr(const U128& a, const U128& b) { - return Inst(Opcode::VectorOr, a, b); -} - -U128 IREmitter::VectorPairedAdd(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedAdd8, a, b); - case 16: - return Inst(Opcode::VectorPairedAdd16, a, b); - case 32: - return Inst(Opcode::VectorPairedAdd32, a, b); - case 64: - return Inst(Opcode::VectorPairedAdd64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorPairedAddLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedAddLower8, a, b); - case 16: - return Inst(Opcode::VectorPairedAddLower16, a, b); - case 32: - return Inst(Opcode::VectorPairedAddLower32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorPairedAddSignedWiden(size_t original_esize, const U128& a) { - switch (original_esize) { - case 8: - return Inst(Opcode::VectorPairedAddSignedWiden8, a); - case 16: - return Inst(Opcode::VectorPairedAddSignedWiden16, a); - case 32: - return Inst(Opcode::VectorPairedAddSignedWiden32, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorPairedAddUnsignedWiden(size_t original_esize, const U128& a) { - switch (original_esize) { - case 8: - return Inst(Opcode::VectorPairedAddUnsignedWiden8, a); - case 16: - return Inst(Opcode::VectorPairedAddUnsignedWiden16, a); - case 32: - return Inst(Opcode::VectorPairedAddUnsignedWiden32, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorPairedMaxSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMaxS8, a, b); - case 16: - return Inst(Opcode::VectorPairedMaxS16, a, b); - case 32: - return Inst(Opcode::VectorPairedMaxS32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMaxUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMaxU8, a, b); - case 16: - return Inst(Opcode::VectorPairedMaxU16, a, b); - case 32: - return Inst(Opcode::VectorPairedMaxU32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMinSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMinS8, a, b); - case 16: - return Inst(Opcode::VectorPairedMinS16, a, b); - case 32: - return Inst(Opcode::VectorPairedMinS32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMinUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMinU8, a, b); - case 16: - return Inst(Opcode::VectorPairedMinU16, a, b); - case 32: - return Inst(Opcode::VectorPairedMinU32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMaxSignedLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMaxLowerS8, a, b); - case 16: - return Inst(Opcode::VectorPairedMaxLowerS16, a, b); - case 32: - return Inst(Opcode::VectorPairedMaxLowerS32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMaxUnsignedLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMaxLowerU8, a, b); - case 16: - return Inst(Opcode::VectorPairedMaxLowerU16, a, b); - case 32: - return Inst(Opcode::VectorPairedMaxLowerU32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMinSignedLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMinLowerS8, a, b); - case 16: - return Inst(Opcode::VectorPairedMinLowerS16, a, b); - case 32: - return Inst(Opcode::VectorPairedMinLowerS32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPairedMinUnsignedLower(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPairedMinLowerU8, a, b); - case 16: - return Inst(Opcode::VectorPairedMinLowerU16, a, b); - case 32: - return Inst(Opcode::VectorPairedMinLowerU32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPolynomialMultiply(const U128& a, const U128& b) { - return Inst(Opcode::VectorPolynomialMultiply8, a, b); -} - -U128 IREmitter::VectorPolynomialMultiplyLong(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorPolynomialMultiplyLong8, a, b); - case 64: - return Inst(Opcode::VectorPolynomialMultiplyLong64, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorPopulationCount(const U128& a) { - return Inst(Opcode::VectorPopulationCount, a); -} - -U128 IREmitter::VectorReverseBits(const U128& a) { - return Inst(Opcode::VectorReverseBits, a); -} - -U128 IREmitter::VectorReverseElementsInHalfGroups(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorReverseElementsInHalfGroups8, a); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorReverseElementsInWordGroups(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorReverseElementsInWordGroups8, a); - case 16: - return Inst(Opcode::VectorReverseElementsInWordGroups16, a); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorReverseElementsInLongGroups(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorReverseElementsInLongGroups8, a); - case 16: - return Inst(Opcode::VectorReverseElementsInLongGroups16, a); - case 32: - return Inst(Opcode::VectorReverseElementsInLongGroups32, a); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorReduceAdd(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorReduceAdd8, a); - case 16: - return Inst(Opcode::VectorReduceAdd16, a); - case 32: - return Inst(Opcode::VectorReduceAdd32, a); - case 64: - return Inst(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(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(esize - amount))); -} - -U128 IREmitter::VectorRotateWholeVectorRight(const U128& a, u8 amount) { - ASSERT(amount % 32 == 0); - return Inst(Opcode::VectorRotateWholeVectorRight, a, Imm8(amount)); -} - -U128 IREmitter::VectorRoundingHalvingAddSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorRoundingHalvingAddS8, a, b); - case 16: - return Inst(Opcode::VectorRoundingHalvingAddS16, a, b); - case 32: - return Inst(Opcode::VectorRoundingHalvingAddS32, a, b); - } - - UNREACHABLE(); -} - -U128 IREmitter::VectorRoundingHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorRoundingHalvingAddU8, a, b); - case 16: - return Inst(Opcode::VectorRoundingHalvingAddU16, a, b); - case 32: - return Inst(Opcode::VectorRoundingHalvingAddU32, a, b); - } - - UNREACHABLE(); -} - -U128 IREmitter::VectorRoundingShiftLeftSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorRoundingShiftLeftS8, a, b); - case 16: - return Inst(Opcode::VectorRoundingShiftLeftS16, a, b); - case 32: - return Inst(Opcode::VectorRoundingShiftLeftS32, a, b); - case 64: - return Inst(Opcode::VectorRoundingShiftLeftS64, a, b); - } - - UNREACHABLE(); -} - -U128 IREmitter::VectorRoundingShiftLeftUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorRoundingShiftLeftU8, a, b); - case 16: - return Inst(Opcode::VectorRoundingShiftLeftU16, a, b); - case 32: - return Inst(Opcode::VectorRoundingShiftLeftU32, a, b); - case 64: - return Inst(Opcode::VectorRoundingShiftLeftU64, a, b); - } - - UNREACHABLE(); -} - -U128 IREmitter::VectorSignExtend(size_t original_esize, const U128& a) { - switch (original_esize) { - case 8: - return Inst(Opcode::VectorSignExtend8, a); - case 16: - return Inst(Opcode::VectorSignExtend16, a); - case 32: - return Inst(Opcode::VectorSignExtend32, a); - case 64: - return Inst(Opcode::VectorSignExtend64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedAbsoluteDifference8, a, b); - case 16: - return Inst(Opcode::VectorSignedAbsoluteDifference16, a, b); - case 32: - return Inst(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(Opcode::GetUpperFromOp, multiply), - Inst(Opcode::GetLowerFromOp, multiply), - }; -} - -U128 IREmitter::VectorSignedSaturatedAbs(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedSaturatedAbs8, a); - case 16: - return Inst(Opcode::VectorSignedSaturatedAbs16, a); - case 32: - return Inst(Opcode::VectorSignedSaturatedAbs32, a); - case 64: - return Inst(Opcode::VectorSignedSaturatedAbs64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedAccumulateUnsigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned8, a, b); - case 16: - return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned32, a, b); - case 64: - return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedDoublingMultiplyHigh(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 16: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHigh16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHigh32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorSignedSaturatedDoublingMultiplyHighRounding(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 16: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding32, a, b); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::VectorSignedSaturatedDoublingMultiplyLong(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 16: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyLong16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyLong32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a) { - switch (original_esize) { - case 16: - return Inst(Opcode::VectorSignedSaturatedNarrowToSigned16, a); - case 32: - return Inst(Opcode::VectorSignedSaturatedNarrowToSigned32, a); - case 64: - return Inst(Opcode::VectorSignedSaturatedNarrowToSigned64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a) { - switch (original_esize) { - case 16: - return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned16, a); - case 32: - return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned32, a); - case 64: - return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedNeg(size_t esize, const U128& a) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedSaturatedNeg8, a); - case 16: - return Inst(Opcode::VectorSignedSaturatedNeg16, a); - case 32: - return Inst(Opcode::VectorSignedSaturatedNeg32, a); - case 64: - return Inst(Opcode::VectorSignedSaturatedNeg64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorSignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorSignedSaturatedShiftLeft8, a, b); - case 16: - return Inst(Opcode::VectorSignedSaturatedShiftLeft16, a, b); - case 32: - return Inst(Opcode::VectorSignedSaturatedShiftLeft32, a, b); - case 64: - return Inst(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(Opcode::VectorSignedSaturatedShiftLeftUnsigned8, a, Imm8(shift_amount)); - case 16: - return Inst(Opcode::VectorSignedSaturatedShiftLeftUnsigned16, a, Imm8(shift_amount)); - case 32: - return Inst(Opcode::VectorSignedSaturatedShiftLeftUnsigned32, a, Imm8(shift_amount)); - case 64: - return Inst(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(Opcode::VectorSub8, a, b); - case 16: - return Inst(Opcode::VectorSub16, a, b); - case 32: - return Inst(Opcode::VectorSub32, a, b); - case 64: - return Inst(Opcode::VectorSub64, a, b); - } - UNREACHABLE(); -} - -Table IREmitter::VectorTable(std::vector values) { - ASSERT(values.size() >= 1 && values.size() <= 4); - values.resize(4); - return Inst(Opcode::VectorTable, values[0], values[1], values[2], values[3]); -} - -Table IREmitter::VectorTable(std::vector values) { - ASSERT(values.size() >= 1 && values.size() <= 4); - values.resize(4); - return Inst
(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(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(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(Opcode::VectorTranspose8, a, b, Imm1(part)); - case 16: - return Inst(Opcode::VectorTranspose16, a, b, Imm1(part)); - case 32: - return Inst(Opcode::VectorTranspose32, a, b, Imm1(part)); - case 64: - return Inst(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(Opcode::VectorUnsignedAbsoluteDifference8, a, b); - case 16: - return Inst(Opcode::VectorUnsignedAbsoluteDifference16, a, b); - case 32: - return Inst(Opcode::VectorUnsignedAbsoluteDifference32, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorUnsignedRecipEstimate(const U128& a) { - return Inst(Opcode::VectorUnsignedRecipEstimate, a); -} - -U128 IREmitter::VectorUnsignedRecipSqrtEstimate(const U128& a) { - return Inst(Opcode::VectorUnsignedRecipSqrtEstimate, a); -} - -U128 IREmitter::VectorUnsignedSaturatedAccumulateSigned(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned8, a, b); - case 16: - return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned16, a, b); - case 32: - return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned32, a, b); - case 64: - return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorUnsignedSaturatedNarrow(size_t esize, const U128& a) { - switch (esize) { - case 16: - return Inst(Opcode::VectorUnsignedSaturatedNarrow16, a); - case 32: - return Inst(Opcode::VectorUnsignedSaturatedNarrow32, a); - case 64: - return Inst(Opcode::VectorUnsignedSaturatedNarrow64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorUnsignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) { - switch (esize) { - case 8: - return Inst(Opcode::VectorUnsignedSaturatedShiftLeft8, a, b); - case 16: - return Inst(Opcode::VectorUnsignedSaturatedShiftLeft16, a, b); - case 32: - return Inst(Opcode::VectorUnsignedSaturatedShiftLeft32, a, b); - case 64: - return Inst(Opcode::VectorUnsignedSaturatedShiftLeft64, a, b); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorZeroExtend(size_t original_esize, const U128& a) { - switch (original_esize) { - case 8: - return Inst(Opcode::VectorZeroExtend8, a); - case 16: - return Inst(Opcode::VectorZeroExtend16, a); - case 32: - return Inst(Opcode::VectorZeroExtend32, a); - case 64: - return Inst(Opcode::VectorZeroExtend64, a); - } - UNREACHABLE(); -} - -U128 IREmitter::VectorZeroUpper(const U128& a) { - return Inst(Opcode::VectorZeroUpper, a); -} - -U128 IREmitter::ZeroVector() { - return Inst(Opcode::ZeroVector); -} - -U16U32U64 IREmitter::FPAbs(const U16U32U64& a) { - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPAbs16, a); - case Type::U32: - return Inst(Opcode::FPAbs32, a); - case Type::U64: - return Inst(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(Opcode::FPAdd32, a, b); - case Type::U64: - return Inst(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(Opcode::FPCompare32, a, b, exc_on_qnan_imm); - case Type::U64: - return Inst(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(Opcode::FPDiv32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMax32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMaxNumeric32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMin32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMinNumeric32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMul32, a, b); - case Type::U64: - return Inst(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(Opcode::FPMulAdd16, a, b, c); - case Type::U32: - return Inst(Opcode::FPMulAdd32, a, b, c); - case Type::U64: - return Inst(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(Opcode::FPMulSub16, a, b, c); - case Type::U32: - return Inst(Opcode::FPMulSub32, a, b, c); - case Type::U64: - return Inst(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(Opcode::FPMulX32, a, b); - case Type::U64: - return Inst(Opcode::FPMulX64, a, b); - default: - UNREACHABLE(); - } -} - -U16U32U64 IREmitter::FPNeg(const U16U32U64& a) { - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPNeg16, a); - case Type::U32: - return Inst(Opcode::FPNeg32, a); - case Type::U64: - return Inst(Opcode::FPNeg64, a); - default: - UNREACHABLE(); - } -} - -U16U32U64 IREmitter::FPRecipEstimate(const U16U32U64& a) { - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPRecipEstimate16, a); - case Type::U32: - return Inst(Opcode::FPRecipEstimate32, a); - case Type::U64: - return Inst(Opcode::FPRecipEstimate64, a); - default: - UNREACHABLE(); - } -} - -U16U32U64 IREmitter::FPRecipExponent(const U16U32U64& a) { - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPRecipExponent16, a); - case Type::U32: - return Inst(Opcode::FPRecipExponent32, a); - case Type::U64: - return Inst(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(Opcode::FPRecipStepFused16, a, b); - case Type::U32: - return Inst(Opcode::FPRecipStepFused32, a, b); - case Type::U64: - return Inst(Opcode::FPRecipStepFused64, a, b); - default: - UNREACHABLE(); - } -} - -U16U32U64 IREmitter::FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact) { - const u8 rounding_value = static_cast(rounding); - const IR::U1 exact_imm = Imm1(exact); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPRoundInt16, a, rounding_value, exact_imm); - case Type::U32: - return Inst(Opcode::FPRoundInt32, a, rounding_value, exact_imm); - case Type::U64: - return Inst(Opcode::FPRoundInt64, a, rounding_value, exact_imm); - default: - UNREACHABLE(); - } -} - -U16U32U64 IREmitter::FPRSqrtEstimate(const U16U32U64& a) { - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPRSqrtEstimate16, a); - case Type::U32: - return Inst(Opcode::FPRSqrtEstimate32, a); - case Type::U64: - return Inst(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(Opcode::FPRSqrtStepFused16, a, b); - case Type::U32: - return Inst(Opcode::FPRSqrtStepFused32, a, b); - case Type::U64: - return Inst(Opcode::FPRSqrtStepFused64, a, b); - default: - UNREACHABLE(); - } -} - -U32U64 IREmitter::FPSqrt(const U32U64& a) { - switch (a.GetType()) { - case Type::U32: - return Inst(Opcode::FPSqrt32, a); - case Type::U64: - return Inst(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(Opcode::FPSub32, a, b); - case Type::U64: - return Inst(Opcode::FPSub64, a, b); - default: - UNREACHABLE(); - } -} - -U16 IREmitter::FPDoubleToHalf(const U64& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPDoubleToHalf, a, Imm8(static_cast(rounding))); -} - -U32 IREmitter::FPDoubleToSingle(const U64& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPDoubleToSingle, a, Imm8(static_cast(rounding))); -} - -U64 IREmitter::FPHalfToDouble(const U16& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPHalfToDouble, a, Imm8(static_cast(rounding))); -} - -U32 IREmitter::FPHalfToSingle(const U16& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPHalfToSingle, a, Imm8(static_cast(rounding))); -} - -U64 IREmitter::FPSingleToDouble(const U32& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPSingleToDouble, a, Imm8(static_cast(rounding))); -} - -U16 IREmitter::FPSingleToHalf(const U32& a, FP::RoundingMode rounding) { - return Inst(Opcode::FPSingleToHalf, a, Imm8(static_cast(rounding))); -} - -U16 IREmitter::FPToFixedS16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) { - ASSERT(fbits <= 16); - - const U8 fbits_imm = Imm8(static_cast(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedS16, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedS16, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedS32, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedS32, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedS64, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedS64, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedU16, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedU16, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedU32, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedU32, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPHalfToFixedU64, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPSingleToFixedU64, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const IR::U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPFixedS16ToSingle, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPFixedS32ToSingle, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const IR::U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPFixedU16ToSingle, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPFixedU32ToSingle, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const IR::U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPFixedS16ToDouble, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPFixedS32ToDouble, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(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(fbits)); - const IR::U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (a.GetType()) { - case Type::U16: - return Inst(Opcode::FPFixedU16ToDouble, a, fbits_imm, rounding_imm); - case Type::U32: - return Inst(Opcode::FPFixedU32ToDouble, a, fbits_imm, rounding_imm); - case Type::U64: - return Inst(Opcode::FPFixedU64ToDouble, a, fbits_imm, rounding_imm); - default: - UNREACHABLE(); - } -} - -U128 IREmitter::FPVectorAbs(size_t esize, const U128& a) { - switch (esize) { - case 16: - return Inst(Opcode::FPVectorAbs16, a); - case 32: - return Inst(Opcode::FPVectorAbs32, a); - case 64: - return Inst(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(Opcode::FPVectorAdd32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorDiv32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorEqual16, a, b, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorEqual32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorFromHalf32, a, Imm8(static_cast(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(Opcode::FPVectorFromSignedFixed32, a, Imm8(static_cast(fbits)), Imm8(static_cast(rounding)), Imm1(fpcr_controlled)); - case 64: - return Inst(Opcode::FPVectorFromSignedFixed64, a, Imm8(static_cast(fbits)), Imm8(static_cast(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(Opcode::FPVectorFromUnsignedFixed32, a, Imm8(static_cast(fbits)), Imm8(static_cast(rounding)), Imm1(fpcr_controlled)); - case 64: - return Inst(Opcode::FPVectorFromUnsignedFixed64, a, Imm8(static_cast(fbits)), Imm8(static_cast(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(Opcode::FPVectorGreater32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorGreaterEqual32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMax32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMaxNumeric32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMin32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMinNumeric32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMul32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMulAdd16, a, b, c, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorMulAdd32, a, b, c, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorMulX32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(Opcode::FPVectorMulX64, a, b, Imm1(fpcr_controlled)); - } - UNREACHABLE(); -} - -U128 IREmitter::FPVectorNeg(size_t esize, const U128& a) { - switch (esize) { - case 16: - return Inst(Opcode::FPVectorNeg16, a); - case 32: - return Inst(Opcode::FPVectorNeg32, a); - case 64: - return Inst(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(Opcode::FPVectorPairedAdd32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorPairedAddLower32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorRecipEstimate16, a, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorRecipEstimate32, a, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorRecipStepFused16, a, b, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorRecipStepFused32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(rounding)); - const IR::U1 exact_imm = Imm1(exact); - - switch (esize) { - case 16: - return Inst(Opcode::FPVectorRoundInt16, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorRoundInt32, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorRSqrtEstimate16, a, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorRSqrtEstimate32, a, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorRSqrtStepFused16, a, b, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorRSqrtStepFused32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorSqrt32, a, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorSub32, a, b, Imm1(fpcr_controlled)); - case 64: - return Inst(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(Opcode::FPVectorToHalf32, a, Imm8(static_cast(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (esize) { - case 16: - return Inst(Opcode::FPVectorToSignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorToSignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); - case 64: - return Inst(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(fbits)); - const U8 rounding_imm = Imm8(static_cast(rounding)); - - switch (esize) { - case 16: - return Inst(Opcode::FPVectorToUnsignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); - case 32: - return Inst(Opcode::FPVectorToUnsignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); - case 64: - return Inst(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(fn)), Value{}, Value{}, Value{}); -} - -void IREmitter::CallHostFunction(void (*fn)(u64), const U64& arg1) { - Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), arg1, Value{}, Value{}); -} - -void IREmitter::CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) { - Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(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(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 +#include +#include +#include +#include + +#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; + U1 Imm1(bool imm1) const { + return U1(Value(imm1)); + } - void PushRSB(const LocationDescriptor& return_location); + U8 Imm8(u8 imm8) const { + return U8(Value(imm8)); + } - 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 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); + U16 Imm16(u16 imm16) const { + return U16(Value(imm16)); + } - 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); + U32 Imm32(u32 imm32) const { + return U32(Value(imm32)); + } - ResultAndCarry LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in); - ResultAndCarry LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in); - ResultAndCarry ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in); - ResultAndCarry 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 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); + U64 Imm64(u64 imm64) const { + return U64(Value(imm64)); + } - ResultAndOverflow SignedSaturatedAddWithFlag(const U32& a, const U32& b); - ResultAndOverflow SignedSaturatedSubWithFlag(const U32& a, const U32& b); - ResultAndOverflow SignedSaturation(const U32& a, size_t bit_size_to_saturate_to); - ResultAndOverflow UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to); + void PushRSB(const LocationDescriptor& return_location) { + Inst(Opcode::PushRSB, IR::Value(return_location.Value())); + } - 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); + U64 Pack2x32To1x64(const U32& lo, const U32& hi) { + return Inst(Opcode::Pack2x32To1x64, lo, hi); + } - 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); + U128 Pack2x64To1x128(const U64& lo, const U64& hi) { + return Inst(Opcode::Pack2x64To1x128, lo, hi); + } - ResultAndGE PackedAddU8(const U32& a, const U32& b); - ResultAndGE PackedAddS8(const U32& a, const U32& b); - ResultAndGE PackedAddU16(const U32& a, const U32& b); - ResultAndGE PackedAddS16(const U32& a, const U32& b); - ResultAndGE PackedSubU8(const U32& a, const U32& b); - ResultAndGE PackedSubS8(const U32& a, const U32& b); - ResultAndGE PackedSubU16(const U32& a, const U32& b); - ResultAndGE PackedSubS16(const U32& a, const U32& b); - ResultAndGE PackedAddSubU16(const U32& a, const U32& b); - ResultAndGE PackedAddSubS16(const U32& a, const U32& b); - ResultAndGE PackedSubAddU16(const U32& a, const U32& b); - ResultAndGE 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); + 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 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); + U32 LeastSignificantWord(const U64& value) { + return Inst(Opcode::LeastSignificantWord, value); + } - U128 AESDecryptSingleRound(const U128& a); - U128 AESEncryptSingleRound(const U128& a); - U128 AESInverseMixColumns(const U128& a); - U128 AESMixColumns(const U128& a); + U16 LeastSignificantHalf(U32U64 value) { + if (value.GetType() == Type::U64) { + value = LeastSignificantWord(value); + } + return Inst(Opcode::LeastSignificantHalf, value); + } - U8 SM4AccessSubstitutionBox(const U8& a); + U8 LeastSignificantByte(U32U64 value) { + if (value.GetType() == Type::U64) { + value = LeastSignificantWord(value); + } + return Inst(Opcode::LeastSignificantByte, value); + } - 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); + ResultAndCarry MostSignificantWord(const U64& value) { + const auto result = Inst(Opcode::MostSignificantWord, value); + const auto carry_out = Inst(Opcode::GetCarryFromOp, result); + return {result, carry_out}; + } - 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 values); - Table VectorTable(std::vector 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(); + U1 MostSignificantBit(const U32& value) { + return Inst(Opcode::MostSignificantBit, value); + } - 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); + U1 IsZero(const U32& value) { + return Inst(Opcode::IsZero32, value); + } - 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); + U1 IsZero(const U64& value) { + return Inst(Opcode::IsZero64, value); + } - 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); + U1 IsZero(const U32U64& value) { + if (value.GetType() == Type::U32) { + return Inst(Opcode::IsZero32, value); + } else { + return Inst(Opcode::IsZero64, value); + } + } - void SetTerm(const Terminal& terminal); + U1 TestBit(const U32U64& value, const U8& bit) { + if (value.GetType() == Type::U32) { + return Inst(Opcode::TestBit, IndeterminateExtendToLong(value), bit); + } else { + return Inst(Opcode::TestBit, value, bit); + } + } + + U32 ConditionalSelect(Cond cond, const U32& a, const U32& b) { + return Inst(Opcode::ConditionalSelect32, Value{cond}, a, b); + } + + U64 ConditionalSelect(Cond cond, const U64& a, const U64& b) { + return Inst(Opcode::ConditionalSelect64, Value{cond}, a, b); + } + + NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b) { + return Inst(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(Opcode::ConditionalSelect32, Value{cond}, a, b); + } else { + return Inst(Opcode::ConditionalSelect64, Value{cond}, a, b); + } + } + + U1 GetCFlagFromNZCV(const NZCV& nzcv) { + return Inst(Opcode::GetCFlagFromNZCV, nzcv); + } + + NZCV NZCVFromPackedFlags(const U32& a) { + return Inst(Opcode::NZCVFromPackedFlags, a); + } + + NZCV NZCVFrom(const Value& value) { + return Inst(Opcode::GetNZCVFromOp, value); + } + + ResultAndCarry LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + const auto result = Inst(Opcode::LogicalShiftLeft32, value_in, shift_amount, carry_in); + const auto carry_out = Inst(Opcode::GetCarryFromOp, result); + return {result, carry_out}; + } + + ResultAndCarry LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + const auto result = Inst(Opcode::LogicalShiftRight32, value_in, shift_amount, carry_in); + const auto carry_out = Inst(Opcode::GetCarryFromOp, result); + return {result, carry_out}; + } + + ResultAndCarry ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + const auto result = Inst(Opcode::ArithmeticShiftRight32, value_in, shift_amount, carry_in); + const auto carry_out = Inst(Opcode::GetCarryFromOp, result); + return {result, carry_out}; + } + + ResultAndCarry RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + const auto result = Inst(Opcode::RotateRight32, value_in, shift_amount, carry_in); + const auto carry_out = Inst(Opcode::GetCarryFromOp, result); + return {result, carry_out}; + } + + ResultAndCarry RotateRightExtended(const U32& value_in, const U1& carry_in) { + const auto result = Inst(Opcode::RotateRightExtended, value_in, carry_in); + const auto carry_out = Inst(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(Opcode::LogicalShiftLeft32, value_in, shift_amount, Imm1(0)); + } else { + return Inst(Opcode::LogicalShiftLeft64, value_in, shift_amount); + } + } + + U32U64 LogicalShiftRight(const U32U64& value_in, const U8& shift_amount) { + if (value_in.GetType() == Type::U32) { + return Inst(Opcode::LogicalShiftRight32, value_in, shift_amount, Imm1(0)); + } else { + return Inst(Opcode::LogicalShiftRight64, value_in, shift_amount); + } + } + + U32U64 ArithmeticShiftRight(const U32U64& value_in, const U8& shift_amount) { + if (value_in.GetType() == Type::U32) { + return Inst(Opcode::ArithmeticShiftRight32, value_in, shift_amount, Imm1(0)); + } else { + return Inst(Opcode::ArithmeticShiftRight64, value_in, shift_amount); + } + } + + U32U64 RotateRight(const U32U64& value_in, const U8& shift_amount) { + if (value_in.GetType() == Type::U32) { + return Inst(Opcode::RotateRight32, value_in, shift_amount, Imm1(0)); + } else { + return Inst(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(Opcode::LogicalShiftLeftMasked32, value_in, shift_amount); + } else { + return Inst(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(Opcode::LogicalShiftRightMasked32, value_in, shift_amount); + } else { + return Inst(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(Opcode::ArithmeticShiftRightMasked32, value_in, shift_amount); + } else { + return Inst(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(Opcode::RotateRightMasked32, value_in, shift_amount); + } else { + return Inst(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(Opcode::Add32, a, b, carry_in); + } else { + return Inst(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(Opcode::Add32, a, b, Imm1(0)); + } else { + return Inst(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(Opcode::Sub32, a, b, carry_in); + } else { + return Inst(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(Opcode::Sub32, a, b, Imm1(1)); + } else { + return Inst(Opcode::Sub64, a, b, Imm1(1)); + } + } + + U32U64 Mul(const U32U64& a, const U32U64& b) { + if (a.GetType() == Type::U32) { + return Inst(Opcode::Mul32, a, b); + } + + return Inst(Opcode::Mul64, a, b); + } + + U64 UnsignedMultiplyHigh(const U64& a, const U64& b) { + return Inst(Opcode::UnsignedMultiplyHigh64, a, b); + } + + U64 SignedMultiplyHigh(const U64& a, const U64& b) { + return Inst(Opcode::SignedMultiplyHigh64, a, b); + } + + U32U64 UnsignedDiv(const U32U64& a, const U32U64& b) { + if (a.GetType() == Type::U32) { + return Inst(Opcode::UnsignedDiv32, a, b); + } + + return Inst(Opcode::UnsignedDiv64, a, b); + } + + U32U64 SignedDiv(const U32U64& a, const U32U64& b) { + if (a.GetType() == Type::U32) { + return Inst(Opcode::SignedDiv32, a, b); + } + + return Inst(Opcode::SignedDiv64, a, b); + } + + U32U64 And(const U32U64& a, const U32U64& b) { + ASSERT(a.GetType() == b.GetType()); + if (a.GetType() == Type::U32) { + return Inst(Opcode::And32, a, b); + } else { + return Inst(Opcode::And64, a, b); + } + } + + U32U64 AndNot(const U32U64& a, const U32U64& b) { + ASSERT(a.GetType() == b.GetType()); + if (a.GetType() == Type::U32) { + return Inst(Opcode::AndNot32, a, b); + } else { + return Inst(Opcode::AndNot64, a, b); + } + } + + U32U64 Eor(const U32U64& a, const U32U64& b) { + ASSERT(a.GetType() == b.GetType()); + if (a.GetType() == Type::U32) { + return Inst(Opcode::Eor32, a, b); + } else { + return Inst(Opcode::Eor64, a, b); + } + } + + U32U64 Or(const U32U64& a, const U32U64& b) { + ASSERT(a.GetType() == b.GetType()); + if (a.GetType() == Type::U32) { + return Inst(Opcode::Or32, a, b); + } else { + return Inst(Opcode::Or64, a, b); + } + } + + U32U64 Not(const U32U64& a) { + if (a.GetType() == Type::U32) { + return Inst(Opcode::Not32, a); + } else { + return Inst(Opcode::Not64, a); + } + } + + U64 SignExtendToLong(const UAny& a) { + switch (a.GetType()) { + case Type::U8: + return Inst(Opcode::SignExtendByteToLong, a); + case Type::U16: + return Inst(Opcode::SignExtendHalfToLong, a); + case Type::U32: + return Inst(Opcode::SignExtendWordToLong, a); + case Type::U64: + return U64(a); + default: + UNREACHABLE(); + } + } + + U32 SignExtendToWord(const UAny& a) { + switch (a.GetType()) { + case Type::U8: + return Inst(Opcode::SignExtendByteToWord, a); + case Type::U16: + return Inst(Opcode::SignExtendHalfToWord, a); + case Type::U32: + return U32(a); + case Type::U64: + return Inst(Opcode::LeastSignificantWord, a); + default: + UNREACHABLE(); + } + } + + U64 SignExtendWordToLong(const U32& a) { + return Inst(Opcode::SignExtendWordToLong, a); + } + + U32 SignExtendHalfToWord(const U16& a) { + return Inst(Opcode::SignExtendHalfToWord, a); + } + + U32 SignExtendByteToWord(const U8& a) { + return Inst(Opcode::SignExtendByteToWord, a); + } + + U64 ZeroExtendToLong(const UAny& a) { + switch (a.GetType()) { + case Type::U8: + return Inst(Opcode::ZeroExtendByteToLong, a); + case Type::U16: + return Inst(Opcode::ZeroExtendHalfToLong, a); + case Type::U32: + return Inst(Opcode::ZeroExtendWordToLong, a); + case Type::U64: + return U64(a); + default: + UNREACHABLE(); + } + } + + U32 ZeroExtendToWord(const UAny& a) { + switch (a.GetType()) { + case Type::U8: + return Inst(Opcode::ZeroExtendByteToWord, a); + case Type::U16: + return Inst(Opcode::ZeroExtendHalfToWord, a); + case Type::U32: + return U32(a); + case Type::U64: + return Inst(Opcode::LeastSignificantWord, a); + default: + UNREACHABLE(); + } + } + + U128 ZeroExtendToQuad(const UAny& a) { + return Inst(Opcode::ZeroExtendLongToQuad, ZeroExtendToLong(a)); + } + + U64 ZeroExtendWordToLong(const U32& a) { + return Inst(Opcode::ZeroExtendWordToLong, a); + } + + U32 ZeroExtendHalfToWord(const U16& a) { + return Inst(Opcode::ZeroExtendHalfToWord, a); + } + + U32 ZeroExtendByteToWord(const U8& a) { + return Inst(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(Opcode::ByteReverseWord, a); + } + + U16 ByteReverseHalf(const U16& a) { + return Inst(Opcode::ByteReverseHalf, a); + } + + U64 ByteReverseDual(const U64& a) { + return Inst(Opcode::ByteReverseDual, a); + } + + U32U64 CountLeadingZeros(const U32U64& a) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::CountLeadingZeros32, a); + } + + return Inst(Opcode::CountLeadingZeros64, a); + } + + U32U64 ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::ExtractRegister32, a, b, lsb); + } + + return Inst(Opcode::ExtractRegister64, a, b, lsb); + } + + U32U64 ReplicateBit(const U32U64& a, u8 bit) { + if (a.GetType() == IR::Type::U32) { + ASSERT(bit < 32); + return Inst(Opcode::ReplicateBit32, a, Imm8(bit)); + } + + ASSERT(bit < 64); + return Inst(Opcode::ReplicateBit64, a, Imm8(bit)); + } + + U32U64 MaxSigned(const U32U64& a, const U32U64& b) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::MaxSigned32, a, b); + } + + return Inst(Opcode::MaxSigned64, a, b); + } + + U32U64 MaxUnsigned(const U32U64& a, const U32U64& b) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::MaxUnsigned32, a, b); + } + + return Inst(Opcode::MaxUnsigned64, a, b); + } + + U32U64 MinSigned(const U32U64& a, const U32U64& b) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::MinSigned32, a, b); + } + + return Inst(Opcode::MinSigned64, a, b); + } + + U32U64 MinUnsigned(const U32U64& a, const U32U64& b) { + if (a.GetType() == IR::Type::U32) { + return Inst(Opcode::MinUnsigned32, a, b); + } + + return Inst(Opcode::MinUnsigned64, a, b); + } + + ResultAndOverflow SignedSaturatedAddWithFlag(const U32& a, const U32& b) { + const auto result = Inst(Opcode::SignedSaturatedAddWithFlag32, a, b); + const auto overflow = Inst(Opcode::GetOverflowFromOp, result); + return {result, overflow}; + } + + ResultAndOverflow SignedSaturatedSubWithFlag(const U32& a, const U32& b) { + const auto result = Inst(Opcode::SignedSaturatedSubWithFlag32, a, b); + const auto overflow = Inst(Opcode::GetOverflowFromOp, result); + return {result, overflow}; + } + + ResultAndOverflow 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(Opcode::SignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); + const auto overflow = Inst(Opcode::GetOverflowFromOp, result); + return {result, overflow}; + } + + ResultAndOverflow UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to) { + ASSERT(bit_size_to_saturate_to <= 31); + const auto result = Inst(Opcode::UnsignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); + const auto overflow = Inst(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(Opcode::SignedSaturatedAdd8, a, b); + case IR::Type::U16: + return Inst(Opcode::SignedSaturatedAdd16, a, b); + case IR::Type::U32: + return Inst(Opcode::SignedSaturatedAdd32, a, b); + case IR::Type::U64: + return Inst(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(Opcode::SignedSaturatedDoublingMultiplyReturnHigh16, a, b); + case IR::Type::U32: + return Inst(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(Opcode::SignedSaturatedSub8, a, b); + case IR::Type::U16: + return Inst(Opcode::SignedSaturatedSub16, a, b); + case IR::Type::U32: + return Inst(Opcode::SignedSaturatedSub32, a, b); + case IR::Type::U64: + return Inst(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(Opcode::UnsignedSaturatedAdd8, a, b); + case IR::Type::U16: + return Inst(Opcode::UnsignedSaturatedAdd16, a, b); + case IR::Type::U32: + return Inst(Opcode::UnsignedSaturatedAdd32, a, b); + case IR::Type::U64: + return Inst(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(Opcode::UnsignedSaturatedSub8, a, b); + case IR::Type::U16: + return Inst(Opcode::UnsignedSaturatedSub16, a, b); + case IR::Type::U32: + return Inst(Opcode::UnsignedSaturatedSub32, a, b); + case IR::Type::U64: + return Inst(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(Opcode::VectorSignedSaturatedAdd8, a, b); + case 16: + return Inst(Opcode::VectorSignedSaturatedAdd16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedAdd32, a, b); + case 64: + return Inst(Opcode::VectorSignedSaturatedAdd64, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorSignedSaturatedSub(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedSaturatedSub8, a, b); + case 16: + return Inst(Opcode::VectorSignedSaturatedSub16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedSub32, a, b); + case 64: + return Inst(Opcode::VectorSignedSaturatedSub64, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorUnsignedSaturatedAdd(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorUnsignedSaturatedAdd8, a, b); + case 16: + return Inst(Opcode::VectorUnsignedSaturatedAdd16, a, b); + case 32: + return Inst(Opcode::VectorUnsignedSaturatedAdd32, a, b); + case 64: + return Inst(Opcode::VectorUnsignedSaturatedAdd64, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorUnsignedSaturatedSub(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorUnsignedSaturatedSub8, a, b); + case 16: + return Inst(Opcode::VectorUnsignedSaturatedSub16, a, b); + case 32: + return Inst(Opcode::VectorUnsignedSaturatedSub32, a, b); + case 64: + return Inst(Opcode::VectorUnsignedSaturatedSub64, a, b); + default: + UNREACHABLE(); + } + } + + ResultAndGE PackedAddU8(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddU8, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedAddS8(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddS8, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedAddU16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddU16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedAddS16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddS16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubU8(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubU8, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubS8(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubS8, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubU16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubU16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubS16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubS16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedAddSubU16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddSubU16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedAddSubS16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedAddSubS16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubAddU16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubAddU16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + ResultAndGE PackedSubAddS16(const U32& a, const U32& b) { + const auto result = Inst(Opcode::PackedSubAddS16, a, b); + const auto ge = Inst(Opcode::GetGEFromOp, result); + return {result, ge}; + } + + U32 PackedHalvingAddU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddU8, a, b); + } + + U32 PackedHalvingAddS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddS8, a, b); + } + + U32 PackedHalvingSubU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubU8, a, b); + } + + U32 PackedHalvingSubS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubS8, a, b); + } + + U32 PackedHalvingAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddU16, a, b); + } + + U32 PackedHalvingAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddS16, a, b); + } + + U32 PackedHalvingSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubU16, a, b); + } + + U32 PackedHalvingSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubS16, a, b); + } + + U32 PackedHalvingAddSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddSubU16, a, b); + } + + U32 PackedHalvingAddSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddSubS16, a, b); + } + + U32 PackedHalvingSubAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubAddU16, a, b); + } + + U32 PackedHalvingSubAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubAddS16, a, b); + } + + U32 PackedSaturatedAddU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddU8, a, b); + } + + U32 PackedSaturatedAddS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddS8, a, b); + } + + U32 PackedSaturatedSubU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubU8, a, b); + } + + U32 PackedSaturatedSubS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubS8, a, b); + } + + U32 PackedSaturatedAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddU16, a, b); + } + + U32 PackedSaturatedAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddS16, a, b); + } + + U32 PackedSaturatedSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubU16, a, b); + } + + U32 PackedSaturatedSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubS16, a, b); + } + + U32 PackedAbsDiffSumU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedAbsDiffSumU8, a, b); + } + + U32 PackedSelect(const U32& ge, const U32& a, const U32& b) { + return Inst(Opcode::PackedSelect, ge, a, b); + } + + U32 CRC32Castagnoli8(const U32& a, const U32& b) { + return Inst(Opcode::CRC32Castagnoli8, a, b); + } + + U32 CRC32Castagnoli16(const U32& a, const U32& b) { + return Inst(Opcode::CRC32Castagnoli16, a, b); + } + + U32 CRC32Castagnoli32(const U32& a, const U32& b) { + return Inst(Opcode::CRC32Castagnoli32, a, b); + } + + U32 CRC32Castagnoli64(const U32& a, const U64& b) { + return Inst(Opcode::CRC32Castagnoli64, a, b); + } + + U32 CRC32ISO8(const U32& a, const U32& b) { + return Inst(Opcode::CRC32ISO8, a, b); + } + + U32 CRC32ISO16(const U32& a, const U32& b) { + return Inst(Opcode::CRC32ISO16, a, b); + } + + U32 CRC32ISO32(const U32& a, const U32& b) { + return Inst(Opcode::CRC32ISO32, a, b); + } + + U32 CRC32ISO64(const U32& a, const U64& b) { + return Inst(Opcode::CRC32ISO64, a, b); + } + + U128 AESDecryptSingleRound(const U128& a) { + return Inst(Opcode::AESDecryptSingleRound, a); + } + + U128 AESEncryptSingleRound(const U128& a) { + return Inst(Opcode::AESEncryptSingleRound, a); + } + + U128 AESInverseMixColumns(const U128& a) { + return Inst(Opcode::AESInverseMixColumns, a); + } + + U128 AESMixColumns(const U128& a) { + return Inst(Opcode::AESMixColumns, a); + } + + U8 SM4AccessSubstitutionBox(const U8& a) { + return Inst(Opcode::SM4AccessSubstitutionBox, a); + } + + U128 SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1) { + return Inst(Opcode::SHA256Hash, x, y, w, Imm1(part1)); + } + + U128 SHA256MessageSchedule0(const U128& x, const U128& y) { + return Inst(Opcode::SHA256MessageSchedule0, x, y); + } + + U128 SHA256MessageSchedule1(const U128& x, const U128& y, const U128& z) { + return Inst(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(Opcode::VectorGetElement8, a, Imm8(static_cast(index))); + case 16: + return Inst(Opcode::VectorGetElement16, a, Imm8(static_cast(index))); + case 32: + return Inst(Opcode::VectorGetElement32, a, Imm8(static_cast(index))); + case 64: + return Inst(Opcode::VectorGetElement64, a, Imm8(static_cast(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(Opcode::VectorSetElement8, a, Imm8(static_cast(index)), elem); + case 16: + return Inst(Opcode::VectorSetElement16, a, Imm8(static_cast(index)), elem); + case 32: + return Inst(Opcode::VectorSetElement32, a, Imm8(static_cast(index)), elem); + case 64: + return Inst(Opcode::VectorSetElement64, a, Imm8(static_cast(index)), elem); + default: + UNREACHABLE(); + } + } + + U128 VectorAbs(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorAbs8, a); + case 16: + return Inst(Opcode::VectorAbs16, a); + case 32: + return Inst(Opcode::VectorAbs32, a); + case 64: + return Inst(Opcode::VectorAbs64, a); + } + UNREACHABLE(); + } + + U128 VectorAdd(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorAdd8, a, b); + case 16: + return Inst(Opcode::VectorAdd16, a, b); + case 32: + return Inst(Opcode::VectorAdd32, a, b); + case 64: + return Inst(Opcode::VectorAdd64, a, b); + } + UNREACHABLE(); + } + + U128 VectorAnd(const U128& a, const U128& b) { + return Inst(Opcode::VectorAnd, a, b); + } + + U128 VectorAndNot(const U128& a, const U128& b) { + return Inst(Opcode::VectorAndNot, a, b); + } + + U128 VectorArithmeticShiftRight(size_t esize, const U128& a, u8 shift_amount) { + switch (esize) { + case 8: + return Inst(Opcode::VectorArithmeticShiftRight8, a, Imm8(shift_amount)); + case 16: + return Inst(Opcode::VectorArithmeticShiftRight16, a, Imm8(shift_amount)); + case 32: + return Inst(Opcode::VectorArithmeticShiftRight32, a, Imm8(shift_amount)); + case 64: + return Inst(Opcode::VectorArithmeticShiftRight64, a, Imm8(shift_amount)); + } + UNREACHABLE(); + } + + U128 VectorArithmeticVShift(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorArithmeticVShift8, a, b); + case 16: + return Inst(Opcode::VectorArithmeticVShift16, a, b); + case 32: + return Inst(Opcode::VectorArithmeticVShift32, a, b); + case 64: + return Inst(Opcode::VectorArithmeticVShift64, a, b); + } + UNREACHABLE(); + } + + U128 VectorBroadcastLower(size_t esize, const UAny& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorBroadcastLower8, U8(a)); + case 16: + return Inst(Opcode::VectorBroadcastLower16, U16(a)); + case 32: + return Inst(Opcode::VectorBroadcastLower32, U32(a)); + } + UNREACHABLE(); + } + + U128 VectorBroadcast(size_t esize, const UAny& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorBroadcast8, U8(a)); + case 16: + return Inst(Opcode::VectorBroadcast16, U16(a)); + case 32: + return Inst(Opcode::VectorBroadcast32, U32(a)); + case 64: + return Inst(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(Opcode::VectorBroadcastElementLower8, a, u8(index)); + case 16: + return Inst(Opcode::VectorBroadcastElementLower16, a, u8(index)); + case 32: + return Inst(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(Opcode::VectorBroadcastElement8, a, u8(index)); + case 16: + return Inst(Opcode::VectorBroadcastElement16, a, u8(index)); + case 32: + return Inst(Opcode::VectorBroadcastElement32, a, u8(index)); + case 64: + return Inst(Opcode::VectorBroadcastElement64, a, u8(index)); + } + UNREACHABLE(); + } + + U128 VectorCountLeadingZeros(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorCountLeadingZeros8, a); + case 16: + return Inst(Opcode::VectorCountLeadingZeros16, a); + case 32: + return Inst(Opcode::VectorCountLeadingZeros32, a); + } + UNREACHABLE(); + } + + U128 VectorDeinterleaveEven(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorDeinterleaveEven8, a, b); + case 16: + return Inst(Opcode::VectorDeinterleaveEven16, a, b); + case 32: + return Inst(Opcode::VectorDeinterleaveEven32, a, b); + case 64: + return Inst(Opcode::VectorDeinterleaveEven64, a, b); + } + UNREACHABLE(); + } + + U128 VectorDeinterleaveOdd(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorDeinterleaveOdd8, a, b); + case 16: + return Inst(Opcode::VectorDeinterleaveOdd16, a, b); + case 32: + return Inst(Opcode::VectorDeinterleaveOdd32, a, b); + case 64: + return Inst(Opcode::VectorDeinterleaveOdd64, a, b); + } + UNREACHABLE(); + } + + U128 VectorDeinterleaveEvenLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorDeinterleaveEvenLower8, a, b); + case 16: + return Inst(Opcode::VectorDeinterleaveEvenLower16, a, b); + case 32: + return Inst(Opcode::VectorDeinterleaveEvenLower32, a, b); + } + UNREACHABLE(); + } + + U128 VectorDeinterleaveOddLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorDeinterleaveOddLower8, a, b); + case 16: + return Inst(Opcode::VectorDeinterleaveOddLower16, a, b); + case 32: + return Inst(Opcode::VectorDeinterleaveOddLower32, a, b); + } + UNREACHABLE(); + } + + U128 VectorEor(const U128& a, const U128& b) { + return Inst(Opcode::VectorEor, a, b); + } + + U128 VectorEqual(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorEqual8, a, b); + case 16: + return Inst(Opcode::VectorEqual16, a, b); + case 32: + return Inst(Opcode::VectorEqual32, a, b); + case 64: + return Inst(Opcode::VectorEqual64, a, b); + case 128: + return Inst(Opcode::VectorEqual128, a, b); + } + UNREACHABLE(); + } + + U128 VectorExtract(const U128& a, const U128& b, size_t position) { + ASSERT(position <= 128); + return Inst(Opcode::VectorExtract, a, b, Imm8(static_cast(position))); + } + + U128 VectorExtractLower(const U128& a, const U128& b, size_t position) { + ASSERT(position <= 64); + return Inst(Opcode::VectorExtractLower, a, b, Imm8(static_cast(position))); + } + + U128 VectorGreaterSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorGreaterS8, a, b); + case 16: + return Inst(Opcode::VectorGreaterS16, a, b); + case 32: + return Inst(Opcode::VectorGreaterS32, a, b); + case 64: + return Inst(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(Opcode::VectorHalvingAddS8, a, b); + case 16: + return Inst(Opcode::VectorHalvingAddS16, a, b); + case 32: + return Inst(Opcode::VectorHalvingAddS32, a, b); + } + UNREACHABLE(); + } + + U128 VectorHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorHalvingAddU8, a, b); + case 16: + return Inst(Opcode::VectorHalvingAddU16, a, b); + case 32: + return Inst(Opcode::VectorHalvingAddU32, a, b); + } + UNREACHABLE(); + } + + U128 VectorHalvingSubSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorHalvingSubS8, a, b); + case 16: + return Inst(Opcode::VectorHalvingSubS16, a, b); + case 32: + return Inst(Opcode::VectorHalvingSubS32, a, b); + } + UNREACHABLE(); + } + + U128 VectorHalvingSubUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorHalvingSubU8, a, b); + case 16: + return Inst(Opcode::VectorHalvingSubU16, a, b); + case 32: + return Inst(Opcode::VectorHalvingSubU32, a, b); + } + UNREACHABLE(); + } + + U128 VectorInterleaveLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorInterleaveLower8, a, b); + case 16: + return Inst(Opcode::VectorInterleaveLower16, a, b); + case 32: + return Inst(Opcode::VectorInterleaveLower32, a, b); + case 64: + return Inst(Opcode::VectorInterleaveLower64, a, b); + } + UNREACHABLE(); + } + + U128 VectorInterleaveUpper(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorInterleaveUpper8, a, b); + case 16: + return Inst(Opcode::VectorInterleaveUpper16, a, b); + case 32: + return Inst(Opcode::VectorInterleaveUpper32, a, b); + case 64: + return Inst(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(Opcode::VectorLogicalShiftLeft8, a, Imm8(shift_amount)); + case 16: + return Inst(Opcode::VectorLogicalShiftLeft16, a, Imm8(shift_amount)); + case 32: + return Inst(Opcode::VectorLogicalShiftLeft32, a, Imm8(shift_amount)); + case 64: + return Inst(Opcode::VectorLogicalShiftLeft64, a, Imm8(shift_amount)); + } + UNREACHABLE(); + } + + U128 VectorLogicalShiftRight(size_t esize, const U128& a, u8 shift_amount) { + switch (esize) { + case 8: + return Inst(Opcode::VectorLogicalShiftRight8, a, Imm8(shift_amount)); + case 16: + return Inst(Opcode::VectorLogicalShiftRight16, a, Imm8(shift_amount)); + case 32: + return Inst(Opcode::VectorLogicalShiftRight32, a, Imm8(shift_amount)); + case 64: + return Inst(Opcode::VectorLogicalShiftRight64, a, Imm8(shift_amount)); + } + UNREACHABLE(); + } + + U128 VectorLogicalVShift(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorLogicalVShift8, a, b); + case 16: + return Inst(Opcode::VectorLogicalVShift16, a, b); + case 32: + return Inst(Opcode::VectorLogicalVShift32, a, b); + case 64: + return Inst(Opcode::VectorLogicalVShift64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMaxSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMaxS8, a, b); + case 16: + return Inst(Opcode::VectorMaxS16, a, b); + case 32: + return Inst(Opcode::VectorMaxS32, a, b); + case 64: + return Inst(Opcode::VectorMaxS64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMaxUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMaxU8, a, b); + case 16: + return Inst(Opcode::VectorMaxU16, a, b); + case 32: + return Inst(Opcode::VectorMaxU32, a, b); + case 64: + return Inst(Opcode::VectorMaxU64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMinSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMinS8, a, b); + case 16: + return Inst(Opcode::VectorMinS16, a, b); + case 32: + return Inst(Opcode::VectorMinS32, a, b); + case 64: + return Inst(Opcode::VectorMinS64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMinUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMinU8, a, b); + case 16: + return Inst(Opcode::VectorMinU16, a, b); + case 32: + return Inst(Opcode::VectorMinU32, a, b); + case 64: + return Inst(Opcode::VectorMinU64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMultiply(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMultiply8, a, b); + case 16: + return Inst(Opcode::VectorMultiply16, a, b); + case 32: + return Inst(Opcode::VectorMultiply32, a, b); + case 64: + return Inst(Opcode::VectorMultiply64, a, b); + } + UNREACHABLE(); + } + + U128 VectorMultiplySignedWiden(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMultiplySignedWiden8, a, b); + case 16: + return Inst(Opcode::VectorMultiplySignedWiden16, a, b); + case 32: + return Inst(Opcode::VectorMultiplySignedWiden32, a, b); + } + UNREACHABLE(); + } + + U128 VectorMultiplyUnsignedWiden(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorMultiplyUnsignedWiden8, a, b); + case 16: + return Inst(Opcode::VectorMultiplyUnsignedWiden16, a, b); + case 32: + return Inst(Opcode::VectorMultiplyUnsignedWiden32, a, b); + } + UNREACHABLE(); + } + + U128 VectorNarrow(size_t original_esize, const U128& a) { + switch (original_esize) { + case 16: + return Inst(Opcode::VectorNarrow16, a); + case 32: + return Inst(Opcode::VectorNarrow32, a); + case 64: + return Inst(Opcode::VectorNarrow64, a); + } + UNREACHABLE(); + } + + U128 VectorNot(const U128& a) { + return Inst(Opcode::VectorNot, a); + } + + U128 VectorOr(const U128& a, const U128& b) { + return Inst(Opcode::VectorOr, a, b); + } + + U128 VectorPairedAdd(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedAdd8, a, b); + case 16: + return Inst(Opcode::VectorPairedAdd16, a, b); + case 32: + return Inst(Opcode::VectorPairedAdd32, a, b); + case 64: + return Inst(Opcode::VectorPairedAdd64, a, b); + } + UNREACHABLE(); + } + + U128 VectorPairedAddLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedAddLower8, a, b); + case 16: + return Inst(Opcode::VectorPairedAddLower16, a, b); + case 32: + return Inst(Opcode::VectorPairedAddLower32, a, b); + } + UNREACHABLE(); + } + + U128 VectorPairedAddSignedWiden(size_t original_esize, const U128& a) { + switch (original_esize) { + case 8: + return Inst(Opcode::VectorPairedAddSignedWiden8, a); + case 16: + return Inst(Opcode::VectorPairedAddSignedWiden16, a); + case 32: + return Inst(Opcode::VectorPairedAddSignedWiden32, a); + } + UNREACHABLE(); + } + + U128 VectorPairedAddUnsignedWiden(size_t original_esize, const U128& a) { + switch (original_esize) { + case 8: + return Inst(Opcode::VectorPairedAddUnsignedWiden8, a); + case 16: + return Inst(Opcode::VectorPairedAddUnsignedWiden16, a); + case 32: + return Inst(Opcode::VectorPairedAddUnsignedWiden32, a); + } + UNREACHABLE(); + } + + U128 VectorPairedMaxSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMaxS8, a, b); + case 16: + return Inst(Opcode::VectorPairedMaxS16, a, b); + case 32: + return Inst(Opcode::VectorPairedMaxS32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMaxUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMaxU8, a, b); + case 16: + return Inst(Opcode::VectorPairedMaxU16, a, b); + case 32: + return Inst(Opcode::VectorPairedMaxU32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMinSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMinS8, a, b); + case 16: + return Inst(Opcode::VectorPairedMinS16, a, b); + case 32: + return Inst(Opcode::VectorPairedMinS32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMinUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMinU8, a, b); + case 16: + return Inst(Opcode::VectorPairedMinU16, a, b); + case 32: + return Inst(Opcode::VectorPairedMinU32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMaxSignedLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMaxLowerS8, a, b); + case 16: + return Inst(Opcode::VectorPairedMaxLowerS16, a, b); + case 32: + return Inst(Opcode::VectorPairedMaxLowerS32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMaxUnsignedLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMaxLowerU8, a, b); + case 16: + return Inst(Opcode::VectorPairedMaxLowerU16, a, b); + case 32: + return Inst(Opcode::VectorPairedMaxLowerU32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMinSignedLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMinLowerS8, a, b); + case 16: + return Inst(Opcode::VectorPairedMinLowerS16, a, b); + case 32: + return Inst(Opcode::VectorPairedMinLowerS32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPairedMinUnsignedLower(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPairedMinLowerU8, a, b); + case 16: + return Inst(Opcode::VectorPairedMinLowerU16, a, b); + case 32: + return Inst(Opcode::VectorPairedMinLowerU32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPolynomialMultiply(const U128& a, const U128& b) { + return Inst(Opcode::VectorPolynomialMultiply8, a, b); + } + + U128 VectorPolynomialMultiplyLong(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorPolynomialMultiplyLong8, a, b); + case 64: + return Inst(Opcode::VectorPolynomialMultiplyLong64, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorPopulationCount(const U128& a) { + return Inst(Opcode::VectorPopulationCount, a); + } + + U128 VectorReverseBits(const U128& a) { + return Inst(Opcode::VectorReverseBits, a); + } + + U128 VectorReverseElementsInHalfGroups(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorReverseElementsInHalfGroups8, a); + default: + UNREACHABLE(); + } + } + + U128 VectorReverseElementsInWordGroups(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorReverseElementsInWordGroups8, a); + case 16: + return Inst(Opcode::VectorReverseElementsInWordGroups16, a); + default: + UNREACHABLE(); + } + } + + U128 VectorReverseElementsInLongGroups(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorReverseElementsInLongGroups8, a); + case 16: + return Inst(Opcode::VectorReverseElementsInLongGroups16, a); + case 32: + return Inst(Opcode::VectorReverseElementsInLongGroups32, a); + default: + UNREACHABLE(); + } + } + + U128 VectorReduceAdd(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorReduceAdd8, a); + case 16: + return Inst(Opcode::VectorReduceAdd16, a); + case 32: + return Inst(Opcode::VectorReduceAdd32, a); + case 64: + return Inst(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(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(esize - amount))); + } + + U128 VectorRotateWholeVectorRight(const U128& a, u8 amount) { + ASSERT(amount % 32 == 0); + return Inst(Opcode::VectorRotateWholeVectorRight, a, Imm8(amount)); + } + + U128 VectorRoundingHalvingAddSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorRoundingHalvingAddS8, a, b); + case 16: + return Inst(Opcode::VectorRoundingHalvingAddS16, a, b); + case 32: + return Inst(Opcode::VectorRoundingHalvingAddS32, a, b); + } + + UNREACHABLE(); + } + + U128 VectorRoundingHalvingAddUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorRoundingHalvingAddU8, a, b); + case 16: + return Inst(Opcode::VectorRoundingHalvingAddU16, a, b); + case 32: + return Inst(Opcode::VectorRoundingHalvingAddU32, a, b); + } + + UNREACHABLE(); + } + + U128 VectorRoundingShiftLeftSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorRoundingShiftLeftS8, a, b); + case 16: + return Inst(Opcode::VectorRoundingShiftLeftS16, a, b); + case 32: + return Inst(Opcode::VectorRoundingShiftLeftS32, a, b); + case 64: + return Inst(Opcode::VectorRoundingShiftLeftS64, a, b); + } + + UNREACHABLE(); + } + + U128 VectorRoundingShiftLeftUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorRoundingShiftLeftU8, a, b); + case 16: + return Inst(Opcode::VectorRoundingShiftLeftU16, a, b); + case 32: + return Inst(Opcode::VectorRoundingShiftLeftU32, a, b); + case 64: + return Inst(Opcode::VectorRoundingShiftLeftU64, a, b); + } + + UNREACHABLE(); + } + + U128 VectorSignExtend(size_t original_esize, const U128& a) { + switch (original_esize) { + case 8: + return Inst(Opcode::VectorSignExtend8, a); + case 16: + return Inst(Opcode::VectorSignExtend16, a); + case 32: + return Inst(Opcode::VectorSignExtend32, a); + case 64: + return Inst(Opcode::VectorSignExtend64, a); + } + UNREACHABLE(); + } + + U128 VectorSignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedAbsoluteDifference8, a, b); + case 16: + return Inst(Opcode::VectorSignedAbsoluteDifference16, a, b); + case 32: + return Inst(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(Opcode::GetUpperFromOp, multiply), + Inst(Opcode::GetLowerFromOp, multiply), + }; + } + + U128 VectorSignedSaturatedAbs(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedSaturatedAbs8, a); + case 16: + return Inst(Opcode::VectorSignedSaturatedAbs16, a); + case 32: + return Inst(Opcode::VectorSignedSaturatedAbs32, a); + case 64: + return Inst(Opcode::VectorSignedSaturatedAbs64, a); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedAccumulateUnsigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned8, a, b); + case 16: + return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned32, a, b); + case 64: + return Inst(Opcode::VectorSignedSaturatedAccumulateUnsigned64, a, b); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedDoublingMultiplyHigh(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 16: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHigh16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHigh32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorSignedSaturatedDoublingMultiplyHighRounding(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 16: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyHighRounding32, a, b); + default: + UNREACHABLE(); + } + } + + U128 VectorSignedSaturatedDoublingMultiplyLong(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 16: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyLong16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedDoublingMultiplyLong32, a, b); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedNarrowToSigned(size_t original_esize, const U128& a) { + switch (original_esize) { + case 16: + return Inst(Opcode::VectorSignedSaturatedNarrowToSigned16, a); + case 32: + return Inst(Opcode::VectorSignedSaturatedNarrowToSigned32, a); + case 64: + return Inst(Opcode::VectorSignedSaturatedNarrowToSigned64, a); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedNarrowToUnsigned(size_t original_esize, const U128& a) { + switch (original_esize) { + case 16: + return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned16, a); + case 32: + return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned32, a); + case 64: + return Inst(Opcode::VectorSignedSaturatedNarrowToUnsigned64, a); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedNeg(size_t esize, const U128& a) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedSaturatedNeg8, a); + case 16: + return Inst(Opcode::VectorSignedSaturatedNeg16, a); + case 32: + return Inst(Opcode::VectorSignedSaturatedNeg32, a); + case 64: + return Inst(Opcode::VectorSignedSaturatedNeg64, a); + } + UNREACHABLE(); + } + + U128 VectorSignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSignedSaturatedShiftLeft8, a, b); + case 16: + return Inst(Opcode::VectorSignedSaturatedShiftLeft16, a, b); + case 32: + return Inst(Opcode::VectorSignedSaturatedShiftLeft32, a, b); + case 64: + return Inst(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(Opcode::VectorSignedSaturatedShiftLeftUnsigned8, a, Imm8(shift_amount)); + case 16: + return Inst(Opcode::VectorSignedSaturatedShiftLeftUnsigned16, a, Imm8(shift_amount)); + case 32: + return Inst(Opcode::VectorSignedSaturatedShiftLeftUnsigned32, a, Imm8(shift_amount)); + case 64: + return Inst(Opcode::VectorSignedSaturatedShiftLeftUnsigned64, a, Imm8(shift_amount)); + } + UNREACHABLE(); + } + + U128 VectorSub(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorSub8, a, b); + case 16: + return Inst(Opcode::VectorSub16, a, b); + case 32: + return Inst(Opcode::VectorSub32, a, b); + case 64: + return Inst(Opcode::VectorSub64, a, b); + } + UNREACHABLE(); + } + + Table VectorTable(std::vector values) { + ASSERT(values.size() >= 1 && values.size() <= 4); + values.resize(4); + return Inst
(Opcode::VectorTable, values[0], values[1], values[2], values[3]); + } + + Table VectorTable(std::vector values) { + ASSERT(values.size() >= 1 && values.size() <= 4); + values.resize(4); + return Inst
(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(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(Opcode::VectorTableLookup128, defaults, table, indices); + } + + U128 VectorTranspose(size_t esize, const U128& a, const U128& b, bool part) { + switch (esize) { + case 8: + return Inst(Opcode::VectorTranspose8, a, b, Imm1(part)); + case 16: + return Inst(Opcode::VectorTranspose16, a, b, Imm1(part)); + case 32: + return Inst(Opcode::VectorTranspose32, a, b, Imm1(part)); + case 64: + return Inst(Opcode::VectorTranspose64, a, b, Imm1(part)); + } + UNREACHABLE(); + } + + U128 VectorUnsignedAbsoluteDifference(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorUnsignedAbsoluteDifference8, a, b); + case 16: + return Inst(Opcode::VectorUnsignedAbsoluteDifference16, a, b); + case 32: + return Inst(Opcode::VectorUnsignedAbsoluteDifference32, a, b); + } + UNREACHABLE(); + } + + U128 VectorUnsignedRecipEstimate(const U128& a) { + return Inst(Opcode::VectorUnsignedRecipEstimate, a); + } + + U128 VectorUnsignedRecipSqrtEstimate(const U128& a) { + return Inst(Opcode::VectorUnsignedRecipSqrtEstimate, a); + } + + U128 VectorUnsignedSaturatedAccumulateSigned(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned8, a, b); + case 16: + return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned16, a, b); + case 32: + return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned32, a, b); + case 64: + return Inst(Opcode::VectorUnsignedSaturatedAccumulateSigned64, a, b); + } + UNREACHABLE(); + } + + U128 VectorUnsignedSaturatedNarrow(size_t esize, const U128& a) { + switch (esize) { + case 16: + return Inst(Opcode::VectorUnsignedSaturatedNarrow16, a); + case 32: + return Inst(Opcode::VectorUnsignedSaturatedNarrow32, a); + case 64: + return Inst(Opcode::VectorUnsignedSaturatedNarrow64, a); + } + UNREACHABLE(); + } + + U128 VectorUnsignedSaturatedShiftLeft(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 8: + return Inst(Opcode::VectorUnsignedSaturatedShiftLeft8, a, b); + case 16: + return Inst(Opcode::VectorUnsignedSaturatedShiftLeft16, a, b); + case 32: + return Inst(Opcode::VectorUnsignedSaturatedShiftLeft32, a, b); + case 64: + return Inst(Opcode::VectorUnsignedSaturatedShiftLeft64, a, b); + } + UNREACHABLE(); + } + + U128 VectorZeroExtend(size_t original_esize, const U128& a) { + switch (original_esize) { + case 8: + return Inst(Opcode::VectorZeroExtend8, a); + case 16: + return Inst(Opcode::VectorZeroExtend16, a); + case 32: + return Inst(Opcode::VectorZeroExtend32, a); + case 64: + return Inst(Opcode::VectorZeroExtend64, a); + } + UNREACHABLE(); + } + + U128 VectorZeroUpper(const U128& a) { + return Inst(Opcode::VectorZeroUpper, a); + } + + U128 ZeroVector() { + return Inst(Opcode::ZeroVector); + } + + U16U32U64 FPAbs(const U16U32U64& a) { + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPAbs16, a); + case Type::U32: + return Inst(Opcode::FPAbs32, a); + case Type::U64: + return Inst(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(Opcode::FPAdd32, a, b); + case Type::U64: + return Inst(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(Opcode::FPCompare32, a, b, exc_on_qnan_imm); + case Type::U64: + return Inst(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(Opcode::FPDiv32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMax32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMaxNumeric32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMin32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMinNumeric32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMul32, a, b); + case Type::U64: + return Inst(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(Opcode::FPMulAdd16, a, b, c); + case Type::U32: + return Inst(Opcode::FPMulAdd32, a, b, c); + case Type::U64: + return Inst(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(Opcode::FPMulSub16, a, b, c); + case Type::U32: + return Inst(Opcode::FPMulSub32, a, b, c); + case Type::U64: + return Inst(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(Opcode::FPMulX32, a, b); + case Type::U64: + return Inst(Opcode::FPMulX64, a, b); + default: + UNREACHABLE(); + } + } + + U16U32U64 FPNeg(const U16U32U64& a) { + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPNeg16, a); + case Type::U32: + return Inst(Opcode::FPNeg32, a); + case Type::U64: + return Inst(Opcode::FPNeg64, a); + default: + UNREACHABLE(); + } + } + + U16U32U64 FPRecipEstimate(const U16U32U64& a) { + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPRecipEstimate16, a); + case Type::U32: + return Inst(Opcode::FPRecipEstimate32, a); + case Type::U64: + return Inst(Opcode::FPRecipEstimate64, a); + default: + UNREACHABLE(); + } + } + + U16U32U64 FPRecipExponent(const U16U32U64& a) { + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPRecipExponent16, a); + case Type::U32: + return Inst(Opcode::FPRecipExponent32, a); + case Type::U64: + return Inst(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(Opcode::FPRecipStepFused16, a, b); + case Type::U32: + return Inst(Opcode::FPRecipStepFused32, a, b); + case Type::U64: + return Inst(Opcode::FPRecipStepFused64, a, b); + default: + UNREACHABLE(); + } + } + + U16U32U64 FPRoundInt(const U16U32U64& a, FP::RoundingMode rounding, bool exact) { + const u8 rounding_value = static_cast(rounding); + const IR::U1 exact_imm = Imm1(exact); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPRoundInt16, a, rounding_value, exact_imm); + case Type::U32: + return Inst(Opcode::FPRoundInt32, a, rounding_value, exact_imm); + case Type::U64: + return Inst(Opcode::FPRoundInt64, a, rounding_value, exact_imm); + default: + UNREACHABLE(); + } + } + + U16U32U64 FPRSqrtEstimate(const U16U32U64& a) { + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPRSqrtEstimate16, a); + case Type::U32: + return Inst(Opcode::FPRSqrtEstimate32, a); + case Type::U64: + return Inst(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(Opcode::FPRSqrtStepFused16, a, b); + case Type::U32: + return Inst(Opcode::FPRSqrtStepFused32, a, b); + case Type::U64: + return Inst(Opcode::FPRSqrtStepFused64, a, b); + default: + UNREACHABLE(); + } + } + + U32U64 FPSqrt(const U32U64& a) { + switch (a.GetType()) { + case Type::U32: + return Inst(Opcode::FPSqrt32, a); + case Type::U64: + return Inst(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(Opcode::FPSub32, a, b); + case Type::U64: + return Inst(Opcode::FPSub64, a, b); + default: + UNREACHABLE(); + } + } + + U16 FPDoubleToHalf(const U64& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPDoubleToHalf, a, Imm8(static_cast(rounding))); + } + + U32 FPDoubleToSingle(const U64& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPDoubleToSingle, a, Imm8(static_cast(rounding))); + } + + U64 FPHalfToDouble(const U16& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPHalfToDouble, a, Imm8(static_cast(rounding))); + } + + U32 FPHalfToSingle(const U16& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPHalfToSingle, a, Imm8(static_cast(rounding))); + } + + U64 FPSingleToDouble(const U32& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPSingleToDouble, a, Imm8(static_cast(rounding))); + } + + U16 FPSingleToHalf(const U32& a, FP::RoundingMode rounding) { + return Inst(Opcode::FPSingleToHalf, a, Imm8(static_cast(rounding))); + } + + U16 FPToFixedS16(const U16U32U64& a, size_t fbits, FP::RoundingMode rounding) { + ASSERT(fbits <= 16); + + const U8 fbits_imm = Imm8(static_cast(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedS16, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedS16, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedS32, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedS32, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedS64, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedS64, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedU16, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedU16, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedU32, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedU32, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPHalfToFixedU64, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPSingleToFixedU64, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const IR::U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPFixedS16ToSingle, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPFixedS32ToSingle, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const IR::U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPFixedU16ToSingle, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPFixedU32ToSingle, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const IR::U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPFixedS16ToDouble, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPFixedS32ToDouble, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(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(fbits)); + const IR::U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (a.GetType()) { + case Type::U16: + return Inst(Opcode::FPFixedU16ToDouble, a, fbits_imm, rounding_imm); + case Type::U32: + return Inst(Opcode::FPFixedU32ToDouble, a, fbits_imm, rounding_imm); + case Type::U64: + return Inst(Opcode::FPFixedU64ToDouble, a, fbits_imm, rounding_imm); + default: + UNREACHABLE(); + } + } + + U128 FPVectorAbs(size_t esize, const U128& a) { + switch (esize) { + case 16: + return Inst(Opcode::FPVectorAbs16, a); + case 32: + return Inst(Opcode::FPVectorAbs32, a); + case 64: + return Inst(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(Opcode::FPVectorAdd32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorDiv32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorEqual16, a, b, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorEqual32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorFromHalf32, a, Imm8(static_cast(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(Opcode::FPVectorFromSignedFixed32, a, Imm8(static_cast(fbits)), Imm8(static_cast(rounding)), Imm1(fpcr_controlled)); + case 64: + return Inst(Opcode::FPVectorFromSignedFixed64, a, Imm8(static_cast(fbits)), Imm8(static_cast(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(Opcode::FPVectorFromUnsignedFixed32, a, Imm8(static_cast(fbits)), Imm8(static_cast(rounding)), Imm1(fpcr_controlled)); + case 64: + return Inst(Opcode::FPVectorFromUnsignedFixed64, a, Imm8(static_cast(fbits)), Imm8(static_cast(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(Opcode::FPVectorGreater32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorGreaterEqual32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMax32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMaxNumeric32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMin32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMinNumeric32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMul32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMulAdd16, a, b, c, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorMulAdd32, a, b, c, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorMulX32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(Opcode::FPVectorMulX64, a, b, Imm1(fpcr_controlled)); + } + UNREACHABLE(); + } + + U128 FPVectorNeg(size_t esize, const U128& a) { + switch (esize) { + case 16: + return Inst(Opcode::FPVectorNeg16, a); + case 32: + return Inst(Opcode::FPVectorNeg32, a); + case 64: + return Inst(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(Opcode::FPVectorPairedAdd32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorPairedAddLower32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorRecipEstimate16, a, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorRecipEstimate32, a, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorRecipStepFused16, a, b, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorRecipStepFused32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(rounding)); + const IR::U1 exact_imm = Imm1(exact); + + switch (esize) { + case 16: + return Inst(Opcode::FPVectorRoundInt16, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorRoundInt32, operand, rounding_imm, exact_imm, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorRSqrtEstimate16, a, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorRSqrtEstimate32, a, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorRSqrtStepFused16, a, b, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorRSqrtStepFused32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorSqrt32, a, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorSub32, a, b, Imm1(fpcr_controlled)); + case 64: + return Inst(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(Opcode::FPVectorToHalf32, a, Imm8(static_cast(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (esize) { + case 16: + return Inst(Opcode::FPVectorToSignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorToSignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); + case 64: + return Inst(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(fbits)); + const U8 rounding_imm = Imm8(static_cast(rounding)); + + switch (esize) { + case 16: + return Inst(Opcode::FPVectorToUnsignedFixed16, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); + case 32: + return Inst(Opcode::FPVectorToUnsignedFixed32, a, fbits_imm, rounding_imm, Imm1(fpcr_controlled)); + case 64: + return Inst(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(fn)), Value{}, Value{}, Value{}); + } + + void CallHostFunction(void (*fn)(u64), const U64& arg1) { + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), arg1, Value{}, Value{}); + } + + void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) { + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(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(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};