[dynarmic] lea over mov and other stuff (#24)
Co-authored-by: Esther1024 <danishreyjavik@outlook.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/24 Co-authored-by: Ghost <> Co-committed-by: Ghost <>
This commit is contained in:
parent
a0a208db57
commit
fe4f5a3860
54 changed files with 3894 additions and 4269 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -33,6 +33,7 @@ CMakeLists.txt.user*
|
|||
|
||||
# Visual Studio CMake settings
|
||||
CMakeSettings.json
|
||||
.cache/
|
||||
|
||||
# OSX global filetypes
|
||||
# Created by Finder or Spotlight in directories for various OS functionality (indexing, etc)
|
||||
|
|
|
|||
6
externals/dynarmic/CMakeLists.txt
vendored
6
externals/dynarmic/CMakeLists.txt
vendored
|
|
@ -98,8 +98,7 @@ else()
|
|||
-Wextra
|
||||
-Wcast-qual
|
||||
-pedantic
|
||||
-Wno-missing-braces
|
||||
-Wstack-usage=4096)
|
||||
-Wno-missing-braces)
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
list(APPEND DYNARMIC_CXX_FLAGS -mtune=core2)
|
||||
|
|
@ -123,12 +122,15 @@ else()
|
|||
# GCC knows that the variable is actually a Reg64. isMEM() will never return true for a
|
||||
# Reg64, but GCC doesn't know that.
|
||||
list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds)
|
||||
list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang")
|
||||
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
|
||||
# And this in turns limits the size of a std::array.
|
||||
list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024)
|
||||
# Clang mistakenly blames CMake for using unused arguments during compilation
|
||||
list(APPEND DYNARMIC_CXX_FLAGS -Wno-unused-command-line-argument)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
|||
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/conditional_state.cpp
|
||||
frontend/A32/translate/conditional_state.h
|
||||
frontend/A32/translate/impl/a32_branch.cpp
|
||||
frontend/A32/translate/impl/a32_crc32.cpp
|
||||
frontend/A32/translate/impl/a32_exception_generating.cpp
|
||||
frontend/A32/translate/impl/a32_translate_impl.cpp
|
||||
frontend/A32/translate/impl/a32_translate_impl.h
|
||||
frontend/A32/translate/impl/asimd_load_store_structures.cpp
|
||||
frontend/A32/translate/impl/asimd_misc.cpp
|
||||
frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
|
||||
frontend/A32/translate/impl/asimd_three_regs.cpp
|
||||
frontend/A32/translate/impl/asimd_two_regs_misc.cpp
|
||||
frontend/A32/translate/impl/asimd_two_regs_scalar.cpp
|
||||
frontend/A32/translate/impl/asimd_two_regs_shift.cpp
|
||||
frontend/A32/translate/impl/barrier.cpp
|
||||
frontend/A32/translate/impl/coprocessor.cpp
|
||||
frontend/A32/translate/impl/data_processing.cpp
|
||||
frontend/A32/translate/impl/divide.cpp
|
||||
frontend/A32/translate/impl/extension.cpp
|
||||
frontend/A32/translate/impl/hint.cpp
|
||||
frontend/A32/translate/impl/load_store.cpp
|
||||
frontend/A32/translate/impl/misc.cpp
|
||||
frontend/A32/translate/impl/multiply.cpp
|
||||
frontend/A32/translate/impl/packing.cpp
|
||||
frontend/A32/translate/impl/parallel.cpp
|
||||
frontend/A32/translate/impl/reversal.cpp
|
||||
frontend/A32/translate/impl/saturated.cpp
|
||||
frontend/A32/translate/impl/status_register_access.cpp
|
||||
frontend/A32/translate/impl/synchronization.cpp
|
||||
frontend/A32/translate/impl/thumb16.cpp
|
||||
frontend/A32/translate/impl/thumb32_branch.cpp
|
||||
frontend/A32/translate/impl/thumb32_control.cpp
|
||||
frontend/A32/translate/impl/thumb32_coprocessor.cpp
|
||||
frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
|
||||
frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
|
||||
frontend/A32/translate/impl/thumb32_data_processing_register.cpp
|
||||
frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp
|
||||
frontend/A32/translate/impl/thumb32_load_byte.cpp
|
||||
frontend/A32/translate/impl/thumb32_load_halfword.cpp
|
||||
frontend/A32/translate/impl/thumb32_load_store_dual.cpp
|
||||
frontend/A32/translate/impl/thumb32_load_store_multiple.cpp
|
||||
frontend/A32/translate/impl/thumb32_load_word.cpp
|
||||
frontend/A32/translate/impl/thumb32_long_multiply.cpp
|
||||
frontend/A32/translate/impl/thumb32_misc.cpp
|
||||
frontend/A32/translate/impl/thumb32_multiply.cpp
|
||||
frontend/A32/translate/impl/thumb32_parallel.cpp
|
||||
frontend/A32/translate/impl/thumb32_store_single_data_item.cpp
|
||||
frontend/A32/translate/impl/vfp.cpp
|
||||
frontend/A32/translate/translate_arm.cpp
|
||||
frontend/A32/translate/translate_thumb.cpp
|
||||
interface/A32/a32.h
|
||||
|
|
@ -194,65 +148,6 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
|||
frontend/A64/decoder/a64.inc
|
||||
frontend/A64/translate/a64_translate.cpp
|
||||
frontend/A64/translate/a64_translate.h
|
||||
frontend/A64/translate/impl/a64_branch.cpp
|
||||
frontend/A64/translate/impl/a64_exception_generating.cpp
|
||||
frontend/A64/translate/impl/data_processing_addsub.cpp
|
||||
frontend/A64/translate/impl/data_processing_bitfield.cpp
|
||||
frontend/A64/translate/impl/data_processing_conditional_compare.cpp
|
||||
frontend/A64/translate/impl/data_processing_conditional_select.cpp
|
||||
frontend/A64/translate/impl/data_processing_crc32.cpp
|
||||
frontend/A64/translate/impl/data_processing_logical.cpp
|
||||
frontend/A64/translate/impl/data_processing_multiply.cpp
|
||||
frontend/A64/translate/impl/data_processing_pcrel.cpp
|
||||
frontend/A64/translate/impl/data_processing_register.cpp
|
||||
frontend/A64/translate/impl/data_processing_shift.cpp
|
||||
frontend/A64/translate/impl/floating_point_compare.cpp
|
||||
frontend/A64/translate/impl/floating_point_conditional_compare.cpp
|
||||
frontend/A64/translate/impl/floating_point_conditional_select.cpp
|
||||
frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp
|
||||
frontend/A64/translate/impl/floating_point_conversion_integer.cpp
|
||||
frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp
|
||||
frontend/A64/translate/impl/floating_point_data_processing_three_register.cpp
|
||||
frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp
|
||||
frontend/A64/translate/impl/impl.cpp
|
||||
frontend/A64/translate/impl/impl.h
|
||||
frontend/A64/translate/impl/load_store_exclusive.cpp
|
||||
frontend/A64/translate/impl/load_store_load_literal.cpp
|
||||
frontend/A64/translate/impl/load_store_multiple_structures.cpp
|
||||
frontend/A64/translate/impl/load_store_no_allocate_pair.cpp
|
||||
frontend/A64/translate/impl/load_store_register_immediate.cpp
|
||||
frontend/A64/translate/impl/load_store_register_pair.cpp
|
||||
frontend/A64/translate/impl/load_store_register_register_offset.cpp
|
||||
frontend/A64/translate/impl/load_store_register_unprivileged.cpp
|
||||
frontend/A64/translate/impl/load_store_single_structure.cpp
|
||||
frontend/A64/translate/impl/move_wide.cpp
|
||||
frontend/A64/translate/impl/simd_across_lanes.cpp
|
||||
frontend/A64/translate/impl/simd_aes.cpp
|
||||
frontend/A64/translate/impl/simd_copy.cpp
|
||||
frontend/A64/translate/impl/simd_crypto_four_register.cpp
|
||||
frontend/A64/translate/impl/simd_crypto_three_register.cpp
|
||||
frontend/A64/translate/impl/simd_extract.cpp
|
||||
frontend/A64/translate/impl/simd_modified_immediate.cpp
|
||||
frontend/A64/translate/impl/simd_permute.cpp
|
||||
frontend/A64/translate/impl/simd_scalar_pairwise.cpp
|
||||
frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
|
||||
frontend/A64/translate/impl/simd_scalar_three_same.cpp
|
||||
frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
|
||||
frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
|
||||
frontend/A64/translate/impl/simd_sha.cpp
|
||||
frontend/A64/translate/impl/simd_sha512.cpp
|
||||
frontend/A64/translate/impl/simd_shift_by_immediate.cpp
|
||||
frontend/A64/translate/impl/simd_table_lookup.cpp
|
||||
frontend/A64/translate/impl/simd_three_different.cpp
|
||||
frontend/A64/translate/impl/simd_three_same.cpp
|
||||
frontend/A64/translate/impl/simd_three_same_extra.cpp
|
||||
frontend/A64/translate/impl/simd_two_register_misc.cpp
|
||||
frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
|
||||
frontend/A64/translate/impl/sys_dc.cpp
|
||||
frontend/A64/translate/impl/sys_ic.cpp
|
||||
frontend/A64/translate/impl/system.cpp
|
||||
frontend/A64/translate/impl/system_flag_format.cpp
|
||||
frontend/A64/translate/impl/system_flag_manipulation.cpp
|
||||
interface/A64/a64.h
|
||||
interface/A64/config.h
|
||||
ir/opt/a64_callback_config_pass.cpp
|
||||
|
|
|
|||
|
|
@ -59,13 +59,12 @@ constexpr RegisterList ToRegList(oaknut::Reg reg) {
|
|||
}
|
||||
|
||||
if (reg.index() == 31) {
|
||||
throw std::out_of_range("ZR not allowed in reg list");
|
||||
ASSERT_FALSE("ZR not allowed in reg list");
|
||||
}
|
||||
|
||||
if (reg.index() == -1) {
|
||||
return RegisterList{1} << 31;
|
||||
}
|
||||
|
||||
return RegisterList{1} << reg.index();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,29 +14,26 @@ namespace Dynarmic::Backend::RV64 {
|
|||
|
||||
class CodeBlock {
|
||||
public:
|
||||
explicit CodeBlock(std::size_t size)
|
||||
: memsize(size) {
|
||||
explicit CodeBlock(std::size_t size) noexcept : memsize(size) {
|
||||
mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (mem == nullptr)
|
||||
throw std::bad_alloc{};
|
||||
ASSERT_FALSE("out of memory");
|
||||
}
|
||||
|
||||
~CodeBlock() {
|
||||
~CodeBlock() noexcept {
|
||||
if (mem == nullptr)
|
||||
return;
|
||||
|
||||
munmap(mem, memsize);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T ptr() const {
|
||||
T ptr() const noexcept {
|
||||
static_assert(std::is_pointer_v<T> || std::is_same_v<T, uptr> || std::is_same_v<T, sptr>);
|
||||
return reinterpret_cast<T>(mem);
|
||||
}
|
||||
|
||||
protected:
|
||||
u8* mem;
|
||||
u8* mem = nullptr;
|
||||
size_t memsize = 0;
|
||||
};
|
||||
} // namespace Dynarmic::Backend::RV64
|
||||
|
|
|
|||
|
|
@ -124,35 +124,36 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
|||
|
||||
EmitCondPrelude(ctx);
|
||||
|
||||
for (auto iter = block.begin(); iter != block.end(); ++iter) {
|
||||
IR::Inst* inst = &*iter;
|
||||
|
||||
// Call the relevant Emit* member function.
|
||||
switch (inst->GetOpcode()) {
|
||||
#define OPCODE(name, type, ...) \
|
||||
case IR::Opcode::name: \
|
||||
A32EmitX64::Emit##name(ctx, inst); \
|
||||
break;
|
||||
#define A32OPC(name, type, ...) \
|
||||
case IR::Opcode::A32##name: \
|
||||
A32EmitX64::EmitA32##name(ctx, inst); \
|
||||
break;
|
||||
auto const loop_all_inst = [this, &block, &ctx](auto const func) {
|
||||
for (auto iter = block.begin(); iter != block.end(); ++iter) [[likely]] {
|
||||
auto* inst = &*iter;
|
||||
// Call the relevant Emit* member function.
|
||||
switch (inst->GetOpcode()) {
|
||||
#define OPCODE(name, type, ...) \
|
||||
case IR::Opcode::name: \
|
||||
A32EmitX64::Emit##name(ctx, inst); \
|
||||
break;
|
||||
#define A32OPC(name, type, ...) \
|
||||
case IR::Opcode::A32##name: \
|
||||
A32EmitX64::EmitA32##name(ctx, inst);\
|
||||
break;
|
||||
#define A64OPC(...)
|
||||
#include "dynarmic/ir/opcodes.inc"
|
||||
#undef OPCODE
|
||||
#undef A32OPC
|
||||
#undef A64OPC
|
||||
|
||||
default:
|
||||
ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
|
||||
break;
|
||||
default: [[unlikely]] ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
|
||||
}
|
||||
reg_alloc.EndOfAllocScope();
|
||||
func(reg_alloc);
|
||||
}
|
||||
|
||||
reg_alloc.EndOfAllocScope();
|
||||
|
||||
if (conf.very_verbose_debugging_output) {
|
||||
};
|
||||
if (!conf.very_verbose_debugging_output) [[likely]] {
|
||||
loop_all_inst([](auto&) { /*noop*/ });
|
||||
} else [[unlikely]] {
|
||||
loop_all_inst([this](auto& reg_alloc) {
|
||||
EmitVerboseDebuggingOutput(reg_alloc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reg_alloc.AssertNoMoreUses();
|
||||
|
|
@ -229,7 +230,7 @@ void A32EmitX64::GenTerminalHandlers() {
|
|||
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
||||
calculate_location_descriptor();
|
||||
code.mov(eax, dword[r15 + offsetof(A32JitState, rsb_ptr)]);
|
||||
code.sub(eax, 1);
|
||||
code.dec(eax);
|
||||
code.and_(eax, u32(A32JitState::RSBPtrMask));
|
||||
code.mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], eax);
|
||||
code.cmp(rbx, qword[r15 + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
||||
|
|
|
|||
|
|
@ -198,18 +198,19 @@ void A64EmitX64::GenTerminalHandlers() {
|
|||
code.or_(rbx, rcx);
|
||||
};
|
||||
|
||||
Xbyak::Label fast_dispatch_cache_miss, rsb_cache_miss;
|
||||
Xbyak::Label fast_dispatch_cache_miss;
|
||||
Xbyak::Label rsb_cache_miss;
|
||||
|
||||
code.align();
|
||||
terminal_handler_pop_rsb_hint = code.getCurr<const void*>();
|
||||
calculate_location_descriptor();
|
||||
code.mov(eax, dword[r15 + offsetof(A64JitState, rsb_ptr)]);
|
||||
code.sub(eax, 1);
|
||||
code.dec(eax);
|
||||
code.and_(eax, u32(A64JitState::RSBPtrMask));
|
||||
code.mov(dword[r15 + offsetof(A64JitState, rsb_ptr)], eax);
|
||||
code.cmp(rbx, qword[r15 + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
||||
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
|
||||
code.jne(rsb_cache_miss);
|
||||
code.jne(rsb_cache_miss, code.T_NEAR);
|
||||
} else {
|
||||
code.jne(code.GetReturnFromRunCodeAddress());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
#ifdef _WIN32
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code, [&](Xbyak::Reg64 return_value_ptr, [[maybe_unused]] RegList args) {
|
||||
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
|
||||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (8 + 16 + ABI_SHADOW_SPACE)]);
|
||||
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
});
|
||||
code.movups(xmm1, xword[code.ABI_RETURN]);
|
||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
#else
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCall(code);
|
||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||
code.movq(xmm1, code.ABI_RETURN);
|
||||
|
|
@ -57,13 +57,13 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
code.align();
|
||||
memory_write_128 = code.getCurr<void (*)()>();
|
||||
#ifdef _WIN32
|
||||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (8 + 16 + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||
Devirtualize<&A64::UserCallbacks::MemoryWrite128>(conf.callbacks).EmitCall(code);
|
||||
code.add(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||
#else
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||
code.movq(code.ABI_PARAM3, xmm1);
|
||||
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
||||
|
|
@ -81,7 +81,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
code.align();
|
||||
memory_exclusive_write_128 = code.getCurr<void (*)()>();
|
||||
#ifdef _WIN32
|
||||
code.sub(rsp, 8 + 32 + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (8 + 32 + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||
code.lea(code.ABI_PARAM4, ptr[rsp + ABI_SHADOW_SPACE + 16]);
|
||||
code.movaps(xword[code.ABI_PARAM3], xmm1);
|
||||
|
|
@ -89,7 +89,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
|||
Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive128>(conf.callbacks).EmitCall(code);
|
||||
code.add(rsp, 8 + 32 + ABI_SHADOW_SPACE);
|
||||
#else
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
if (code.HasHostFeature(HostFeature::SSE41)) {
|
||||
code.movq(code.ABI_PARAM3, xmm1);
|
||||
code.pextrq(code.ABI_PARAM4, xmm1, 1);
|
||||
|
|
@ -131,8 +131,8 @@ void A64EmitX64::GenFastmemFallbacks() {
|
|||
{64, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive64>(conf.callbacks)},
|
||||
}};
|
||||
|
||||
for (bool ordered : {false, true}) {
|
||||
for (int vaddr_idx : idxes) {
|
||||
for (auto const ordered : {false, true}) {
|
||||
for (auto const vaddr_idx : idxes) {
|
||||
if (vaddr_idx == 4 || vaddr_idx == 15) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@ public:
|
|||
uint8_t* alloc(size_t size) override {
|
||||
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (p == nullptr) {
|
||||
throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
|
||||
using Xbyak::Error;
|
||||
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
|
||||
}
|
||||
return static_cast<uint8_t*>(p);
|
||||
}
|
||||
|
|
@ -95,7 +96,8 @@ public:
|
|||
|
||||
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
|
||||
using Xbyak::Error;
|
||||
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
|
||||
}
|
||||
std::memcpy(p, &size, sizeof(size_t));
|
||||
return static_cast<uint8_t*>(p) + DYNARMIC_PAGE_SIZE;
|
||||
|
|
@ -514,7 +516,8 @@ size_t BlockOfCode::GetTotalCodeSize() const {
|
|||
|
||||
void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
||||
if (size_ + alloc_size >= maxSize_) {
|
||||
throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
|
||||
using Xbyak::Error;
|
||||
XBYAK_THROW(Xbyak::ERR_CODE_IS_TOO_BIG);
|
||||
}
|
||||
|
||||
EnsureMemoryCommitted(alloc_size);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I
|
|||
}
|
||||
|
||||
void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) {
|
||||
code.sub(rsp, sizeof(RegisterData));
|
||||
code.lea(rsp, ptr[rsp - sizeof(RegisterData)]);
|
||||
code.stmxcsr(dword[rsp + offsetof(RegisterData, mxcsr)]);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (rsp.getIdx() == i) {
|
||||
|
|
@ -223,7 +223,7 @@ void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Reg value = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||
code.test(value, value);
|
||||
code.lahf();
|
||||
code.mov(al, 0);
|
||||
code.xor_(al, al);
|
||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +270,6 @@ void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
|||
code.shr(nzcv, 28);
|
||||
code.imul(nzcv, nzcv, NZCV::to_x64_multiplier);
|
||||
code.and_(nzcv, NZCV::x64_mask);
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||
}
|
||||
}
|
||||
|
|
@ -331,10 +330,8 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
|
|||
code.jle(pass);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, "Unknown cond {}", static_cast<size_t>(cond));
|
||||
break;
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -992,7 +992,6 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
|||
code.seto(overflow);
|
||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,23 @@
|
|||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
using namespace Xbyak::util;
|
||||
|
|
@ -60,23 +77,6 @@ constexpr u64 f64_max_s32 = 0x41dfffffffc00000u; // 2147483647 as a double
|
|||
constexpr u64 f64_max_u32 = 0x41efffffffe00000u; // 4294967295 as a double
|
||||
constexpr u64 f64_max_s64_lim = 0x43e0000000000000u; // 2^63 as a double (actual maximum unrepresentable)
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
|
||||
template<size_t fsize>
|
||||
void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> to_daz) {
|
||||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
|
|
@ -473,7 +473,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
}
|
||||
|
||||
template<size_t fsize, bool is_max>
|
||||
static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) noexcept {
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
|
||||
|
||||
|
|
@ -701,15 +701,14 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
// x64 rounds before flushing to zero
|
||||
// AArch64 rounds after flushing to zero
|
||||
// This difference of behaviour is noticable if something would round to a smallest normalized number
|
||||
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
code.movq(code.ABI_PARAM1, operand1);
|
||||
code.movq(code.ABI_PARAM2, operand2);
|
||||
code.movq(code.ABI_PARAM3, operand3);
|
||||
code.mov(code.ABI_PARAM4.cvt32(), ctx.FPCR().Value());
|
||||
#ifdef _WIN32
|
||||
code.sub(rsp, 16 + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (16 + ABI_SHADOW_SPACE)]);
|
||||
code.lea(rax, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||
code.mov(qword[rsp + ABI_SHADOW_SPACE], rax);
|
||||
code.CallFunction(fallback_fn);
|
||||
|
|
@ -735,13 +734,13 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.vmovaps(xmm0, code.Const(xword, FP::FPInfo<FPT>::mantissa_msb));
|
||||
|
||||
FCODE(ucomis)(operand2, operand3);
|
||||
code.jp(has_nan);
|
||||
code.jp(has_nan, code.T_NEAR);
|
||||
FCODE(ucomis)(operand1, operand1);
|
||||
code.jnp(indeterminate);
|
||||
code.jnp(indeterminate, code.T_NEAR);
|
||||
|
||||
// AArch64 specifically emits a default NaN for the case when the addend is a QNaN and the two other arguments are {inf, zero}
|
||||
code.ptest(operand1, xmm0);
|
||||
code.jz(op1_snan);
|
||||
code.jz(op1_snan, code.T_NEAR);
|
||||
FCODE(vmuls)(xmm0, operand2, operand3); // check if {op2, op3} are {inf, zero}/{zero, inf}
|
||||
FCODE(ucomis)(xmm0, xmm0);
|
||||
code.jnp(*end);
|
||||
|
|
@ -753,10 +752,10 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.L(has_nan);
|
||||
|
||||
FCODE(ucomis)(operand1, operand1);
|
||||
code.jnp(op1_done);
|
||||
code.jnp(op1_done, code.T_NEAR);
|
||||
code.movaps(result, operand1); // this is done because of NaN behavior of vfmadd231s (priority of op2, op3, op1)
|
||||
code.ptest(operand1, xmm0);
|
||||
code.jnz(op1_done);
|
||||
code.jnz(op1_done, code.T_NEAR);
|
||||
code.L(op1_snan);
|
||||
code.vorps(result, operand1, xmm0);
|
||||
code.jmp(*end);
|
||||
|
|
@ -774,9 +773,9 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.L(op2_done);
|
||||
|
||||
FCODE(ucomis)(operand3, operand3);
|
||||
code.jnp(op3_done);
|
||||
code.jnp(op3_done, code.T_NEAR);
|
||||
code.ptest(operand3, xmm0);
|
||||
code.jnz(op3_done);
|
||||
code.jnz(op3_done, code.T_NEAR);
|
||||
code.vorps(result, operand3, xmm0);
|
||||
code.jmp(*end);
|
||||
code.L(op3_done);
|
||||
|
|
@ -1019,7 +1018,7 @@ static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst*
|
|||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*fallback);
|
||||
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
code.movq(code.ABI_PARAM1, operand1);
|
||||
code.movq(code.ABI_PARAM2, operand2);
|
||||
|
|
@ -1204,9 +1203,9 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
}
|
||||
|
||||
// a > 0 && a < 0x00800000;
|
||||
code.sub(tmp, 1);
|
||||
code.dec(tmp);
|
||||
code.cmp(tmp, 0x007FFFFF);
|
||||
code.jb(fallback);
|
||||
code.jb(fallback, code.T_NEAR); //within -127,128
|
||||
needs_fallback = true;
|
||||
}
|
||||
|
||||
|
|
@ -1235,17 +1234,17 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
|
||||
code.ucomisd(value, result);
|
||||
if (ctx.FPCR().DN()) {
|
||||
code.jc(default_nan);
|
||||
code.je(zero);
|
||||
code.jc(default_nan, code.T_NEAR);
|
||||
code.je(zero, code.T_NEAR);
|
||||
} else {
|
||||
code.jp(nan);
|
||||
code.je(zero);
|
||||
code.jc(default_nan);
|
||||
code.jp(nan, code.T_NEAR);
|
||||
code.je(zero, code.T_NEAR);
|
||||
code.jc(default_nan, code.T_NEAR);
|
||||
}
|
||||
|
||||
if (!ctx.FPCR().FZ()) {
|
||||
needs_fallback = true;
|
||||
code.jmp(fallback);
|
||||
code.jmp(fallback, code.T_NEAR);
|
||||
} else {
|
||||
// result = 0
|
||||
code.jmp(*end, code.T_NEAR);
|
||||
|
|
@ -1278,7 +1277,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
|
||||
code.L(fallback);
|
||||
if (needs_fallback) {
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
code.movq(code.ABI_PARAM1, operand);
|
||||
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
|
||||
|
|
@ -1361,7 +1360,7 @@ static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst*
|
|||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*fallback);
|
||||
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
code.movq(code.ABI_PARAM1, operand1);
|
||||
code.movq(code.ABI_PARAM2, operand2);
|
||||
|
|
@ -2132,3 +2131,6 @@ void EmitX64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
|||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
|
||||
#undef FCODE
|
||||
#undef ICODE
|
||||
|
|
|
|||
|
|
@ -161,8 +161,7 @@ template<>
|
|||
|
||||
template<>
|
||||
[[maybe_unused]] Xbyak::RegExp EmitFastmemVAddr<A64EmitContext>(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, bool& require_abort_handling, std::optional<Xbyak::Reg64> tmp) {
|
||||
const size_t unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
|
||||
|
||||
auto const unused_top_bits = 64 - ctx.conf.fastmem_address_space_bits;
|
||||
if (unused_top_bits == 0) {
|
||||
return r13 + vaddr;
|
||||
} else if (ctx.conf.silently_mirror_fastmem) {
|
||||
|
|
@ -306,7 +305,7 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int
|
|||
code.L(loop);
|
||||
code.lock();
|
||||
code.cmpxchg16b(xword[addr]);
|
||||
code.jnz(loop);
|
||||
code.jnz(loop, code.T_NEAR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -373,7 +372,7 @@ void EmitExclusiveTestAndClear(BlockOfCode& code, const UserConfig& conf, Xbyak:
|
|||
Xbyak::Label ok;
|
||||
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index)));
|
||||
code.cmp(qword[pointer], vaddr);
|
||||
code.jne(ok);
|
||||
code.jne(ok, code.T_NEAR);
|
||||
code.mov(qword[pointer], tmp);
|
||||
code.L(ok);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,6 @@
|
|||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
using namespace Xbyak::util;
|
||||
namespace mp = mcl::mp;
|
||||
|
||||
namespace {
|
||||
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (fsize == 32) { \
|
||||
|
|
@ -57,6 +50,13 @@ namespace {
|
|||
} \
|
||||
}
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
using namespace Xbyak::util;
|
||||
namespace mp = mcl::mp;
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename Lambda>
|
||||
void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) {
|
||||
const bool switch_mxcsr = ctx.FPCR(fpcr_controlled) != ctx.FPCR();
|
||||
|
|
@ -122,11 +122,11 @@ void HandleNaNs(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, std::
|
|||
|
||||
const Xbyak::Xmm result = xmms[0];
|
||||
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
|
||||
const size_t stack_space = xmms.size() * 16;
|
||||
code.sub(rsp, static_cast<u32>(stack_space + ABI_SHADOW_SPACE));
|
||||
code.lea(rsp, ptr[rsp - static_cast<u32>(stack_space + ABI_SHADOW_SPACE)]);
|
||||
for (size_t i = 0; i < xmms.size(); ++i) {
|
||||
code.movaps(xword[rsp + ABI_SHADOW_SPACE + i * 16], xmms[i]);
|
||||
}
|
||||
|
|
@ -443,7 +443,7 @@ void EmitTwoOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak
|
|||
const u32 fpcr = ctx.FPCR(fpcr_controlled).Value();
|
||||
|
||||
constexpr u32 stack_space = 2 * 16;
|
||||
code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||
code.mov(code.ABI_PARAM3.cvt32(), fpcr);
|
||||
|
|
@ -479,7 +479,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby
|
|||
|
||||
#ifdef _WIN32
|
||||
constexpr u32 stack_space = 4 * 16;
|
||||
code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]);
|
||||
|
|
@ -488,7 +488,7 @@ void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xby
|
|||
code.mov(qword[rsp + ABI_SHADOW_SPACE + 0], rax);
|
||||
#else
|
||||
constexpr u32 stack_space = 3 * 16;
|
||||
code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
|
||||
|
|
@ -536,7 +536,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya
|
|||
|
||||
#ifdef _WIN32
|
||||
constexpr u32 stack_space = 5 * 16;
|
||||
code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 3 * 16]);
|
||||
|
|
@ -546,7 +546,7 @@ void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbya
|
|||
code.mov(qword[rsp + ABI_SHADOW_SPACE + 8], rax);
|
||||
#else
|
||||
constexpr u32 stack_space = 4 * 16;
|
||||
code.sub(rsp, stack_space + ABI_SHADOW_SPACE);
|
||||
code.lea(rsp, ptr[rsp - (stack_space + ABI_SHADOW_SPACE)]);
|
||||
code.lea(code.ABI_PARAM1, ptr[rsp + ABI_SHADOW_SPACE + 0 * 16]);
|
||||
code.lea(code.ABI_PARAM2, ptr[rsp + ABI_SHADOW_SPACE + 1 * 16]);
|
||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE + 2 * 16]);
|
||||
|
|
@ -1371,7 +1371,7 @@ void EmitFPVectorMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*fallback);
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
if (needs_rounding_correction && needs_nan_correction) {
|
||||
EmitFourOpFallbackWithoutRegAlloc<LoadPreviousResult::Yes>(code, ctx, result, xmm_a, xmm_b, xmm_c, EmitFPVectorMulAddFallback<FPT, true, true>, fpcr_controlled);
|
||||
|
|
@ -1635,7 +1635,7 @@ static void EmitRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
|||
|
||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*fallback);
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
|
|
@ -1812,7 +1812,7 @@ static void EmitRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* ins
|
|||
|
||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*bad_values);
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
EmitTwoOpFallbackWithoutRegAlloc(code, ctx, result, operand, fallback_fn, fpcr_controlled);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
|
|
@ -1898,7 +1898,7 @@ static void EmitRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
|||
|
||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
code.L(*fallback);
|
||||
code.sub(rsp, 8);
|
||||
code.lea(rsp, ptr[rsp - 8]);
|
||||
ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
EmitThreeOpFallbackWithoutRegAlloc(code, ctx, result, operand1, operand2, fallback_fn, fpcr_controlled);
|
||||
ABI_PopCallerSaveRegistersAndAdjustStackExcept(code, HostLocXmmIdx(result.getIdx()));
|
||||
|
|
@ -2180,3 +2180,6 @@ void EmitX64::EmitFPVectorToUnsignedFixed64(EmitContext& ctx, IR::Inst* inst) {
|
|||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
|
||||
#undef FCODE
|
||||
#undef ICODE
|
||||
|
|
|
|||
|
|
@ -338,3 +338,6 @@ void EmitX64::EmitVectorUnsignedSaturatedSub64(EmitContext& ctx, IR::Inst* inst)
|
|||
}
|
||||
|
||||
} // 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.ja(exception_handler_without_cb);
|
||||
|
||||
code.sub(code.rsp, 8);
|
||||
code.lea(code.rsp, code.ptr[code.rsp - 8]);
|
||||
code.mov(code.ABI_PARAM1, mcl::bit_cast<u64>(&cb));
|
||||
code.mov(code.ABI_PARAM2, code.ABI_PARAM3);
|
||||
code.CallLambda(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
enum class ArchVersion;
|
||||
enum class ArchVersion : std::uint8_t;
|
||||
enum class CoprocReg;
|
||||
enum class Exception;
|
||||
enum class ExtReg;
|
||||
|
|
@ -27,12 +27,11 @@ enum class Reg;
|
|||
* The user of this class updates `current_location` as appropriate.
|
||||
*/
|
||||
class IREmitter : public IR::IREmitter {
|
||||
IR::U64 ImmCurrentLocationDescriptor();
|
||||
public:
|
||||
IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version)
|
||||
: IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {}
|
||||
|
||||
LocationDescriptor current_location;
|
||||
|
||||
|
||||
size_t ArchVersion() const;
|
||||
|
||||
u32 PC() const;
|
||||
|
|
@ -107,10 +106,9 @@ public:
|
|||
IR::U64 CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm);
|
||||
void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option);
|
||||
void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option);
|
||||
|
||||
private:
|
||||
public:
|
||||
LocationDescriptor current_location;
|
||||
enum ArchVersion arch_version;
|
||||
IR::U64 ImmCurrentLocationDescriptor();
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
|
|
|||
|
|
@ -33,13 +33,11 @@ inline size_t ToFastLookupIndexArm(u32 instruction) {
|
|||
} // namespace detail
|
||||
|
||||
template<typename V>
|
||||
ArmDecodeTable<V> GetArmDecodeTable() {
|
||||
constexpr ArmDecodeTable<V> GetArmDecodeTable() {
|
||||
std::vector<ArmMatcher<V>> list = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||
#include "./arm.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
|
|
@ -62,9 +60,10 @@ ArmDecodeTable<V> GetArmDecodeTable() {
|
|||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) {
|
||||
static const auto table = GetArmDecodeTable<V>();
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
alignas(64) static const auto table = GetArmDecodeTable<V>();
|
||||
const auto matches_instruction = [instruction](const auto& matcher) {
|
||||
return matcher.Matches(instruction);
|
||||
};
|
||||
|
||||
const auto& subtable = table[detail::ToFastLookupIndexArm(instruction)];
|
||||
auto iter = std::find_if(subtable.begin(), subtable.end(), matches_instruction);
|
||||
|
|
|
|||
|
|
@ -25,3 +25,51 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
|
|||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
||||
// ls -l | awk '{print "#include \"dynarmic/frontend/A32/translate/impl/" $9 "\""}'
|
||||
#include "dynarmic/frontend/A32/translate/impl/a32_branch.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/a32_crc32.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/a32_exception_generating.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp"
|
||||
//#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_misc.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/barrier.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/coprocessor.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/data_processing.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/divide.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/extension.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/hint.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/load_store.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/misc.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/multiply.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/packing.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/parallel.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/reversal.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/saturated.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/status_register_access.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/synchronization.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb16.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_branch.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_control.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_register.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_load_byte.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_load_halfword.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_load_word.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_long_multiply.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_misc.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_parallel.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/thumb32_store_single_data_item.cpp"
|
||||
#include "dynarmic/frontend/A32/translate/impl/vfp.cpp"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@
|
|||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
bool TranslatorVisitor::arm_NOP() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ArmConditionPassed(Cond cond) {
|
||||
return IsConditionPassed(*this, cond);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue