mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 12:55:45 +00:00
false flag deps removal with lea instead of mov; sub loses against dec since broadwell; untested winapi rearrangement (lea doesnt need to read from an obvious immediate)
This commit is contained in:
parent
2f421923a6
commit
bf91616cad
48 changed files with 3734 additions and 4124 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -33,6 +33,7 @@ CMakeLists.txt.user*
|
||||||
|
|
||||||
# Visual Studio CMake settings
|
# Visual Studio CMake settings
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
|
.cache/
|
||||||
|
|
||||||
# OSX global filetypes
|
# OSX global filetypes
|
||||||
# Created by Finder or Spotlight in directories for various OS functionality (indexing, etc)
|
# Created by Finder or Spotlight in directories for various OS functionality (indexing, etc)
|
||||||
|
|
6
externals/dynarmic/CMakeLists.txt
vendored
6
externals/dynarmic/CMakeLists.txt
vendored
|
@ -98,8 +98,7 @@ else()
|
||||||
-Wextra
|
-Wextra
|
||||||
-Wcast-qual
|
-Wcast-qual
|
||||||
-pedantic
|
-pedantic
|
||||||
-Wno-missing-braces
|
-Wno-missing-braces)
|
||||||
-Wstack-usage=4096)
|
|
||||||
|
|
||||||
if (ARCHITECTURE STREQUAL "x86_64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
list(APPEND DYNARMIC_CXX_FLAGS -mtune=core2)
|
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
|
# GCC knows that the variable is actually a Reg64. isMEM() will never return true for a
|
||||||
# Reg64, but GCC doesn't know that.
|
# Reg64, but GCC doesn't know that.
|
||||||
list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds)
|
list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds)
|
||||||
|
list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang")
|
||||||
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
|
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
|
||||||
# And this in turns limits the size of a std::array.
|
# And this in turns limits the size of a std::array.
|
||||||
list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024)
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
105
externals/dynarmic/src/dynarmic/CMakeLists.txt
vendored
105
externals/dynarmic/src/dynarmic/CMakeLists.txt
vendored
|
@ -125,52 +125,6 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
|
||||||
frontend/A32/translate/a32_translate.h
|
frontend/A32/translate/a32_translate.h
|
||||||
frontend/A32/translate/conditional_state.cpp
|
frontend/A32/translate/conditional_state.cpp
|
||||||
frontend/A32/translate/conditional_state.h
|
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_arm.cpp
|
||||||
frontend/A32/translate/translate_thumb.cpp
|
frontend/A32/translate/translate_thumb.cpp
|
||||||
interface/A32/a32.h
|
interface/A32/a32.h
|
||||||
|
@ -194,65 +148,6 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
||||||
frontend/A64/decoder/a64.inc
|
frontend/A64/decoder/a64.inc
|
||||||
frontend/A64/translate/a64_translate.cpp
|
frontend/A64/translate/a64_translate.cpp
|
||||||
frontend/A64/translate/a64_translate.h
|
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/a64.h
|
||||||
interface/A64/config.h
|
interface/A64/config.h
|
||||||
ir/opt/a64_callback_config_pass.cpp
|
ir/opt/a64_callback_config_pass.cpp
|
||||||
|
|
|
@ -59,13 +59,12 @@ constexpr RegisterList ToRegList(oaknut::Reg reg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg.index() == 31) {
|
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) {
|
if (reg.index() == -1) {
|
||||||
return RegisterList{1} << 31;
|
return RegisterList{1} << 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RegisterList{1} << reg.index();
|
return RegisterList{1} << reg.index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,29 +14,26 @@ namespace Dynarmic::Backend::RV64 {
|
||||||
|
|
||||||
class CodeBlock {
|
class CodeBlock {
|
||||||
public:
|
public:
|
||||||
explicit CodeBlock(std::size_t size)
|
explicit CodeBlock(std::size_t size) noexcept : memsize(size) {
|
||||||
: memsize(size) {
|
|
||||||
mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||||
|
|
||||||
if (mem == nullptr)
|
if (mem == nullptr)
|
||||||
throw std::bad_alloc{};
|
ASSERT_FALSE("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
~CodeBlock() {
|
~CodeBlock() noexcept {
|
||||||
if (mem == nullptr)
|
if (mem == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
munmap(mem, memsize);
|
munmap(mem, memsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T ptr() const {
|
T ptr() const noexcept {
|
||||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||||
return reinterpret_cast<T>(mem);
|
return reinterpret_cast<T>(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
u8* mem;
|
u8* mem = nullptr;
|
||||||
size_t memsize = 0;
|
size_t memsize = 0;
|
||||||
};
|
};
|
||||||
} // namespace Dynarmic::Backend::RV64
|
} // namespace Dynarmic::Backend::RV64
|
||||||
|
|
|
@ -124,35 +124,36 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
|
|
||||||
EmitCondPrelude(ctx);
|
EmitCondPrelude(ctx);
|
||||||
|
|
||||||
for (auto iter = block.begin(); iter != block.end(); ++iter) {
|
auto const loop_all_inst = [this, &block, &ctx](auto const func) {
|
||||||
IR::Inst* inst = &*iter;
|
for (auto iter = block.begin(); iter != block.end(); ++iter) [[likely]] {
|
||||||
|
auto* inst = &*iter;
|
||||||
// Call the relevant Emit* member function.
|
// Call the relevant Emit* member function.
|
||||||
switch (inst->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
#define OPCODE(name, type, ...) \
|
#define OPCODE(name, type, ...) \
|
||||||
case IR::Opcode::name: \
|
case IR::Opcode::name: \
|
||||||
A32EmitX64::Emit##name(ctx, inst); \
|
A32EmitX64::Emit##name(ctx, inst); \
|
||||||
break;
|
break;
|
||||||
#define A32OPC(name, type, ...) \
|
#define A32OPC(name, type, ...) \
|
||||||
case IR::Opcode::A32##name: \
|
case IR::Opcode::A32##name: \
|
||||||
A32EmitX64::EmitA32##name(ctx, inst); \
|
A32EmitX64::EmitA32##name(ctx, inst);\
|
||||||
break;
|
break;
|
||||||
#define A64OPC(...)
|
#define A64OPC(...)
|
||||||
#include "dynarmic/ir/opcodes.inc"
|
#include "dynarmic/ir/opcodes.inc"
|
||||||
#undef OPCODE
|
#undef OPCODE
|
||||||
#undef A32OPC
|
#undef A32OPC
|
||||||
#undef A64OPC
|
#undef A64OPC
|
||||||
|
default: [[unlikely]] ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
|
||||||
default:
|
}
|
||||||
ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
|
reg_alloc.EndOfAllocScope();
|
||||||
break;
|
func(reg_alloc);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
reg_alloc.EndOfAllocScope();
|
if (!conf.very_verbose_debugging_output) [[likely]] {
|
||||||
|
loop_all_inst([](auto&) { /*noop*/ });
|
||||||
if (conf.very_verbose_debugging_output) {
|
} else [[unlikely]] {
|
||||||
|
loop_all_inst([this](auto& reg_alloc) {
|
||||||
EmitVerboseDebuggingOutput(reg_alloc);
|
EmitVerboseDebuggingOutput(reg_alloc);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_alloc.AssertNoMoreUses();
|
reg_alloc.AssertNoMoreUses();
|
||||||
|
@ -229,7 +230,7 @@ void A32EmitX64::GenTerminalHandlers() {
|
||||||
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
||||||
calculate_location_descriptor();
|
calculate_location_descriptor();
|
||||||
code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]);
|
code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]);
|
||||||
code.sub(eax, 1);
|
code.dec(eax);
|
||||||
code.and_(eax, u32(A32JitState::RSBPtrMask));
|
code.and_(eax, u32(A32JitState::RSBPtrMask));
|
||||||
code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax);
|
code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax);
|
||||||
code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
||||||
|
|
|
@ -198,18 +198,19 @@ void A64EmitX64::GenTerminalHandlers() {
|
||||||
code.or_(rbx, rcx);
|
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();
|
code.align();
|
||||||
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
||||||
calculate_location_descriptor();
|
calculate_location_descriptor();
|
||||||
code.mov(eax, dword[r15 + offsetof(A64JitState, rsb_ptr)]);
|
code.mov(eax, dword[r15 + offsetof(A64JitState, rsb_ptr)]);
|
||||||
code.sub(eax, 1);
|
code.dec(eax);
|
||||||
code.and_(eax, u32(A64JitState::RSBPtrMask));
|
code.and_(eax, u32(A64JitState::RSBPtrMask));
|
||||||
code.mov(dword[r15 + offsetof(A64JitState, rsb_ptr)], eax);
|
code.mov(dword[r15 + offsetof(A64JitState, rsb_ptr)], eax);
|
||||||
code.cmp(rbx, qword[r15 + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
code.cmp(rbx, qword[r15 + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
||||||
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
|
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
|
||||||
code.jne(rsb_cache_miss);
|
code.jne(rsb_cache_miss, code.T_NEAR);
|
||||||
} else {
|
} else {
|
||||||
code.jne(code.GetReturnFromRunCodeAddress());
|
code.jne(code.GetReturnFromRunCodeAddress());
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ void A64EmitX64::GenMemory128Accessors() {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code, [&](Xbyak::Reg64 return_value_ptr, [[maybe_unused]] RegList args) {
|
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.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.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||||
});
|
});
|
||||||
code.movups(xmm1, xword[code.ABI_RETURN]);
|
code.movups(xmm1, xword[code.ABI_RETURN]);
|
||||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||||
#else
|
#else
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCall(code);
|
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCall(code);
|
||||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||||
code.movq(xmm1, code.ABI_RETURN);
|
code.movq(xmm1, code.ABI_RETURN);
|
||||||
|
@ -57,13 +57,13 @@ void A64EmitX64::GenMemory128Accessors() {
|
||||||
code.align();
|
code.align();
|
||||||
memory_write_128 = code.getCurr<void (*)()>();
|
memory_write_128 = code.getCurr<void (*)()>();
|
||||||
#ifdef _WIN32
|
#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.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||||
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
|
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
|
||||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||||
#else
|
#else
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||||
code.movq(code.ABI_PARAM3, xmm1);
|
code.movq(code.ABI_PARAM3, xmm1);
|
||||||
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
||||||
|
@ -81,7 +81,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
||||||
code.align();
|
code.align();
|
||||||
memory_exclusive_write_128 = code.getCurr<void (*)()>();
|
memory_exclusive_write_128 = code.getCurr<void (*)()>();
|
||||||
#ifdef _WIN32
|
#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_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||||
code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 16]);
|
code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 16]);
|
||||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||||
|
@ -89,7 +89,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
||||||
Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive128>(conf.callbacks).EmitCall(code);
|
Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive128>(conf.callbacks).EmitCall(code);
|
||||||
code.add(rsp, 8 + 32 + ABI_SHADOW_SPACE);
|
code.add(rsp, 8 + 32 + ABI_SHADOW_SPACE);
|
||||||
#else
|
#else
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||||
code.movq(code.ABI_PARAM3, xmm1);
|
code.movq(code.ABI_PARAM3, xmm1);
|
||||||
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
||||||
|
@ -131,8 +131,8 @@ void A64EmitX64::GenFastmemFallbacks() {
|
||||||
{64, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive64>(conf.callbacks)},
|
{64, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive64>(conf.callbacks)},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
for (bool ordered : {false, true}) {
|
for (auto const ordered : {false, true}) {
|
||||||
for (int vaddr_idx : idxes) {
|
for (auto const vaddr_idx : idxes) {
|
||||||
if (vaddr_idx == 4 || vaddr_idx == 15) {
|
if (vaddr_idx == 4 || vaddr_idx == 15) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,8 @@ public:
|
||||||
uint8_t* alloc(size_t size) override {
|
uint8_t* alloc(size_t size) override {
|
||||||
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
if (p == nullptr) {
|
if (p == nullptr) {
|
||||||
throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
|
using Xbyak::Error;
|
||||||
|
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
|
||||||
}
|
}
|
||||||
return static_cast<uint8_t*>(p);
|
return static_cast<uint8_t*>(p);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +96,8 @@ public:
|
||||||
|
|
||||||
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
|
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
|
||||||
if (p == MAP_FAILED) {
|
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));
|
std::memcpy(p, &size, sizeof(size_t));
|
||||||
return static_cast<uint8_t*>(p) + DYNARMIC_PAGE_SIZE;
|
return static_cast<uint8_t*>(p) + DYNARMIC_PAGE_SIZE;
|
||||||
|
@ -514,7 +516,8 @@ size_t BlockOfCode::GetTotalCodeSize() const {
|
||||||
|
|
||||||
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
||||||
if (size_ + alloc_size >= maxSize_) {
|
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);
|
EnsureMemoryCommitted(alloc_size);
|
||||||
|
|
|
@ -104,7 +104,7 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) {
|
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)]);
|
code.stmxcsr(dword[rsp + offsetof(RegisterData, mxcsr)]);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
if (rsp.getIdx() == 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);
|
const Xbyak::Reg value = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||||
code.test(value, value);
|
code.test(value, value);
|
||||||
code.lahf();
|
code.lahf();
|
||||||
code.mov(al, 0);
|
code.xor_(al, al);
|
||||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,6 @@ void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.shr(nzcv, 28);
|
code.shr(nzcv, 28);
|
||||||
code.imul(nzcv, nzcv, NZCV::to_x64_multiplier);
|
code.imul(nzcv, nzcv, NZCV::to_x64_multiplier);
|
||||||
code.and_(nzcv, NZCV::x64_mask);
|
code.and_(nzcv, NZCV::x64_mask);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,10 +330,8 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
|
||||||
code.jle(pass);
|
code.jle(pass);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(false, "Unknown cond {}", static_cast<size_t>(cond));
|
UNREACHABLE();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -992,7 +992,6 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
||||||
code.seto(overflow);
|
code.seto(overflow);
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,23 @@
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.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 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
using namespace Xbyak::util;
|
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_u32 = 0x41efffffffe00000u; // 4294967295 as a double
|
||||||
constexpr u64 f64_max_s64_lim = 0x43e0000000000000u; // 2^63 as a double (actual maximum unrepresentable)
|
constexpr u64 f64_max_s64_lim = 0x43e0000000000000u; // 2^63 as a double (actual maximum unrepresentable)
|
||||||
|
|
||||||
#define FCODE(NAME) \
|
|
||||||
[&code](auto... args) { \
|
|
||||||
if constexpr (fsize == 32) { \
|
|
||||||
code.NAME##s(args...); \
|
|
||||||
} else { \
|
|
||||||
code.NAME##d(args...); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define ICODE(NAME) \
|
|
||||||
[&code](auto... args) { \
|
|
||||||
if constexpr (fsize == 32) { \
|
|
||||||
code.NAME##d(args...); \
|
|
||||||
} else { \
|
|
||||||
code.NAME##q(args...); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t fsize>
|
template<size_t fsize>
|
||||||
void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> to_daz) {
|
void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> to_daz) {
|
||||||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||||
|
@ -473,7 +473,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t fsize, bool is_max>
|
template<size_t fsize, bool is_max>
|
||||||
static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) noexcept {
|
||||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||||
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
|
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
|
||||||
|
|
||||||
|
@ -701,15 +701,14 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
// x64 rounds before flushing to zero
|
// x64 rounds before flushing to zero
|
||||||
// AArch64 rounds after flushing to zero
|
// AArch64 rounds after flushing to zero
|
||||||
// This difference of behaviour is noticable if something would round to a smallest normalized number
|
// This difference of behaviour is noticable if something would round to a smallest normalized number
|
||||||
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
code.sub(rsp, 8);
|
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
code.movq(code.ABI_PARAM1, operand1);
|
code.movq(code.ABI_PARAM1, operand1);
|
||||||
code.movq(code.ABI_PARAM2, operand2);
|
code.movq(code.ABI_PARAM2, operand2);
|
||||||
code.movq(code.ABI_PARAM3, operand3);
|
code.movq(code.ABI_PARAM3, operand3);
|
||||||
code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value());
|
code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value());
|
||||||
#ifdef _WIN32
|
#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.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||||
code.mov(qword[rsp + ABI_SHADOW_SPACE], rax);
|
code.mov(qword[rsp + ABI_SHADOW_SPACE], rax);
|
||||||
code.CallFunction(fallback_fn);
|
code.CallFunction(fallback_fn);
|
||||||
|
@ -735,13 +734,13 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.vmovaps(xmm0, code.Const(xword, FP::FPInfo<FPT>::mantissa_msb));
|
code.vmovaps(xmm0, code.Const(xword, FP::FPInfo<FPT>::mantissa_msb));
|
||||||
|
|
||||||
FCODE(ucomis)(operand2, operand3);
|
FCODE(ucomis)(operand2, operand3);
|
||||||
code.jp(has_nan);
|
code.jp(has_nan, code.T_NEAR);
|
||||||
FCODE(ucomis)(operand1, operand1);
|
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}
|
// 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.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(vmuls)(xmm0, operand2, operand3); // check if {op2, op3} are {inf, zero}/{zero, inf}
|
||||||
FCODE(ucomis)(xmm0, xmm0);
|
FCODE(ucomis)(xmm0, xmm0);
|
||||||
code.jnp(*end);
|
code.jnp(*end);
|
||||||
|
@ -753,10 +752,10 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.L(has_nan);
|
code.L(has_nan);
|
||||||
|
|
||||||
FCODE(ucomis)(operand1, operand1);
|
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.movaps(result, operand1); // this is done because of NaN behavior of vfmadd231s (priority of op2, op3, op1)
|
||||||
code.ptest(operand1, xmm0);
|
code.ptest(operand1, xmm0);
|
||||||
code.jnz(op1_done);
|
code.jnz(op1_done, code.T_NEAR);
|
||||||
code.L(op1_snan);
|
code.L(op1_snan);
|
||||||
code.vorps(result, operand1, xmm0);
|
code.vorps(result, operand1, xmm0);
|
||||||
code.jmp(*end);
|
code.jmp(*end);
|
||||||
|
@ -774,9 +773,9 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.L(op2_done);
|
code.L(op2_done);
|
||||||
|
|
||||||
FCODE(ucomis)(operand3, operand3);
|
FCODE(ucomis)(operand3, operand3);
|
||||||
code.jnp(op3_done);
|
code.jnp(op3_done, code.T_NEAR);
|
||||||
code.ptest(operand3, xmm0);
|
code.ptest(operand3, xmm0);
|
||||||
code.jnz(op3_done);
|
code.jnz(op3_done, code.T_NEAR);
|
||||||
code.vorps(result, operand3, xmm0);
|
code.vorps(result, operand3, xmm0);
|
||||||
code.jmp(*end);
|
code.jmp(*end);
|
||||||
code.L(op3_done);
|
code.L(op3_done);
|
||||||
|
@ -1019,7 +1018,7 @@ static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst*
|
||||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*fallback);
|
code.L(*fallback);
|
||||||
|
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
code.movq(code.ABI_PARAM1, operand1);
|
code.movq(code.ABI_PARAM1, operand1);
|
||||||
code.movq(code.ABI_PARAM2, operand2);
|
code.movq(code.ABI_PARAM2, operand2);
|
||||||
|
@ -1204,9 +1203,9 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
}
|
}
|
||||||
|
|
||||||
// a > 0 && a < 0x00800000;
|
// a > 0 && a < 0x00800000;
|
||||||
code.sub(tmp, 1);
|
code.dec(tmp);
|
||||||
code.cmp(tmp, 0x007FFFFF);
|
code.cmp(tmp, 0x007FFFFF);
|
||||||
code.jb(fallback);
|
code.jb(fallback, code.T_NEAR); //within -127,128
|
||||||
needs_fallback = true;
|
needs_fallback = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,17 +1234,17 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
|
|
||||||
code.ucomisd(value, result);
|
code.ucomisd(value, result);
|
||||||
if (ctx.FPCR().DN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
code.jc(default_nan);
|
code.jc(default_nan, code.T_NEAR);
|
||||||
code.je(zero);
|
code.je(zero, code.T_NEAR);
|
||||||
} else {
|
} else {
|
||||||
code.jp(nan);
|
code.jp(nan, code.T_NEAR);
|
||||||
code.je(zero);
|
code.je(zero, code.T_NEAR);
|
||||||
code.jc(default_nan);
|
code.jc(default_nan, code.T_NEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx.FPCR().FZ()) {
|
if (!ctx.FPCR().FZ()) {
|
||||||
needs_fallback = true;
|
needs_fallback = true;
|
||||||
code.jmp(fallback);
|
code.jmp(fallback, code.T_NEAR);
|
||||||
} else {
|
} else {
|
||||||
// result = 0
|
// result = 0
|
||||||
code.jmp(*end, code.T_NEAR);
|
code.jmp(*end, code.T_NEAR);
|
||||||
|
@ -1278,7 +1277,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
|
|
||||||
code.L(fallback);
|
code.L(fallback);
|
||||||
if (needs_fallback) {
|
if (needs_fallback) {
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
code.movq(code.ABI_PARAM1, operand);
|
code.movq(code.ABI_PARAM1, operand);
|
||||||
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
|
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] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*fallback);
|
code.L(*fallback);
|
||||||
|
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
code.movq(code.ABI_PARAM1, operand1);
|
code.movq(code.ABI_PARAM1, operand1);
|
||||||
code.movq(code.ABI_PARAM2, operand2);
|
code.movq(code.ABI_PARAM2, operand2);
|
||||||
|
@ -2132,3 +2131,6 @@ void EmitX64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
}
|
}
|
||||||
} // namespace Dynarmic::Backend::X64
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
||||||
|
#undef FCODE
|
||||||
|
#undef ICODE
|
||||||
|
|
|
@ -161,8 +161,7 @@ template<>
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr<A64EmitContext>(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional<Xbyak::Reg64> tmp) {
|
[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr<A64EmitContext>(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional<Xbyak::Reg64> tmp) {
|
||||||
const size_t unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
|
auto const unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
|
||||||
|
|
||||||
if (unused_top_bits == 0) {
|
if (unused_top_bits == 0) {
|
||||||
return r13 + vaddr;
|
return r13 + vaddr;
|
||||||
} else if (ctx.conf.silently_mirror_fastmem) {
|
} 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.L(loop);
|
||||||
code.lock();
|
code.lock();
|
||||||
code.cmpxchg16b(xword[addr]);
|
code.cmpxchg16b(xword[addr]);
|
||||||
code.jnz(loop);
|
code.jnz(loop, code.T_NEAR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -373,7 +372,7 @@ void EmitExclusiveTestAndClear(BlockOfCode& code, const UserConfig& conf, Xbyak:
|
||||||
Xbyak::Label ok;
|
Xbyak::Label ok;
|
||||||
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index)));
|
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index)));
|
||||||
code.cmp(qword[pointer], vaddr);
|
code.cmp(qword[pointer], vaddr);
|
||||||
code.jne(ok);
|
code.jne(ok, code.T_NEAR);
|
||||||
code.mov(qword[pointer], tmp);
|
code.mov(qword[pointer], tmp);
|
||||||
code.L(ok);
|
code.L(ok);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,6 @@
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
|
||||||
|
|
||||||
using namespace Xbyak::util;
|
|
||||||
namespace mp = mcl::mp;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
#define FCODE(NAME) \
|
#define FCODE(NAME) \
|
||||||
[&code](auto... args) { \
|
[&code](auto... args) { \
|
||||||
if constexpr (fsize == 32) { \
|
if constexpr (fsize == 32) { \
|
||||||
|
@ -57,6 +50,13 @@ namespace {
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
|
using namespace Xbyak::util;
|
||||||
|
namespace mp = mcl::mp;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
template<typename Lambda>
|
template<typename Lambda>
|
||||||
void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) {
|
void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) {
|
||||||
const bool switch_mxcsr = ctx.FPCR(fpcr_controlled) != ctx.FPCR();
|
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];
|
const Xbyak::Xmm result = xmms[0];
|
||||||
|
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
|
|
||||||
const size_t stack_space = xmms.size() * 16;
|
const size_t stack_space = xmms.size() * 16;
|
||||||
code.sub(rsp, static_cast<u32>(stack_space + ABI_SHADOW_SPACE));
|
code.lea(rsp, ptr[rsp - static_cast<u32>(stack_space + ABI_SHADOW_SPACE)]);
|
||||||
for (size_t i = 0; i < xmms.size(); ++i) {
|
for (size_t i = 0; i < xmms.size(); ++i) {
|
||||||
code.movaps(xword[rsp + ABI_SHADOW_SPACE + i * 16], xmms[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();
|
const u32 fpcr = ctx.FPCR(fpcr_controlled).Value();
|
||||||
|
|
||||||
constexpr u32 stack_space = 2 * 16;
|
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_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||||
code.mov(code.ABI_PARAM3.cvt32(), fpcr);
|
code.mov(code.ABI_PARAM3.cvt32(), fpcr);
|
||||||
|
@ -479,7 +479,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
constexpr u32 stack_space = 4 * 16;
|
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_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 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]);
|
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);
|
code.mov(qword[rsp + ABI_SHADOW_SPACE + 0], rax);
|
||||||
#else
|
#else
|
||||||
constexpr u32 stack_space = 3 * 16;
|
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_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 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]);
|
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
|
#ifdef _WIN32
|
||||||
constexpr u32 stack_space = 5 * 16;
|
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_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 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]);
|
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);
|
code.mov(qword[rsp + ABI_SHADOW_SPACE + 8], rax);
|
||||||
#else
|
#else
|
||||||
constexpr u32 stack_space = 4 * 16;
|
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_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 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]);
|
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] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*fallback);
|
code.L(*fallback);
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
if (needs_rounding_correction && needs_nan_correction) {
|
if (needs_rounding_correction && needs_nan_correction) {
|
||||||
EmitFourOpFallbackWithoutRegAlloc<LoadPreviousResult::Yes>(code, ctx, result, xmm_a, xmm_b, xmm_c, EmitFPVectorMulAddFallback<FPT, true, true>, fpcr_controlled);
|
EmitFourOpFallbackWithoutRegAlloc<LoadPreviousResult::Yes>(code, ctx, result, xmm_a, xmm_b, xmm_c, EmitFPVectorMulAddFallback<FPT, true, true>, fpcr_controlled);
|
||||||
|
@ -1635,7 +1635,7 @@ static void EmitRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
||||||
|
|
||||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*fallback);
|
code.L(*fallback);
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
||||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
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] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*bad_values);
|
code.L(*bad_values);
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
EmitTwoOpFallbackWithoutRegAlloc(code, ctx, result, operand, fallback_fn, fpcr_controlled);
|
EmitTwoOpFallbackWithoutRegAlloc(code, ctx, result, operand, fallback_fn, fpcr_controlled);
|
||||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
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] {
|
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||||
code.L(*fallback);
|
code.L(*fallback);
|
||||||
code.sub(rsp, 8);
|
code.lea(rsp, ptr[rsp - 8]);
|
||||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
||||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||||
|
@ -2180,3 +2180,6 @@ void EmitX64::EmitFPVectorToUnsignedFixed64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::X64
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
||||||
|
#undef FCODE
|
||||||
|
#undef ICODE
|
||||||
|
|
|
@ -338,3 +338,6 @@ void EmitX64::EmitVectorUnsignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::X64
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
||||||
|
#undef FCODE
|
||||||
|
#undef ICODE
|
||||||
|
|
|
@ -186,7 +186,7 @@ struct ExceptionHandler::Impl final {
|
||||||
code.cmp(code.rax, static_cast<u32>(code.GetTotalCodeSize()));
|
code.cmp(code.rax, static_cast<u32>(code.GetTotalCodeSize()));
|
||||||
code.ja(exception_handler_without_cb);
|
code.ja(exception_handler_without_cb);
|
||||||
|
|
||||||
code.sub(code.rsp, 8);
|
code.lea(code.rsp, ptr[code.rsp - 8]);
|
||||||
code.mov(code.ABI_PARAM1, mcl::bit_cast<u64>(&cb));
|
code.mov(code.ABI_PARAM1, mcl::bit_cast<u64>(&cb));
|
||||||
code.mov(code.ABI_PARAM2, code.ABI_PARAM3);
|
code.mov(code.ABI_PARAM2, code.ABI_PARAM3);
|
||||||
code.CallLambda(
|
code.CallLambda(
|
||||||
|
|
|
@ -25,3 +25,51 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // 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"
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
bool TranslatorVisitor::arm_NOP() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::ArmConditionPassed(Cond cond) {
|
bool TranslatorVisitor::ArmConditionPassed(Cond cond) {
|
||||||
return IsConditionPassed(*this, cond);
|
return IsConditionPassed(*this, cond);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,7 @@ struct TranslatorVisitor final {
|
||||||
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
||||||
bool arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
|
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_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_RBIT(Cond cond, Reg d, Reg m);
|
||||||
bool arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
|
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);
|
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mcl/bit/bit_field.hpp>
|
#include <mcl/bit/bit_field.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -17,11 +18,6 @@ enum class Comparison {
|
||||||
AbsoluteGT,
|
AbsoluteGT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AccumulateBehavior {
|
|
||||||
None,
|
|
||||||
Accumulate,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class WidenBehaviour {
|
enum class WidenBehaviour {
|
||||||
Second,
|
Second,
|
||||||
Both,
|
Both,
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
#include <mcl/bit/bit_field.hpp>
|
#include <mcl/bit/bit_field.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
enum class Comparison {
|
enum class ComparisonATRM {
|
||||||
EQ,
|
EQ,
|
||||||
GE,
|
GE,
|
||||||
GT,
|
GT,
|
||||||
|
@ -19,7 +20,7 @@ enum class Comparison {
|
||||||
LT,
|
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)) {
|
if (sz == 0b11 || (F && sz != 0b10)) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -36,15 +37,15 @@ bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F,
|
||||||
|
|
||||||
if (F) {
|
if (F) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Comparison::EQ:
|
case ComparisonATRM::EQ:
|
||||||
return v.ir.FPVectorEqual(32, reg_m, zero, false);
|
return v.ir.FPVectorEqual(32, reg_m, zero, false);
|
||||||
case Comparison::GE:
|
case ComparisonATRM::GE:
|
||||||
return v.ir.FPVectorGreaterEqual(32, reg_m, zero, false);
|
return v.ir.FPVectorGreaterEqual(32, reg_m, zero, false);
|
||||||
case Comparison::GT:
|
case ComparisonATRM::GT:
|
||||||
return v.ir.FPVectorGreater(32, reg_m, zero, false);
|
return v.ir.FPVectorGreater(32, reg_m, zero, false);
|
||||||
case Comparison::LE:
|
case ComparisonATRM::LE:
|
||||||
return v.ir.FPVectorGreaterEqual(32, zero, reg_m, false);
|
return v.ir.FPVectorGreaterEqual(32, zero, reg_m, false);
|
||||||
case Comparison::LT:
|
case ComparisonATRM::LT:
|
||||||
return v.ir.FPVectorGreater(32, zero, reg_m, false);
|
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;
|
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) {
|
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) {
|
if (sz == 0b11) {
|
||||||
return v.UndefinedInstruction();
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::asimd_VABS(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ enum class Accumulating {
|
||||||
Accumulate
|
Accumulate
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Rounding {
|
enum class RoundingATRS {
|
||||||
None,
|
None,
|
||||||
Round,
|
Round,
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ enum class Signedness {
|
||||||
Unsigned
|
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_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);
|
const auto round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(original, round_const), round_const);
|
||||||
return v.ir.VectorSub(esize, shifted, round_correction);
|
return v.ir.VectorSub(esize, shifted, round_correction);
|
||||||
|
@ -58,7 +58,7 @@ std::pair<size_t, size_t> ElementSizeAndShiftAmount(bool right_shift, bool L, si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm, Accumulating accumulate, Rounding rounding) {
|
bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm, Accumulating accumulate, RoundingATRS RoundingATRS) {
|
||||||
if (!L && mcl::bit::get_bits<3, 5>(imm6) == 0) {
|
if (!L && mcl::bit::get_bits<3, 5>(imm6) == 0) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,9 @@ bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bo
|
||||||
auto result = U ? v.ir.VectorLogicalShiftRight(esize, reg_m, static_cast<u8>(shift_amount))
|
auto result = U ? v.ir.VectorLogicalShiftRight(esize, reg_m, static_cast<u8>(shift_amount))
|
||||||
: v.ir.VectorArithmeticShiftRight(esize, reg_m, static_cast<u8>(shift_amount));
|
: v.ir.VectorArithmeticShiftRight(esize, reg_m, static_cast<u8>(shift_amount));
|
||||||
|
|
||||||
if (rounding == Rounding::Round) {
|
if (RoundingATRS == RoundingATRS::Round) {
|
||||||
const u64 round_value = 1ULL << (shift_amount - 1);
|
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) {
|
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;
|
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) {
|
if (mcl::bit::get_bits<3, 5>(imm6) == 0) {
|
||||||
return v.DecodeError();
|
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);
|
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);
|
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 = [&] {
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
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,
|
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) {
|
bool TranslatorVisitor::asimd_VSHLL(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm) {
|
||||||
|
|
31
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h
vendored
Normal file
31
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/common.h
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
static inline IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) noexcept {
|
||||||
|
return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) noexcept {
|
||||||
|
return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) noexcept {
|
||||||
|
const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
|
||||||
|
return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool ITBlockCheck(const A32::IREmitter& ir) noexcept {
|
||||||
|
return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
using ExtensionFunctionU16 = IR::U32 (IREmitter::*)(const IR::U16&);
|
||||||
|
|
||||||
|
enum class AccumulateBehavior {
|
||||||
|
None,
|
||||||
|
Accumulate,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -4,14 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
static IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
|
|
||||||
const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
|
|
||||||
return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
|
// SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
|
||||||
bool TranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
bool TranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||||
if (d == Reg::PC || m == Reg::PC) {
|
if (d == Reg::PC || m == Reg::PC) {
|
||||||
|
|
|
@ -4,17 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
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
|
// Saturation instructions
|
||||||
|
|
||||||
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
|
// SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
|
||||||
|
|
|
@ -7,15 +7,9 @@
|
||||||
#include <mcl/bitsizeof.hpp>
|
#include <mcl/bitsizeof.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
|
||||||
return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 value) {
|
|
||||||
return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result);
|
|
||||||
}
|
|
||||||
|
|
||||||
using SaturationFunction = IR::ResultAndOverflow<IR::U32> (IREmitter::*)(const IR::U32&, size_t);
|
using SaturationFunction = IR::ResultAndOverflow<IR::U32> (IREmitter::*)(const IR::U32&, size_t);
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
|
|
||||||
const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
|
|
||||||
return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
|
|
||||||
}
|
|
||||||
|
|
||||||
using ShiftFunction = IR::ResultAndCarry<IR::U32> (IREmitter::*)(const IR::U32&, const IR::U8&, const IR::U1&);
|
using ShiftFunction = IR::ResultAndCarry<IR::U32> (IREmitter::*)(const IR::U32&, const IR::U8&, const IR::U1&);
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ static bool PLIHandler(TranslatorVisitor& v) {
|
||||||
return v.RaiseException(Exception::PreloadInstruction);
|
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 imm32 = imm12.ZeroExtend();
|
||||||
const u32 base = v.ir.AlignPC(4);
|
const u32 base = v.ir.AlignPC(4);
|
||||||
const u32 address = U ? (base + imm32) : (base - imm32);
|
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;
|
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) {
|
if (m == Reg::PC) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
|
||||||
return true;
|
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 u32 imm32 = imm12.ZeroExtend();
|
||||||
const IR::U32 reg_n = v.ir.GetRegister(n);
|
const IR::U32 reg_n = v.ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U16&);
|
static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunctionU16 ext_fn) {
|
||||||
|
|
||||||
static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunction ext_fn) {
|
|
||||||
const auto imm32 = imm12.ZeroExtend();
|
const auto imm32 = imm12.ZeroExtend();
|
||||||
const auto base = v.ir.AlignPC(4);
|
const auto base = v.ir.AlignPC(4);
|
||||||
const auto address = U ? (base + imm32) : (base - imm32);
|
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;
|
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) {
|
if (m == Reg::PC) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -34,7 +33,7 @@ static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
|
||||||
return true;
|
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 u32 imm32 = imm12.ZeroExtend();
|
||||||
const IR::U32 reg_n = v.ir.GetRegister(n);
|
const IR::U32 reg_n = v.ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
#include <mcl/bit/bit_field.hpp>
|
#include <mcl/bit/bit_field.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
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) {
|
static bool TableBranch(TranslatorVisitor& v, Reg n, Reg m, bool half) {
|
||||||
if (m == Reg::PC) {
|
if (m == Reg::PC) {
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
#include <mcl/bit/bit_count.hpp>
|
#include <mcl/bit/bit_count.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
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) {
|
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;
|
auto address = start_address;
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
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) {
|
bool TranslatorVisitor::thumb32_LDR_lit(bool U, Reg t, Imm<12> imm12) {
|
||||||
if (t == Reg::PC && ITBlockCheck(ir)) {
|
if (t == Reg::PC && ITBlockCheck(ir)) {
|
||||||
|
|
|
@ -4,15 +4,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/common.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
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) {
|
bool TranslatorVisitor::thumb32_SADD8(Reg n, Reg d, Reg m) {
|
||||||
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
|
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
|
||||||
|
|
|
@ -5,261 +5,7 @@
|
||||||
|
|
||||||
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
|
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
|
||||||
|
|
||||||
#include <mcl/assert.hpp>
|
|
||||||
|
|
||||||
#include "dynarmic/ir/opcodes.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
using Opcode = IR::Opcode;
|
|
||||||
|
|
||||||
u64 IREmitter::PC() const {
|
|
||||||
return current_location->PC();
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 IREmitter::AlignPC(size_t alignment) const {
|
|
||||||
const u64 pc = PC();
|
|
||||||
return static_cast<u64>(pc - pc % alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetCheckBit(const IR::U1& value) {
|
|
||||||
Inst(Opcode::A64SetCheckBit, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U1 IREmitter::GetCFlag() {
|
|
||||||
return Inst<IR::U1>(Opcode::A64GetCFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetNZCVRaw() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetNZCVRaw(IR::U32 value) {
|
|
||||||
Inst(Opcode::A64SetNZCVRaw, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
|
|
||||||
Inst(Opcode::A64SetNZCV, nzcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::CallSupervisor(u32 imm) {
|
|
||||||
Inst(Opcode::A64CallSupervisor, Imm32(imm));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::ExceptionRaised(Exception exception) {
|
|
||||||
Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) {
|
|
||||||
Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast<u64>(op)), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) {
|
|
||||||
Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::DataSynchronizationBarrier() {
|
|
||||||
Inst(Opcode::A64DataSynchronizationBarrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::DataMemoryBarrier() {
|
|
||||||
Inst(Opcode::A64DataMemoryBarrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::InstructionSynchronizationBarrier() {
|
|
||||||
Inst(Opcode::A64InstructionSynchronizationBarrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetCNTFRQ() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetCNTFRQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::GetCNTPCT() {
|
|
||||||
return Inst<IR::U64>(Opcode::A64GetCNTPCT);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetCTR() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetCTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetDCZID() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetDCZID);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::GetTPIDR() {
|
|
||||||
return Inst<IR::U64>(Opcode::A64GetTPIDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetTPIDR(const IR::U64& value) {
|
|
||||||
Inst(Opcode::A64SetTPIDR, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::GetTPIDRRO() {
|
|
||||||
return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::ClearExclusive() {
|
|
||||||
Inst(Opcode::A64ClearExclusive);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U8>(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U16>(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U64>(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U128>(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U8>(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U16>(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U64>(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U128>(Opcode::A64ExclusiveReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) {
|
|
||||||
Inst(Opcode::A64WriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) {
|
|
||||||
Inst(Opcode::A64WriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) {
|
|
||||||
Inst(Opcode::A64WriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) {
|
|
||||||
Inst(Opcode::A64WriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) {
|
|
||||||
Inst(Opcode::A64WriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) {
|
|
||||||
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetW(Reg reg) {
|
|
||||||
if (reg == Reg::ZR)
|
|
||||||
return Imm32(0);
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::GetX(Reg reg) {
|
|
||||||
if (reg == Reg::ZR)
|
|
||||||
return Imm64(0);
|
|
||||||
return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U128 IREmitter::GetS(Vec vec) {
|
|
||||||
return Inst<IR::U128>(Opcode::A64GetS, IR::Value(vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U128 IREmitter::GetD(Vec vec) {
|
|
||||||
return Inst<IR::U128>(Opcode::A64GetD, IR::Value(vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U128 IREmitter::GetQ(Vec vec) {
|
|
||||||
return Inst<IR::U128>(Opcode::A64GetQ, IR::Value(vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::GetSP() {
|
|
||||||
return Inst<IR::U64>(Opcode::A64GetSP);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetFPCR() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetFPCR);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 IREmitter::GetFPSR() {
|
|
||||||
return Inst<IR::U32>(Opcode::A64GetFPSR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetW(const Reg reg, const IR::U32& value) {
|
|
||||||
if (reg == Reg::ZR)
|
|
||||||
return;
|
|
||||||
Inst(Opcode::A64SetW, IR::Value(reg), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetX(const Reg reg, const IR::U64& value) {
|
|
||||||
if (reg == Reg::ZR)
|
|
||||||
return;
|
|
||||||
Inst(Opcode::A64SetX, IR::Value(reg), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetS(const Vec vec, const IR::U128& value) {
|
|
||||||
Inst(Opcode::A64SetS, IR::Value(vec), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetD(const Vec vec, const IR::U128& value) {
|
|
||||||
Inst(Opcode::A64SetD, IR::Value(vec), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetQ(const Vec vec, const IR::U128& value) {
|
|
||||||
Inst(Opcode::A64SetQ, IR::Value(vec), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetSP(const IR::U64& value) {
|
|
||||||
Inst(Opcode::A64SetSP, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetFPCR(const IR::U32& value) {
|
|
||||||
Inst(Opcode::A64SetFPCR, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetFPSR(const IR::U32& value) {
|
|
||||||
Inst(Opcode::A64SetFPSR, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetPC(const IR::U64& value) {
|
|
||||||
Inst(Opcode::A64SetPC, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U64 IREmitter::ImmCurrentLocationDescriptor() {
|
|
||||||
return Imm64(IR::LocationDescriptor{*current_location}.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include <mcl/stdint.hpp>
|
#include <mcl/stdint.hpp>
|
||||||
|
#include <mcl/assert.hpp>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/a64_types.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/interface/A64/config.h"
|
#include "dynarmic/interface/A64/config.h"
|
||||||
#include "dynarmic/ir/ir_emitter.h"
|
#include "dynarmic/ir/ir_emitter.h"
|
||||||
#include "dynarmic/ir/value.h"
|
#include "dynarmic/ir/value.h"
|
||||||
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
@ -24,79 +26,262 @@ namespace Dynarmic::A64 {
|
||||||
*/
|
*/
|
||||||
class IREmitter : public IR::IREmitter {
|
class IREmitter : public IR::IREmitter {
|
||||||
public:
|
public:
|
||||||
explicit IREmitter(IR::Block& block)
|
explicit IREmitter(IR::Block& block) : IR::IREmitter(block) {}
|
||||||
: IR::IREmitter(block) {}
|
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {}
|
||||||
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor)
|
|
||||||
: IR::IREmitter(block), current_location(descriptor) {}
|
|
||||||
|
|
||||||
std::optional<LocationDescriptor> current_location;
|
std::optional<LocationDescriptor> current_location;
|
||||||
|
|
||||||
u64 PC() const;
|
using Opcode = IR::Opcode;
|
||||||
u64 AlignPC(size_t alignment) const;
|
|
||||||
|
|
||||||
void SetCheckBit(const IR::U1& value);
|
u64 PC() const noexcept {
|
||||||
IR::U1 GetCFlag();
|
return current_location->PC();
|
||||||
IR::U32 GetNZCVRaw();
|
}
|
||||||
void SetNZCVRaw(IR::U32 value);
|
|
||||||
void SetNZCV(const IR::NZCV& nzcv);
|
|
||||||
|
|
||||||
void CallSupervisor(u32 imm);
|
u64 AlignPC(size_t alignment) const noexcept {
|
||||||
void ExceptionRaised(Exception exception);
|
const u64 pc = PC();
|
||||||
void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value);
|
return static_cast<u64>(pc - pc % alignment);
|
||||||
void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value);
|
}
|
||||||
void DataSynchronizationBarrier();
|
|
||||||
void DataMemoryBarrier();
|
|
||||||
void InstructionSynchronizationBarrier();
|
|
||||||
IR::U32 GetCNTFRQ();
|
|
||||||
IR::U64 GetCNTPCT(); // TODO: Ensure sub-basic-block cycle counts are updated before this.
|
|
||||||
IR::U32 GetCTR();
|
|
||||||
IR::U32 GetDCZID();
|
|
||||||
IR::U64 GetTPIDR();
|
|
||||||
IR::U64 GetTPIDRRO();
|
|
||||||
void SetTPIDR(const IR::U64& value);
|
|
||||||
|
|
||||||
void ClearExclusive();
|
void SetCheckBit(const IR::U1& value) noexcept {
|
||||||
IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type);
|
Inst(Opcode::A64SetCheckBit, value);
|
||||||
IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type);
|
}
|
||||||
IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type);
|
|
||||||
void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type);
|
|
||||||
void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type);
|
|
||||||
void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type);
|
|
||||||
void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type);
|
|
||||||
void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type);
|
|
||||||
IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type);
|
|
||||||
|
|
||||||
IR::U32 GetW(Reg source_reg);
|
IR::U1 GetCFlag() noexcept {
|
||||||
IR::U64 GetX(Reg source_reg);
|
return Inst<IR::U1>(Opcode::A64GetCFlag);
|
||||||
IR::U128 GetS(Vec source_vec);
|
}
|
||||||
IR::U128 GetD(Vec source_vec);
|
|
||||||
IR::U128 GetQ(Vec source_vec);
|
IR::U32 GetNZCVRaw() noexcept {
|
||||||
IR::U64 GetSP();
|
return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
|
||||||
IR::U32 GetFPCR();
|
}
|
||||||
IR::U32 GetFPSR();
|
|
||||||
void SetW(Reg dest_reg, const IR::U32& value);
|
void SetNZCVRaw(IR::U32 value) noexcept {
|
||||||
void SetX(Reg dest_reg, const IR::U64& value);
|
Inst(Opcode::A64SetNZCVRaw, 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 SetNZCV(const IR::NZCV& nzcv) noexcept {
|
||||||
void SetSP(const IR::U64& value);
|
Inst(Opcode::A64SetNZCV, nzcv);
|
||||||
void SetFPCR(const IR::U32& value);
|
}
|
||||||
void SetFPSR(const IR::U32& value);
|
|
||||||
void SetPC(const IR::U64& value);
|
void CallSupervisor(u32 imm) noexcept {
|
||||||
|
Inst(Opcode::A64CallSupervisor, Imm32(imm));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExceptionRaised(Exception exception) noexcept {
|
||||||
|
Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) noexcept {
|
||||||
|
Inst(Opcode::A64DataCacheOperationRaised, ImmCurrentLocationDescriptor(), Imm64(static_cast<u64>(op)), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) noexcept {
|
||||||
|
Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataSynchronizationBarrier() noexcept {
|
||||||
|
Inst(Opcode::A64DataSynchronizationBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataMemoryBarrier() noexcept {
|
||||||
|
Inst(Opcode::A64DataMemoryBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSynchronizationBarrier() noexcept {
|
||||||
|
Inst(Opcode::A64InstructionSynchronizationBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetCNTFRQ() noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetCNTFRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 GetCNTPCT() noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetCNTPCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetCTR() noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetCTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetDCZID() noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetDCZID);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 GetTPIDR() noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetTPIDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTPIDR(const IR::U64& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetTPIDR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 GetTPIDRRO() noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearExclusive() noexcept {
|
||||||
|
Inst(Opcode::A64ClearExclusive);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U8 ReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U8>(Opcode::A64ReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 ReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U16>(Opcode::A64ReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 ReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64ReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 ReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U128>(Opcode::A64ReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U8>(Opcode::A64ExclusiveReadMemory8, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U16>(Opcode::A64ExclusiveReadMemory16, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveReadMemory32, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64ExclusiveReadMemory64, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U128>(Opcode::A64ExclusiveReadMemory128, ImmCurrentLocationDescriptor(), vaddr, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) noexcept {
|
||||||
|
Inst(Opcode::A64WriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) noexcept {
|
||||||
|
Inst(Opcode::A64WriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) noexcept {
|
||||||
|
Inst(Opcode::A64WriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) noexcept {
|
||||||
|
Inst(Opcode::A64WriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) noexcept {
|
||||||
|
Inst(Opcode::A64WriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory8, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory16, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory32, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory64, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value, IR::AccType acc_type) noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory128, ImmCurrentLocationDescriptor(), vaddr, value, IR::Value{acc_type});
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetW(Reg reg) noexcept {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return Imm32(0);
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 GetX(Reg reg) noexcept {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return Imm64(0);
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 GetS(Vec vec) noexcept {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetS, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 GetD(Vec vec) noexcept {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetD, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 GetQ(Vec vec) noexcept {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetQ, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 GetSP() noexcept {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetFPCR() noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetFPCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 GetFPSR() noexcept {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetFPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetW(const Reg reg, const IR::U32& value) noexcept {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return;
|
||||||
|
Inst(Opcode::A64SetW, IR::Value(reg), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetX(const Reg reg, const IR::U64& value) noexcept {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return;
|
||||||
|
Inst(Opcode::A64SetX, IR::Value(reg), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetS(const Vec vec, const IR::U128& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetS, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetD(const Vec vec, const IR::U128& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetD, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetQ(const Vec vec, const IR::U128& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetQ, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSP(const IR::U64& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetSP, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFPCR(const IR::U32& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetFPCR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFPSR(const IR::U32& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetFPSR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPC(const IR::U64& value) noexcept {
|
||||||
|
Inst(Opcode::A64SetPC, value);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IR::U64 ImmCurrentLocationDescriptor();
|
IR::U64 ImmCurrentLocationDescriptor() noexcept {
|
||||||
|
return Imm64(IR::LocationDescriptor{*current_location}.Value());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -67,3 +67,64 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // 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"
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
namespace {
|
namespace {
|
||||||
enum class MinMaxOperation {
|
enum class MinMaxOperationSSPW {
|
||||||
Max,
|
Max,
|
||||||
MaxNumeric,
|
MaxNumeric,
|
||||||
Min,
|
Min,
|
||||||
MinNumeric,
|
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 size_t esize = sz ? 64 : 32;
|
||||||
|
|
||||||
const IR::U128 operand = v.V(128, Vn);
|
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 element2 = v.ir.VectorGetElement(esize, operand, 1);
|
||||||
const IR::U32U64 result = [&] {
|
const IR::U32U64 result = [&] {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MinMaxOperation::Max:
|
case MinMaxOperationSSPW::Max:
|
||||||
return v.ir.FPMax(element1, element2);
|
return v.ir.FPMax(element1, element2);
|
||||||
case MinMaxOperation::MaxNumeric:
|
case MinMaxOperationSSPW::MaxNumeric:
|
||||||
return v.ir.FPMaxNumeric(element1, element2);
|
return v.ir.FPMaxNumeric(element1, element2);
|
||||||
case MinMaxOperation::Min:
|
case MinMaxOperationSSPW::Min:
|
||||||
return v.ir.FPMin(element1, element2);
|
return v.ir.FPMin(element1, element2);
|
||||||
case MinMaxOperation::MinNumeric:
|
case MinMaxOperationSSPW::MinNumeric:
|
||||||
return v.ir.FPMinNumeric(element1, element2);
|
return v.ir.FPMinNumeric(element1, element2);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
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) {
|
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) {
|
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) {
|
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) {
|
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
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -27,7 +27,7 @@ enum class ShiftExtraBehavior {
|
||||||
Accumulate,
|
Accumulate,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSSSBI {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned,
|
Unsigned,
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,7 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
|
||||||
return true;
|
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>()) {
|
if (!immh.Bit<3>()) {
|
||||||
return v.ReservedValue();
|
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);
|
const IR::U64 operand = v.V_scalar(esize, Vn);
|
||||||
IR::U64 result = [&]() -> IR::U64 {
|
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.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount));
|
||||||
}
|
}
|
||||||
return v.ir.LogicalShiftRight(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;
|
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>()) {
|
if (!immh.Bit<3>()) {
|
||||||
return v.ReservedValue();
|
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 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 result = [&] {
|
||||||
const IR::U64 shifted = [&]() -> IR::U64 {
|
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.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount));
|
||||||
}
|
}
|
||||||
return v.ir.LogicalShiftRight(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;
|
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) {
|
if (immh == 0b0000) {
|
||||||
return v.ReservedValue();
|
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));
|
const IR::U128 operand = v.ir.ZeroExtendToQuad(v.ir.VectorGetElement(source_esize, v.V(128, Vn), 0));
|
||||||
|
|
||||||
IR::U128 wide_result = [&] {
|
IR::U128 wide_result = [&] {
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSSBI == SignednessSSSBI::Signed) {
|
||||||
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
|
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
|
||||||
}
|
}
|
||||||
return v.ir.VectorLogicalShiftRight(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:
|
case Narrowing::Truncation:
|
||||||
return v.ir.VectorNarrow(source_esize, wide_result);
|
return v.ir.VectorNarrow(source_esize, wide_result);
|
||||||
case Narrowing::SaturateToUnsigned:
|
case Narrowing::SaturateToUnsigned:
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSSBI == SignednessSSSBI::Signed) {
|
||||||
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
|
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
|
||||||
}
|
}
|
||||||
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
|
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
|
||||||
case Narrowing::SaturateToSigned:
|
case Narrowing::SaturateToSigned:
|
||||||
ASSERT(signedness == Signedness::Signed);
|
ASSERT(SignednessSSSBI == SignednessSSSBI::Signed);
|
||||||
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
|
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -206,7 +206,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
|
||||||
return true;
|
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();
|
const u32 immh_value = immh.ZeroExtend();
|
||||||
|
|
||||||
if ((immh_value & 0b1110) == 0b0000) {
|
if ((immh_value & 0b1110) == 0b0000) {
|
||||||
|
@ -227,23 +227,23 @@ bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Ve
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case FloatConversionDirection::FloatToFixed:
|
case FloatConversionDirection::FloatToFixed:
|
||||||
if (esize == 64) {
|
if (esize == 64) {
|
||||||
return sign == Signedness::Signed
|
return sign == SignednessSSSBI::Signed
|
||||||
? v.ir.FPToFixedS64(operand, fbits, rounding_mode)
|
? v.ir.FPToFixedS64(operand, fbits, rounding_mode)
|
||||||
: v.ir.FPToFixedU64(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.FPToFixedS32(operand, fbits, rounding_mode)
|
||||||
: v.ir.FPToFixedU32(operand, fbits, rounding_mode);
|
: v.ir.FPToFixedU32(operand, fbits, rounding_mode);
|
||||||
|
|
||||||
case FloatConversionDirection::FixedToFloat:
|
case FloatConversionDirection::FixedToFloat:
|
||||||
if (esize == 64) {
|
if (esize == 64) {
|
||||||
return sign == Signedness::Signed
|
return sign == SignednessSSSBI::Signed
|
||||||
? v.ir.FPSignedFixedToDouble(operand, fbits, rounding_mode)
|
? v.ir.FPSignedFixedToDouble(operand, fbits, rounding_mode)
|
||||||
: v.ir.FPUnsignedFixedToDouble(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.FPSignedFixedToSingle(operand, fbits, rounding_mode)
|
||||||
: v.ir.FPUnsignedFixedToSingle(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
|
} // Anonymous namespace
|
||||||
|
|
||||||
bool TranslatorVisitor::FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -26,12 +26,12 @@ enum class ComparisonVariant {
|
||||||
Zero,
|
Zero,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSSTS {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned,
|
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) {
|
if (size != 0b11) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(64, Vn);
|
||||||
const IR::U128 operand2 = v.V(64, Vm);
|
const IR::U128 operand2 = v.V(64, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSSTS::Signed) {
|
||||||
return v.ir.VectorRoundingShiftLeftSigned(64, operand1, operand2);
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::USHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
namespace {
|
namespace {
|
||||||
enum class ComparisonType {
|
enum class ComparisonTypeSSTRM {
|
||||||
EQ,
|
EQ,
|
||||||
GE,
|
GE,
|
||||||
GT,
|
GT,
|
||||||
|
@ -15,12 +15,12 @@ enum class ComparisonType {
|
||||||
LT
|
LT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSSTRM {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
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 esize = sz ? 64 : 32;
|
||||||
const size_t datasize = esize;
|
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 zero = v.ir.ZeroVector();
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ComparisonType::EQ:
|
case ComparisonTypeSSTRM::EQ:
|
||||||
return v.ir.FPVectorEqual(esize, operand, zero);
|
return v.ir.FPVectorEqual(esize, operand, zero);
|
||||||
case ComparisonType::GE:
|
case ComparisonTypeSSTRM::GE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
|
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
|
||||||
case ComparisonType::GT:
|
case ComparisonTypeSSTRM::GT:
|
||||||
return v.ir.FPVectorGreater(esize, operand, zero);
|
return v.ir.FPVectorGreater(esize, operand, zero);
|
||||||
case ComparisonType::LE:
|
case ComparisonTypeSSTRM::LE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
|
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
|
||||||
case ComparisonType::LT:
|
case ComparisonTypeSSTRM::LT:
|
||||||
return v.ir.FPVectorGreater(esize, zero, operand);
|
return v.ir.FPVectorGreater(esize, zero, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +47,18 @@ bool ScalarFPCompareAgainstZero(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, C
|
||||||
return true;
|
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 size_t esize = sz ? 64 : 32;
|
||||||
|
|
||||||
const IR::U32U64 operand = v.V_scalar(esize, Vn);
|
const IR::U32U64 operand = v.V_scalar(esize, Vn);
|
||||||
const IR::U32U64 result = [&]() -> IR::U32U64 {
|
const IR::U32U64 result = [&]() -> IR::U32U64 {
|
||||||
if (sz) {
|
if (sz) {
|
||||||
return sign == Signedness::Signed
|
return sign == SignednessSSTRM::Signed
|
||||||
? v.ir.FPToFixedS64(operand, 0, rmode)
|
? v.ir.FPToFixedS64(operand, 0, rmode)
|
||||||
: v.ir.FPToFixedU64(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.FPToFixedS32(operand, 0, rmode)
|
||||||
: v.ir.FPToFixedU32(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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::FRECPE_1(Vec Vn, Vec Vd) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
namespace {
|
namespace {
|
||||||
std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
|
std::pair<size_t, Vec> CombineScalar(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
|
||||||
if (size == 0b01) {
|
if (size == 0b01) {
|
||||||
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
|
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const 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 operand1 = V_scalar(esize, Vn);
|
||||||
const IR::UAny operand2 = ir.VectorGetElement(esize, V(128, Vm), index);
|
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 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 operand1 = ir.ZeroExtendToQuad(ir.VectorGetElement(esize, V(128, Vn), 0));
|
||||||
const IR::U128 operand2 = V(128, Vm);
|
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 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 operand1 = ir.ZeroExtendToQuad(ir.VectorGetElement(esize, V(128, Vn), 0));
|
||||||
const IR::U128 operand2 = V(128, Vm);
|
const IR::U128 operand2 = V(128, Vm);
|
||||||
|
|
|
@ -20,24 +20,24 @@ enum class Accumulating {
|
||||||
Accumulate
|
Accumulate
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSSBI {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
Unsigned
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Narrowing {
|
enum class NarrowingSSBI {
|
||||||
Truncation,
|
Truncation,
|
||||||
SaturateToUnsigned,
|
SaturateToUnsigned,
|
||||||
SaturateToSigned,
|
SaturateToSigned,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SaturatingShiftLeftType {
|
enum class SaturatingShiftLeftTypeSSBI {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned,
|
Unsigned,
|
||||||
SignedWithUnsignedSaturation,
|
SignedWithUnsignedSaturation,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FloatConversionDirection {
|
enum class FloatConversionDirectionSSBI {
|
||||||
FixedToFloat,
|
FixedToFloat,
|
||||||
FloatToFixed,
|
FloatToFixed,
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,7 @@ IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round
|
||||||
return v.ir.VectorSub(esize, shifted, round_correction);
|
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) {
|
if (immh == 0b0000) {
|
||||||
return v.DecodeError();
|
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);
|
const IR::U128 operand = v.V(datasize, Vn);
|
||||||
|
|
||||||
IR::U128 result = [&] {
|
IR::U128 result = [&] {
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSBI == SignednessSSBI::Signed) {
|
||||||
return v.ir.VectorArithmeticShiftRight(esize, operand, shift_amount);
|
return v.ir.VectorArithmeticShiftRight(esize, operand, shift_amount);
|
||||||
}
|
}
|
||||||
return v.ir.VectorLogicalShiftRight(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;
|
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) {
|
if (immh == 0b0000) {
|
||||||
return v.DecodeError();
|
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);
|
const IR::U128 operand = v.V(128, Vn);
|
||||||
|
|
||||||
IR::U128 wide_result = [&] {
|
IR::U128 wide_result = [&] {
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSBI == SignednessSSBI::Signed) {
|
||||||
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
|
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
|
||||||
}
|
}
|
||||||
return v.ir.VectorLogicalShiftRight(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 = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (narrowing) {
|
switch (NarrowingSSBI) {
|
||||||
case Narrowing::Truncation:
|
case NarrowingSSBI::Truncation:
|
||||||
return v.ir.VectorNarrow(source_esize, wide_result);
|
return v.ir.VectorNarrow(source_esize, wide_result);
|
||||||
case Narrowing::SaturateToUnsigned:
|
case NarrowingSSBI::SaturateToUnsigned:
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSBI == SignednessSSBI::Signed) {
|
||||||
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
|
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
|
||||||
}
|
}
|
||||||
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
|
return v.ir.VectorUnsignedSaturatedNarrow(source_esize, wide_result);
|
||||||
case Narrowing::SaturateToSigned:
|
case NarrowingSSBI::SaturateToSigned:
|
||||||
ASSERT(signedness == Signedness::Signed);
|
ASSERT(SignednessSSBI == SignednessSSBI::Signed);
|
||||||
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
|
return v.ir.VectorSignedSaturatedNarrowToSigned(source_esize, wide_result);
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -134,7 +134,7 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
|
||||||
return true;
|
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) {
|
if (immh == 0b0000) {
|
||||||
return v.DecodeError();
|
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 operand = v.Vpart(datasize, Vn, part);
|
||||||
const IR::U128 expanded_operand = [&] {
|
const IR::U128 expanded_operand = [&] {
|
||||||
if (signedness == Signedness::Signed) {
|
if (SignednessSSBI == SignednessSSBI::Signed) {
|
||||||
return v.ir.VectorSignExtend(esize, operand);
|
return v.ir.VectorSignExtend(esize, operand);
|
||||||
}
|
}
|
||||||
return v.ir.VectorZeroExtend(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;
|
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>()) {
|
if (!Q && immh.Bit<3>()) {
|
||||||
return v.ReservedValue();
|
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 operand = v.V(datasize, Vn);
|
||||||
const IR::U128 shift_vec = v.ir.VectorBroadcast(esize, v.I(esize, shift));
|
const IR::U128 shift_vec = v.ir.VectorBroadcast(esize, v.I(esize, shift));
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (type == SaturatingShiftLeftType::Signed) {
|
if (type == SaturatingShiftLeftTypeSSBI::Signed) {
|
||||||
return v.ir.VectorSignedSaturatedShiftLeft(esize, operand, shift_vec);
|
return v.ir.VectorSignedSaturatedShiftLeft(esize, operand, shift_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == SaturatingShiftLeftType::Unsigned) {
|
if (type == SaturatingShiftLeftTypeSSBI::Unsigned) {
|
||||||
return v.ir.VectorUnsignedSaturatedShiftLeft(esize, operand, shift_vec);
|
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;
|
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) {
|
if (immh == 0b0000) {
|
||||||
return v.DecodeError();
|
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 operand = v.V(datasize, Vn);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case FloatConversionDirection::FixedToFloat:
|
case FloatConversionDirectionSSBI::FixedToFloat:
|
||||||
return signedness == Signedness::Signed
|
return SignednessSSBI == SignednessSSBI::Signed
|
||||||
? v.ir.FPVectorFromSignedFixed(esize, operand, fbits, rounding_mode)
|
? v.ir.FPVectorFromSignedFixed(esize, operand, fbits, rounding_mode)
|
||||||
: v.ir.FPVectorFromUnsignedFixed(esize, operand, fbits, rounding_mode);
|
: v.ir.FPVectorFromUnsignedFixed(esize, operand, fbits, rounding_mode);
|
||||||
case FloatConversionDirection::FloatToFixed:
|
case FloatConversionDirectionSSBI::FloatToFixed:
|
||||||
return signedness == Signedness::Signed
|
return SignednessSSBI == SignednessSSBI::Signed
|
||||||
? v.ir.FPVectorToSignedFixed(esize, operand, fbits, rounding_mode)
|
? v.ir.FPVectorToSignedFixed(esize, operand, fbits, rounding_mode)
|
||||||
: v.ir.FPVectorToUnsignedFixed(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
|
} // Anonymous namespace
|
||||||
|
|
||||||
bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -12,12 +12,12 @@ enum class AbsoluteDifferenceBehavior {
|
||||||
Accumulate
|
Accumulate
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSTD {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vn, Q));
|
||||||
const IR::U128 operand2 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vm, 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);
|
: v.ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2);
|
||||||
|
|
||||||
if (behavior == AbsoluteDifferenceBehavior::Accumulate) {
|
if (behavior == AbsoluteDifferenceBehavior::Accumulate) {
|
||||||
|
@ -45,7 +45,7 @@ enum class MultiplyLongBehavior {
|
||||||
Subtract
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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_n = v.Vpart(datasize, Vn, Q);
|
||||||
const auto reg_m = v.Vpart(datasize, Vm, 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.VectorMultiplySignedWiden(esize, reg_n, reg_m)
|
||||||
: v.ir.VectorMultiplyUnsignedWiden(esize, reg_n, reg_m);
|
: v.ir.VectorMultiplyUnsignedWiden(esize, reg_n, reg_m);
|
||||||
}();
|
}();
|
||||||
|
@ -81,7 +81,7 @@ enum class LongOperationBehavior {
|
||||||
Subtraction
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 auto get_operand = [&](Vec vec) {
|
||||||
const IR::U128 tmp = v.Vpart(64, vec, part);
|
const IR::U128 tmp = v.Vpart(64, vec, part);
|
||||||
|
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTD::Signed) {
|
||||||
return v.ir.VectorSignExtend(esize, tmp);
|
return v.ir.VectorSignExtend(esize, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ enum class WideOperationBehavior {
|
||||||
Subtraction
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 operand2 = [&] {
|
||||||
const IR::U128 tmp = v.Vpart(64, Vm, part);
|
const IR::U128 tmp = v.Vpart(64, Vm, part);
|
||||||
|
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTD::Signed) {
|
||||||
return v.ir.VectorSignExtend(esize, tmp);
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::SQDMULL_vec_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
|
||||||
|
|
|
@ -12,12 +12,12 @@ enum class Operation {
|
||||||
Subtract,
|
Subtract,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ExtraBehavior {
|
enum class ExtraBehaviorSTS {
|
||||||
None,
|
None,
|
||||||
Round
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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);
|
return v.ir.VectorSub(doubled_esize, operand1, operand2);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (behavior == ExtraBehavior::Round) {
|
if (behavior == ExtraBehaviorSTS::Round) {
|
||||||
const u64 round_const = 1ULL << (esize - 1);
|
const u64 round_const = 1ULL << (esize - 1);
|
||||||
const IR::U128 round_operand = v.ir.VectorBroadcast(doubled_esize, v.I(doubled_esize, round_const));
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class AbsDiffExtraBehavior {
|
enum class AbsDiffExtraBehaviorSTS {
|
||||||
None,
|
None,
|
||||||
Accumulate
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 result = [&] {
|
||||||
const IR::U128 tmp = v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2);
|
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);
|
const IR::U128 d = v.V(datasize, Vd);
|
||||||
return v.ir.VectorAdd(esize, d, tmp);
|
return v.ir.VectorAdd(esize, d, tmp);
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,12 @@ bool SignedAbsoluteDifference(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSTS {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(datasize, Vm);
|
||||||
const IR::U128 operand2 = v.V(datasize, Vn);
|
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.ir.VectorRoundingHalvingAddUnsigned(esize, operand1, operand2);
|
||||||
|
|
||||||
v.V(datasize, Vd, result);
|
v.V(datasize, Vd, result);
|
||||||
return true;
|
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) {
|
if (size == 0b11 && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(datasize, Vn);
|
||||||
const IR::U128 operand2 = v.V(datasize, Vm);
|
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return v.ir.VectorRoundingShiftLeftSigned(esize, operand1, operand2);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ComparisonType {
|
enum class ComparisonTypeSTS {
|
||||||
EQ,
|
EQ,
|
||||||
GE,
|
GE,
|
||||||
AbsoluteGE,
|
AbsoluteGE,
|
||||||
|
@ -130,7 +130,7 @@ enum class ComparisonType {
|
||||||
AbsoluteGT
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ComparisonType::EQ:
|
case ComparisonTypeSTS::EQ:
|
||||||
return v.ir.FPVectorEqual(esize, operand1, operand2);
|
return v.ir.FPVectorEqual(esize, operand1, operand2);
|
||||||
case ComparisonType::GE:
|
case ComparisonTypeSTS::GE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize, operand1, operand2);
|
return v.ir.FPVectorGreaterEqual(esize, operand1, operand2);
|
||||||
case ComparisonType::AbsoluteGE:
|
case ComparisonTypeSTS::AbsoluteGE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize,
|
return v.ir.FPVectorGreaterEqual(esize,
|
||||||
v.ir.FPVectorAbs(esize, operand1),
|
v.ir.FPVectorAbs(esize, operand1),
|
||||||
v.ir.FPVectorAbs(esize, operand2));
|
v.ir.FPVectorAbs(esize, operand2));
|
||||||
case ComparisonType::GT:
|
case ComparisonTypeSTS::GT:
|
||||||
return v.ir.FPVectorGreater(esize, operand1, operand2);
|
return v.ir.FPVectorGreater(esize, operand1, operand2);
|
||||||
case ComparisonType::AbsoluteGT:
|
case ComparisonTypeSTS::AbsoluteGT:
|
||||||
return v.ir.FPVectorGreater(esize,
|
return v.ir.FPVectorGreater(esize,
|
||||||
v.ir.FPVectorAbs(esize, operand1),
|
v.ir.FPVectorAbs(esize, operand1),
|
||||||
v.ir.FPVectorAbs(esize, operand2));
|
v.ir.FPVectorAbs(esize, operand2));
|
||||||
|
@ -165,12 +165,12 @@ bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class MinMaxOperation {
|
enum class MinMaxOperationSTS {
|
||||||
Min,
|
Min,
|
||||||
Max,
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MinMaxOperation::Max:
|
case MinMaxOperationSTS::Max:
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return v.ir.VectorMaxSigned(esize, operand1, operand2);
|
return v.ir.VectorMaxSigned(esize, operand1, operand2);
|
||||||
}
|
}
|
||||||
return v.ir.VectorMaxUnsigned(esize, operand1, operand2);
|
return v.ir.VectorMaxUnsigned(esize, operand1, operand2);
|
||||||
|
|
||||||
case MinMaxOperation::Min:
|
case MinMaxOperationSTS::Min:
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return v.ir.VectorMinSigned(esize, operand1, operand2);
|
return v.ir.VectorMinSigned(esize, operand1, operand2);
|
||||||
}
|
}
|
||||||
return v.ir.VectorMinUnsigned(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;
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(datasize, Vn);
|
||||||
const IR::U128 operand2 = v.V(datasize, Vm);
|
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (operation == MinMaxOperation::Min) {
|
if (operation == MinMaxOperationSTS::Min) {
|
||||||
return v.ir.FPVectorMin(esize, operand1, operand2);
|
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;
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(datasize, Vn);
|
||||||
const IR::U128 operand2 = v.V(datasize, Vm);
|
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (operation == MinMaxOperation::Min) {
|
if (operation == MinMaxOperationSTS::Min) {
|
||||||
return v.ir.FPVectorMinNumeric(esize, operand1, operand2);
|
return v.ir.FPVectorMinNumeric(esize, operand1, operand2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ bool FPMinMaxNumericOperation(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec
|
||||||
return true;
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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);
|
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||||
IR::U128 result = [&] {
|
IR::U128 result = [&] {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MinMaxOperation::Max:
|
case MinMaxOperationSTS::Max:
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return Q ? v.ir.VectorPairedMaxSigned(esize, operand1, operand2) : v.ir.VectorPairedMaxSignedLower(esize, operand1, operand2);
|
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);
|
return Q ? v.ir.VectorPairedMaxUnsigned(esize, operand1, operand2) : v.ir.VectorPairedMaxUnsignedLower(esize, operand1, operand2);
|
||||||
|
|
||||||
case MinMaxOperation::Min:
|
case MinMaxOperationSTS::Min:
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return Q ? v.ir.VectorPairedMinSigned(esize, operand1, operand2) : v.ir.VectorPairedMinSignedLower(esize, operand1, operand2);
|
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);
|
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;
|
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) {
|
if (size == 0b11 && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand2 = v.V(datasize, Vm);
|
||||||
|
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
if (op == Operation::Add) {
|
if (op == Operation::Add) {
|
||||||
return v.ir.VectorSignedSaturatedAdd(esize, operand1, operand2);
|
return v.ir.VectorSignedSaturatedAdd(esize, operand1, operand2);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ bool SaturatingArithmeticOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Ve
|
||||||
return true;
|
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) {
|
if (size == 0b11 && !Q) {
|
||||||
return v.ReservedValue();
|
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 operand1 = v.V(datasize, Vn);
|
||||||
const IR::U128 operand2 = v.V(datasize, Vm);
|
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTS::Signed) {
|
||||||
return v.ir.VectorSignedSaturatedShiftLeft(esize, operand1, operand2);
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::FMINNMP_vec_2(bool Q, bool sz, Vec Vm, Vec Vn, Vec Vd) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
namespace {
|
namespace {
|
||||||
enum class ComparisonType {
|
enum class ComparisonTypeSTRM {
|
||||||
EQ,
|
EQ,
|
||||||
GE,
|
GE,
|
||||||
GT,
|
GT,
|
||||||
|
@ -16,7 +16,7 @@ enum class ComparisonType {
|
||||||
LT,
|
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) {
|
if (size == 0b11 && !Q) {
|
||||||
return v.ReservedValue();
|
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();
|
const IR::U128 zero = v.ir.ZeroVector();
|
||||||
IR::U128 result = [&] {
|
IR::U128 result = [&] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ComparisonType::EQ:
|
case ComparisonTypeSTRM::EQ:
|
||||||
return v.ir.VectorEqual(esize, operand, zero);
|
return v.ir.VectorEqual(esize, operand, zero);
|
||||||
case ComparisonType::GE:
|
case ComparisonTypeSTRM::GE:
|
||||||
return v.ir.VectorGreaterEqualSigned(esize, operand, zero);
|
return v.ir.VectorGreaterEqualSigned(esize, operand, zero);
|
||||||
case ComparisonType::GT:
|
case ComparisonTypeSTRM::GT:
|
||||||
return v.ir.VectorGreaterSigned(esize, operand, zero);
|
return v.ir.VectorGreaterSigned(esize, operand, zero);
|
||||||
case ComparisonType::LE:
|
case ComparisonTypeSTRM::LE:
|
||||||
return v.ir.VectorLessEqualSigned(esize, operand, zero);
|
return v.ir.VectorLessEqualSigned(esize, operand, zero);
|
||||||
case ComparisonType::LT:
|
case ComparisonTypeSTRM::LT:
|
||||||
default:
|
default:
|
||||||
return v.ir.VectorLessSigned(esize, operand, zero);
|
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;
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 zero = v.ir.ZeroVector();
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ComparisonType::EQ:
|
case ComparisonTypeSTRM::EQ:
|
||||||
return v.ir.FPVectorEqual(esize, operand, zero);
|
return v.ir.FPVectorEqual(esize, operand, zero);
|
||||||
case ComparisonType::GE:
|
case ComparisonTypeSTRM::GE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
|
return v.ir.FPVectorGreaterEqual(esize, operand, zero);
|
||||||
case ComparisonType::GT:
|
case ComparisonTypeSTRM::GT:
|
||||||
return v.ir.FPVectorGreater(esize, operand, zero);
|
return v.ir.FPVectorGreater(esize, operand, zero);
|
||||||
case ComparisonType::LE:
|
case ComparisonTypeSTRM::LE:
|
||||||
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
|
return v.ir.FPVectorGreaterEqual(esize, zero, operand);
|
||||||
case ComparisonType::LT:
|
case ComparisonTypeSTRM::LT:
|
||||||
return v.ir.FPVectorGreater(esize, zero, operand);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSTRM {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 FP::RoundingMode rounding_mode = v.ir.current_location->FPCR().RMode();
|
||||||
|
|
||||||
const IR::U128 operand = v.V(datasize, Vn);
|
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.FPVectorFromSignedFixed(esize, operand, 0, rounding_mode)
|
||||||
: v.ir.FPVectorFromUnsignedFixed(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;
|
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) {
|
if (sz && !Q) {
|
||||||
return v.ReservedValue();
|
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 size_t esize = sz ? 64 : 32;
|
||||||
|
|
||||||
const IR::U128 operand = v.V(datasize, Vn);
|
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.FPVectorToSignedFixed(esize, operand, 0, rounding_mode)
|
||||||
: v.ir.FPVectorToUnsignedFixed(esize, operand, 0, rounding_mode);
|
: v.ir.FPVectorToUnsignedFixed(esize, operand, 0, rounding_mode);
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ enum class PairedAddLongExtraBehavior {
|
||||||
Accumulate,
|
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) {
|
if (size == 0b11) {
|
||||||
return v.ReservedValue();
|
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);
|
const IR::U128 operand = v.V(datasize, Vn);
|
||||||
IR::U128 result = [&] {
|
IR::U128 result = [&] {
|
||||||
if (sign == Signedness::Signed) {
|
if (sign == SignednessSTRM::Signed) {
|
||||||
return v.ir.VectorPairedAddSignedWiden(esize, operand);
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
bool TranslatorVisitor::SHLL(bool Q, Imm<2> size, Vec Vn, Vec Vd) {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
namespace {
|
namespace {
|
||||||
std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
|
std::pair<size_t, Vec> CombineVector(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4> Vmlo) {
|
||||||
if (size == 0b01) {
|
if (size == 0b01) {
|
||||||
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
|
return {concatenate(H, L, M).ZeroExtend(), Vmlo.ZeroExtend<Vec>()};
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,19 @@ std::pair<size_t, Vec> Combine(Imm<2> size, Imm<1> H, Imm<1> L, Imm<1> M, Imm<4>
|
||||||
return {concatenate(H, L).ZeroExtend(), concatenate(M, Vmlo).ZeroExtend<Vec>()};
|
return {concatenate(H, L).ZeroExtend(), concatenate(M, Vmlo).ZeroExtend<Vec>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ExtraBehavior {
|
enum class ExtraBehaviorSVXIE {
|
||||||
None,
|
None,
|
||||||
Extended,
|
Extended,
|
||||||
Accumulate,
|
Accumulate,
|
||||||
Subtract,
|
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) {
|
if (size != 0b01 && size != 0b10) {
|
||||||
return v.ReservedValue();
|
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 idxdsize = H == 1 ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const size_t esize = 8 << size.ZeroExtend();
|
||||||
const size_t datasize = Q ? 128 : 64;
|
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);
|
const IR::U128 operand3 = v.V(datasize, Vd);
|
||||||
|
|
||||||
IR::U128 result = v.ir.VectorMultiply(esize, operand1, operand2);
|
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);
|
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);
|
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;
|
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) {
|
if (sz && L == 1) {
|
||||||
return v.ReservedValue();
|
return v.ReservedValue();
|
||||||
}
|
}
|
||||||
|
@ -71,13 +71,13 @@ bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1>
|
||||||
|
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (extra_behavior) {
|
switch (extra_behavior) {
|
||||||
case ExtraBehavior::None:
|
case ExtraBehaviorSVXIE::None:
|
||||||
return v.ir.FPVectorMul(esize, operand1, operand2);
|
return v.ir.FPVectorMul(esize, operand1, operand2);
|
||||||
case ExtraBehavior::Extended:
|
case ExtraBehaviorSVXIE::Extended:
|
||||||
return v.ir.FPVectorMulX(esize, operand1, operand2);
|
return v.ir.FPVectorMulX(esize, operand1, operand2);
|
||||||
case ExtraBehavior::Accumulate:
|
case ExtraBehaviorSVXIE::Accumulate:
|
||||||
return v.ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
|
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);
|
return v.ir.FPVectorMulAdd(esize, operand3, v.ir.FPVectorNeg(esize, operand1), operand2);
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -86,7 +86,7 @@ bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1>
|
||||||
return true;
|
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 idxdsize = H == 1 ? 128 : 64;
|
||||||
const size_t index = concatenate(H, L, M).ZeroExtend();
|
const size_t index = concatenate(H, L, M).ZeroExtend();
|
||||||
const Vec Vm = Vmlo.ZeroExtend<Vec>();
|
const Vec Vm = Vmlo.ZeroExtend<Vec>();
|
||||||
|
@ -101,13 +101,13 @@ bool FPMultiplyByElementHalfPrecision(TranslatorVisitor& v, bool Q, Imm<1> L, Im
|
||||||
// regular multiplies and extended multiplies.
|
// regular multiplies and extended multiplies.
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (extra_behavior) {
|
switch (extra_behavior) {
|
||||||
case ExtraBehavior::None:
|
case ExtraBehaviorSVXIE::None:
|
||||||
break;
|
break;
|
||||||
case ExtraBehavior::Extended:
|
case ExtraBehaviorSVXIE::Extended:
|
||||||
break;
|
break;
|
||||||
case ExtraBehavior::Accumulate:
|
case ExtraBehaviorSVXIE::Accumulate:
|
||||||
return v.ir.FPVectorMulAdd(esize, operand3, operand1, operand2);
|
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);
|
return v.ir.FPVectorMulAdd(esize, operand3, v.ir.FPVectorNeg(esize, operand1), operand2);
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -151,12 +151,12 @@ bool DotProduct(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Signedness {
|
enum class SignednessSVXIE {
|
||||||
Signed,
|
Signed,
|
||||||
Unsigned
|
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) {
|
if (size == 0b00 || size == 0b11) {
|
||||||
return v.ReservedValue();
|
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 idxsize = H == 1 ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const size_t esize = 8 << size.ZeroExtend();
|
||||||
const size_t datasize = 64;
|
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 operand1 = v.Vpart(datasize, Vn, Q);
|
||||||
const IR::U128 operand2 = v.V(idxsize, Vm);
|
const IR::U128 operand2 = v.V(idxsize, Vm);
|
||||||
const IR::U128 index_vector = v.ir.VectorBroadcastElement(esize, operand2, index);
|
const IR::U128 index_vector = v.ir.VectorBroadcastElement(esize, operand2, index);
|
||||||
|
|
||||||
const IR::U128 result = [&] {
|
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.VectorMultiplySignedWiden(esize, operand1, index_vector)
|
||||||
: v.ir.VectorMultiplyUnsignedWiden(esize, operand1, index_vector);
|
: v.ir.VectorMultiplyUnsignedWiden(esize, operand1, index_vector);
|
||||||
|
|
||||||
if (extra_behavior == ExtraBehavior::None) {
|
if (extra_behavior == ExtraBehaviorSVXIE::None) {
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IR::U128 operand3 = v.V(2 * datasize, Vd);
|
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);
|
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
|
} // 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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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 idxsize = H == 1 ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const size_t esize = 8 << size.ZeroExtend();
|
||||||
const size_t datasize = 64;
|
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 operand1 = Vpart(datasize, Vn, part);
|
||||||
const IR::U128 operand2 = V(idxsize, Vm);
|
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 idxsize = H == 1 ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const size_t esize = 8 << size.ZeroExtend();
|
||||||
const size_t datasize = Q ? 128 : 64;
|
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 operand1 = V(datasize, Vn);
|
||||||
const IR::U128 operand2 = V(idxsize, Vm);
|
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 idxsize = H == 1 ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend();
|
const size_t esize = 8 << size.ZeroExtend();
|
||||||
const size_t datasize = Q ? 128 : 64;
|
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 operand1 = V(datasize, Vn);
|
||||||
const IR::U128 operand2 = V(idxsize, Vm);
|
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) {
|
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) {
|
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) {
|
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
|
} // namespace Dynarmic::A64
|
||||||
|
|
2872
externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp
vendored
2872
externals/dynarmic/src/dynarmic/ir/ir_emitter.cpp
vendored
File diff suppressed because it is too large
Load diff
3176
externals/dynarmic/src/dynarmic/ir/ir_emitter.h
vendored
3176
externals/dynarmic/src/dynarmic/ir/ir_emitter.h
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue