Revert "[dynarmic] replace mcl::bit_cast with std::bit_cast; fix IR_emit codepath warnings for UNREACHABLE(); remove type trait mcl::integer_of_size dependency (#2775)" (#2863)
This reverts commit 61ab1be0e7.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2863
Co-authored-by: unknown <sahyno1996@gmail.com>
Co-committed-by: unknown <sahyno1996@gmail.com>
This commit is contained in:
parent
15becaa5a3
commit
6b01c13975
|
|
@ -6,9 +6,10 @@ add_library(dynarmic STATIC
|
|||
backend/block_range_information.cpp
|
||||
backend/block_range_information.h
|
||||
backend/exception_handler.h
|
||||
common/always_false.h
|
||||
common/assert.cpp
|
||||
common/assert.h
|
||||
common/type_util.h
|
||||
common/cast_util.h
|
||||
common/common_types.h
|
||||
common/crypto/aes.cpp
|
||||
common/crypto/aes.h
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "dynarmic/backend/arm64/devirtualize.h"
|
||||
#include "dynarmic/backend/arm64/emit_arm64.h"
|
||||
#include "dynarmic/backend/arm64/stack_layout.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||
|
|
@ -93,9 +93,9 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -151,9 +151,9 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ void A32AddressSpace::EmitPrelude() {
|
|||
code.MOV(Xstate, X1);
|
||||
code.MOV(Xhalt, X2);
|
||||
if (conf.page_table) {
|
||||
code.MOV(Xpagetable, std::bit_cast<u64>(conf.page_table));
|
||||
code.MOV(Xpagetable, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.MOV(Xfastmem, *conf.fastmem_pointer);
|
||||
|
|
@ -258,7 +258,7 @@ void A32AddressSpace::EmitPrelude() {
|
|||
code.MOV(Xstate, X1);
|
||||
code.MOV(Xhalt, X2);
|
||||
if (conf.page_table) {
|
||||
code.MOV(Xpagetable, std::bit_cast<u64>(conf.page_table));
|
||||
code.MOV(Xpagetable, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.MOV(Xfastmem, *conf.fastmem_pointer);
|
||||
|
|
@ -317,9 +317,9 @@ void A32AddressSpace::EmitPrelude() {
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(this));
|
||||
code.dx(mcl::bit_cast<u64>(this));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
}
|
||||
|
||||
prelude_info.return_from_run_code = code.xptr<void*>();
|
||||
|
|
@ -347,7 +347,7 @@ void A32AddressSpace::EmitPrelude() {
|
|||
|
||||
code.align(8);
|
||||
code.l(l_return_to_dispatcher);
|
||||
code.dx(std::bit_cast<u64>(prelude_info.return_to_dispatcher));
|
||||
code.dx(mcl::bit_cast<u64>(prelude_info.return_to_dispatcher));
|
||||
|
||||
prelude_info.end_of_prelude = code.offset();
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ EmitConfig A32AddressSpace::GetEmitConfig() {
|
|||
|
||||
.check_halt_on_memory_access = conf.check_halt_on_memory_access,
|
||||
|
||||
.page_table_pointer = std::bit_cast<u64>(conf.page_table),
|
||||
.page_table_pointer = mcl::bit_cast<u64>(conf.page_table),
|
||||
.page_table_address_space_bits = 32,
|
||||
.page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits,
|
||||
.silently_mirror_page_table = true,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "dynarmic/backend/arm64/devirtualize.h"
|
||||
#include "dynarmic/backend/arm64/emit_arm64.h"
|
||||
#include "dynarmic/backend/arm64/stack_layout.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||
#include "dynarmic/interface/A64/config.h"
|
||||
|
|
@ -92,9 +92,9 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -150,9 +150,9 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -235,9 +235,9 @@ static void* EmitExclusiveRead128CallTrampoline(oaknut::CodeGenerator& code, con
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -317,9 +317,9 @@ static void* EmitExclusiveWrite128CallTrampoline(oaknut::CodeGenerator& code, co
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(&conf));
|
||||
code.dx(mcl::bit_cast<u64>(&conf));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
@ -396,7 +396,7 @@ void A64AddressSpace::EmitPrelude() {
|
|||
code.MOV(Xstate, X1);
|
||||
code.MOV(Xhalt, X2);
|
||||
if (conf.page_table) {
|
||||
code.MOV(Xpagetable, std::bit_cast<u64>(conf.page_table));
|
||||
code.MOV(Xpagetable, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.MOV(Xfastmem, *conf.fastmem_pointer);
|
||||
|
|
@ -434,7 +434,7 @@ void A64AddressSpace::EmitPrelude() {
|
|||
code.MOV(Xstate, X1);
|
||||
code.MOV(Xhalt, X2);
|
||||
if (conf.page_table) {
|
||||
code.MOV(Xpagetable, std::bit_cast<u64>(conf.page_table));
|
||||
code.MOV(Xpagetable, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.MOV(Xfastmem, *conf.fastmem_pointer);
|
||||
|
|
@ -492,9 +492,9 @@ void A64AddressSpace::EmitPrelude() {
|
|||
|
||||
code.align(8);
|
||||
code.l(l_this);
|
||||
code.dx(std::bit_cast<u64>(this));
|
||||
code.dx(mcl::bit_cast<u64>(this));
|
||||
code.l(l_addr);
|
||||
code.dx(std::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
code.dx(mcl::bit_cast<u64>(Common::FptrCast(fn)));
|
||||
}
|
||||
|
||||
prelude_info.return_from_run_code = code.xptr<void*>();
|
||||
|
|
@ -522,7 +522,7 @@ void A64AddressSpace::EmitPrelude() {
|
|||
|
||||
code.align(8);
|
||||
code.l(l_return_to_dispatcher);
|
||||
code.dx(std::bit_cast<u64>(prelude_info.return_to_dispatcher));
|
||||
code.dx(mcl::bit_cast<u64>(prelude_info.return_to_dispatcher));
|
||||
|
||||
prelude_info.end_of_prelude = code.offset();
|
||||
|
||||
|
|
@ -544,7 +544,7 @@ EmitConfig A64AddressSpace::GetEmitConfig() {
|
|||
|
||||
.check_halt_on_memory_access = conf.check_halt_on_memory_access,
|
||||
|
||||
.page_table_pointer = std::bit_cast<u64>(conf.page_table),
|
||||
.page_table_pointer = mcl::bit_cast<u64>(conf.page_table),
|
||||
.page_table_address_space_bits = conf.page_table_address_space_bits,
|
||||
.page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits,
|
||||
.silently_mirror_page_table = conf.silently_mirror_page_table,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "dynarmic/common/assert.h"
|
||||
#include <oaknut/oaknut.hpp>
|
||||
|
||||
#include "dynarmic/common/always_false.h"
|
||||
|
||||
namespace Dynarmic::Backend::Arm64 {
|
||||
|
||||
|
|
@ -36,8 +37,7 @@ constexpr auto Rscratch0() {
|
|||
} else if constexpr (bitsize == 64) {
|
||||
return Xscratch0;
|
||||
} else {
|
||||
// TODO: This codepath is regarded as "takeable" on gcc12
|
||||
return Xscratch0; //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<bitsize>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,8 +48,7 @@ constexpr auto Rscratch1() {
|
|||
} else if constexpr (bitsize == 64) {
|
||||
return Xscratch1;
|
||||
} else {
|
||||
// TODO: This codepath is regarded as "takeable" on gcc12
|
||||
return Xscratch1; //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<bitsize>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
#include "dynarmic/backend/arm64/a64_address_space.h"
|
||||
#include "dynarmic/backend/arm64/a64_jitstate.h"
|
||||
|
|
@ -16,7 +13,7 @@
|
|||
#include "dynarmic/backend/arm64/devirtualize.h"
|
||||
#include "dynarmic/backend/arm64/emit_arm64.h"
|
||||
#include "dynarmic/backend/arm64/stack_layout.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/common/llvm_disassemble.h"
|
||||
#include "dynarmic/interface/exclusive_monitor.h"
|
||||
|
|
@ -102,7 +99,7 @@ void AddressSpace::ClearCache() {
|
|||
|
||||
void AddressSpace::DumpDisassembly() const {
|
||||
for (u32* ptr = mem.ptr(); ptr < code.xptr<u32*>(); ptr++) {
|
||||
std::printf("%s", Common::DisassembleAArch64(*ptr, std::bit_cast<u64>(ptr)).c_str());
|
||||
std::printf("%s", Common::DisassembleAArch64(*ptr, mcl::bit_cast<u64>(ptr)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +316,7 @@ void AddressSpace::RelinkForDescriptor(IR::LocationDescriptor target_descriptor,
|
|||
|
||||
FakeCall AddressSpace::FastmemCallback(u64 host_pc) {
|
||||
{
|
||||
const auto host_ptr = std::bit_cast<CodePtr>(host_pc);
|
||||
const auto host_ptr = mcl::bit_cast<CodePtr>(host_pc);
|
||||
|
||||
const auto entry_point = ReverseGetEntryPoint(host_ptr);
|
||||
if (!entry_point) {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
|
|
@ -24,7 +23,7 @@ struct DevirtualizedCall {
|
|||
template<auto mfp>
|
||||
DevirtualizedCall DevirtualizeWindows(mcl::class_type<decltype(mfp)>* this_) {
|
||||
static_assert(sizeof(mfp) == 8);
|
||||
return DevirtualizedCall{std::bit_cast<u64>(mfp), reinterpret_cast<u64>(this_)};
|
||||
return DevirtualizedCall{mcl::bit_cast<u64>(mfp), reinterpret_cast<u64>(this_)};
|
||||
}
|
||||
|
||||
// https://github.com/ARM-software/abi-aa/blob/main/cppabi64/cppabi64.rst#representation-of-pointer-to-member-function
|
||||
|
|
@ -35,16 +34,16 @@ DevirtualizedCall DevirtualizeDefault(mcl::class_type<decltype(mfp)>* this_) {
|
|||
u64 ptr;
|
||||
// LSB is discriminator for if function is virtual. Other bits are this adjustment.
|
||||
u64 adj;
|
||||
} mfp_struct = std::bit_cast<MemberFunctionPointer>(mfp);
|
||||
} mfp_struct = mcl::bit_cast<MemberFunctionPointer>(mfp);
|
||||
|
||||
static_assert(sizeof(MemberFunctionPointer) == 16);
|
||||
static_assert(sizeof(MemberFunctionPointer) == sizeof(mfp));
|
||||
|
||||
u64 fn_ptr = mfp_struct.ptr;
|
||||
u64 this_ptr = std::bit_cast<u64>(this_) + (mfp_struct.adj >> 1);
|
||||
u64 this_ptr = mcl::bit_cast<u64>(this_) + (mfp_struct.adj >> 1);
|
||||
if (mfp_struct.adj & 1) {
|
||||
u64 vtable = std::bit_cast<u64>(this_ptr);
|
||||
fn_ptr = std::bit_cast<u64>(vtable + fn_ptr);
|
||||
u64 vtable = mcl::bit_cast_pointee<u64>(this_ptr);
|
||||
fn_ptr = mcl::bit_cast_pointee<u64>(vtable + fn_ptr);
|
||||
}
|
||||
return DevirtualizedCall{fn_ptr, this_ptr};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <oaknut/oaknut.hpp>
|
||||
|
||||
#include "dynarmic/backend/arm64/a64_jitstate.h"
|
||||
|
|
@ -499,7 +495,7 @@ template<>
|
|||
void EmitIR<IR::Opcode::A64GetTPIDR>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto Xvalue = ctx.reg_alloc.WriteX(inst);
|
||||
RegAlloc::Realize(Xvalue);
|
||||
code.MOV(Xscratch0, std::bit_cast<u64>(ctx.conf.tpidr_el0));
|
||||
code.MOV(Xscratch0, mcl::bit_cast<u64>(ctx.conf.tpidr_el0));
|
||||
code.LDR(Xvalue, Xscratch0);
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +503,7 @@ template<>
|
|||
void EmitIR<IR::Opcode::A64GetTPIDRRO>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto Xvalue = ctx.reg_alloc.WriteX(inst);
|
||||
RegAlloc::Realize(Xvalue);
|
||||
code.MOV(Xscratch0, std::bit_cast<u64>(ctx.conf.tpidrro_el0));
|
||||
code.MOV(Xscratch0, mcl::bit_cast<u64>(ctx.conf.tpidrro_el0));
|
||||
code.LDR(Xvalue, Xscratch0);
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +512,7 @@ void EmitIR<IR::Opcode::A64SetTPIDR>(oaknut::CodeGenerator& code, EmitContext& c
|
|||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
auto Xvalue = ctx.reg_alloc.ReadX(args[0]);
|
||||
RegAlloc::Realize(Xvalue);
|
||||
code.MOV(Xscratch0, std::bit_cast<u64>(ctx.conf.tpidr_el0));
|
||||
code.MOV(Xscratch0, mcl::bit_cast<u64>(ctx.conf.tpidr_el0));
|
||||
code.STR(Xvalue, Xscratch0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -10,8 +7,8 @@
|
|||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <oaknut/oaknut.hpp>
|
||||
|
||||
#include "dynarmic/backend/arm64/abi.h"
|
||||
|
|
@ -551,7 +548,7 @@ void FastmemEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::In
|
|||
FastmemPatchInfo{
|
||||
.marker = marker,
|
||||
.fc = FakeCall{
|
||||
.call_pc = std::bit_cast<u64>(code.xptr<void*>()),
|
||||
.call_pc = mcl::bit_cast<u64>(code.xptr<void*>()),
|
||||
},
|
||||
.recompile = ctx.conf.recompile_on_fastmem_failure,
|
||||
});
|
||||
|
|
@ -601,7 +598,7 @@ void FastmemEmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::I
|
|||
FastmemPatchInfo{
|
||||
.marker = marker,
|
||||
.fc = FakeCall{
|
||||
.call_pc = std::bit_cast<u64>(code.xptr<void*>()),
|
||||
.call_pc = mcl::bit_cast<u64>(code.xptr<void*>()),
|
||||
},
|
||||
.recompile = ctx.conf.recompile_on_fastmem_failure,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -15,6 +12,7 @@
|
|||
#include "dynarmic/backend/arm64/emit_context.h"
|
||||
#include "dynarmic/backend/arm64/fpsr_manager.h"
|
||||
#include "dynarmic/backend/arm64/reg_alloc.h"
|
||||
#include "dynarmic/common/always_false.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
|
@ -45,7 +43,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR:
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qoperand->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -68,7 +66,7 @@ static void EmitTwoOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& ctx
|
|||
} else if constexpr (size == 32) {
|
||||
emit(Qresult->D2(), Qoperand->toD().S2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -83,7 +81,7 @@ static void EmitTwoOpArrangedNarrow(oaknut::CodeGenerator& code, EmitContext& ct
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->toD().S2(), Qoperand->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -106,7 +104,7 @@ static void EmitTwoOpArrangedPairWiden(oaknut::CodeGenerator& code, EmitContext&
|
|||
} else if constexpr (size == 32) {
|
||||
emit(Qresult->D2(), Qoperand->S4());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -121,7 +119,7 @@ static void EmitTwoOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& ctx
|
|||
} else if constexpr (size == 32) {
|
||||
emit(Qresult->toD().S2(), Qoperand->toD().S2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -149,7 +147,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qa->D2(), Qb->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -174,7 +172,7 @@ static void EmitThreeOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& c
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->Q1(), Qa->toD().D1(), Qb->toD().D1());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -197,7 +195,7 @@ static void EmitThreeOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& c
|
|||
} else if constexpr (size == 32) {
|
||||
emit(Qresult->toD().S2(), Qa->toD().S2(), Qb->toD().S2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -219,7 +217,7 @@ static void EmitSaturatedAccumulate(oaknut::CodeGenerator&, EmitContext& ctx, IR
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qaccumulator->D2(), Qoperand->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +238,7 @@ static void EmitImmShift(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* ins
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qoperand->D2(), shift_amount);
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +266,7 @@ static void EmitReduce(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst,
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Vresult, Qoperand->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/mp/metavalue/lift_value.hpp>
|
||||
#include <mcl/mp/typelist/cartesian_product.hpp>
|
||||
#include <mcl/mp/typelist/get.hpp>
|
||||
|
|
@ -15,6 +14,7 @@
|
|||
#include <mcl/mp/typelist/list.hpp>
|
||||
#include <mcl/mp/typelist/lower_to_tuple.hpp>
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <oaknut/oaknut.hpp>
|
||||
|
||||
#include "dynarmic/backend/arm64/a32_jitstate.h"
|
||||
|
|
@ -24,7 +24,8 @@
|
|||
#include "dynarmic/backend/arm64/emit_context.h"
|
||||
#include "dynarmic/backend/arm64/fpsr_manager.h"
|
||||
#include "dynarmic/backend/arm64/reg_alloc.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/always_false.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/common/fp/fpsr.h"
|
||||
#include "dynarmic/common/fp/info.h"
|
||||
|
|
@ -83,7 +84,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR:
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qa->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -111,7 +112,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qa->D2(), Qb->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -134,7 +135,7 @@ static void EmitFMA(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* ins
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qm->D2(), Qn->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -156,7 +157,7 @@ static void EmitFromFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Ins
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qto->D2(), Qfrom->D2(), fbits);
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -178,7 +179,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst)
|
|||
} else if constexpr (fsize == 64) {
|
||||
return Qto->D2();
|
||||
} else {
|
||||
return Qto->D2(); //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<fsize>>);
|
||||
}
|
||||
}();
|
||||
auto Vfrom = [&] {
|
||||
|
|
@ -187,7 +188,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst)
|
|||
} else if constexpr (fsize == 64) {
|
||||
return Qfrom->D2();
|
||||
} else {
|
||||
return Qfrom->D2(); //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<fsize>>);
|
||||
}
|
||||
}();
|
||||
|
||||
|
|
@ -270,7 +271,7 @@ static void EmitTwoOpFallbackWithoutRegAlloc(oaknut::CodeGenerator& code, EmitCo
|
|||
|
||||
ABI_PushRegisters(code, ABI_CALLER_SAVE & ~(1ull << Qresult.index()), stack_size);
|
||||
|
||||
code.MOV(Xscratch0, std::bit_cast<u64>(fn));
|
||||
code.MOV(Xscratch0, mcl::bit_cast<u64>(fn));
|
||||
code.ADD(X0, SP, 0 * 16);
|
||||
code.ADD(X1, SP, 1 * 16);
|
||||
code.MOV(X2, fpcr);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -15,6 +12,7 @@
|
|||
#include "dynarmic/backend/arm64/emit_context.h"
|
||||
#include "dynarmic/backend/arm64/fpsr_manager.h"
|
||||
#include "dynarmic/backend/arm64/reg_alloc.h"
|
||||
#include "dynarmic/common/always_false.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
|
@ -41,7 +39,7 @@ static void Emit(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, EmitF
|
|||
} else if constexpr (size == 64) {
|
||||
emit(Qresult->D2(), Qa->D2(), Qb->D2());
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<size>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <mcl/bit/bit_field.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/mp/metavalue/lift_value.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#include "dynarmic/backend/arm64/emit_context.h"
|
||||
#include "dynarmic/backend/arm64/fpsr_manager.h"
|
||||
#include "dynarmic/backend/arm64/verbose_debugging_output.h"
|
||||
#include "dynarmic/common/always_false.h"
|
||||
|
||||
namespace Dynarmic::Backend::Arm64 {
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ void RegAlloc::AssertNoMoreUses() const {
|
|||
}
|
||||
|
||||
void RegAlloc::EmitVerboseDebuggingOutput() {
|
||||
code.MOV(X19, std::bit_cast<u64>(&PrintVerboseDebuggingOutputLine)); // Non-volatile register
|
||||
code.MOV(X19, mcl::bit_cast<u64>(&PrintVerboseDebuggingOutputLine)); // Non-volatile register
|
||||
|
||||
const auto do_location = [&](HostLocInfo& info, HostLocType type, size_t index) {
|
||||
using namespace oaknut::util;
|
||||
|
|
@ -300,7 +301,7 @@ int RegAlloc::GenerateImmediate(const IR::Value& value) {
|
|||
|
||||
return 0;
|
||||
} else {
|
||||
return 0;//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +370,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
|||
} else if constexpr (required_kind == HostLoc::Kind::Flags) {
|
||||
ASSERT_FALSE("A simple read from flags is likely a logic error.");
|
||||
} else {
|
||||
return 0;//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<required_kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +395,7 @@ int RegAlloc::RealizeWriteImpl(const IR::Inst* value) {
|
|||
flags.SetupLocation(value);
|
||||
return 0;
|
||||
} else {
|
||||
return 0; //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,7 +416,7 @@ int RegAlloc::RealizeReadWriteImpl(const IR::Value& read_value, const IR::Inst*
|
|||
} else if constexpr (kind == HostLoc::Kind::Flags) {
|
||||
ASSERT_FALSE("Incorrect function for ReadWrite of flags");
|
||||
} else {
|
||||
return write_loc; //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,17 +11,19 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
class BlockOfCode;
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
namespace oaknut {
|
||||
class CodeBlock;
|
||||
} // namespace oaknut
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
namespace Dynarmic::Backend::RV64 {
|
||||
class CodeBlock;
|
||||
} // namespace Dynarmic::Backend::RV64
|
||||
|
|
@ -31,16 +33,16 @@ class CodeBlock;
|
|||
|
||||
namespace Dynarmic::Backend {
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
struct FakeCall {
|
||||
u64 call_rip;
|
||||
u64 ret_rip;
|
||||
};
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
struct FakeCall {
|
||||
u64 call_pc;
|
||||
};
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
struct FakeCall {
|
||||
};
|
||||
#else
|
||||
|
|
@ -52,11 +54,11 @@ public:
|
|||
ExceptionHandler();
|
||||
~ExceptionHandler();
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
void Register(X64::BlockOfCode& code);
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
void Register(oaknut::CodeBlock& mem, std::size_t mem_size);
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
void Register(RV64::CodeBlock& mem, std::size_t mem_size);
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
#include <fmt/format.h>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
|
|
@ -145,7 +146,7 @@ kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) {
|
|||
FakeCall fc = iter->cb(ts->__rip);
|
||||
|
||||
ts->__rsp -= sizeof(u64);
|
||||
*std::bit_cast<u64*>(ts->__rsp) = fc.ret_rip;
|
||||
*mcl::bit_cast<u64*>(ts->__rsp) = fc.ret_rip;
|
||||
ts->__rip = fc.call_rip;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
|
|
@ -270,13 +271,13 @@ ExceptionHandler::~ExceptionHandler() = default;
|
|||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
void ExceptionHandler::Register(X64::BlockOfCode& code) {
|
||||
const u64 code_begin = std::bit_cast<u64>(code.getCode());
|
||||
const u64 code_begin = mcl::bit_cast<u64>(code.getCode());
|
||||
const u64 code_end = code_begin + code.GetTotalCodeSize();
|
||||
impl = std::make_unique<Impl>(code_begin, code_end);
|
||||
}
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||
const u64 code_begin = std::bit_cast<u64>(mem.ptr());
|
||||
const u64 code_begin = mcl::bit_cast<u64>(mem.ptr());
|
||||
const u64 code_end = code_begin + size;
|
||||
impl = std::make_unique<Impl>(code_begin, code_end);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# include "dynarmic/backend/x64/mig/mach_exc_server.c"
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#else
|
||||
# error "Invalid architecture"
|
||||
#endif
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
namespace Dynarmic::Backend {
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
|||
if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_RIP); iter != sig_handler->code_block_infos.end()) {
|
||||
FakeCall fc = iter->second.cb(CTX_RIP);
|
||||
CTX_RSP -= sizeof(u64);
|
||||
*std::bit_cast<u64*>(CTX_RSP) = fc.ret_rip;
|
||||
*mcl::bit_cast<u64*>(CTX_RSP) = fc.ret_rip;
|
||||
CTX_RIP = fc.call_rip;
|
||||
return;
|
||||
}
|
||||
|
|
@ -187,17 +187,17 @@ private:
|
|||
ExceptionHandler::ExceptionHandler() = default;
|
||||
ExceptionHandler::~ExceptionHandler() = default;
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
#if defined(MCL_ARCHITECTURE_X86_64)
|
||||
void ExceptionHandler::Register(X64::BlockOfCode& code) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(code.getCode()), code.GetTotalCodeSize());
|
||||
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(code.getCode()), code.GetTotalCodeSize());
|
||||
}
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
#elif defined(MCL_ARCHITECTURE_ARM64)
|
||||
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr()), size);
|
||||
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(mem.ptr()), size);
|
||||
}
|
||||
#elif defined(ARCHITECTURE_riscv64)
|
||||
#elif defined(MCL_ARCHITECTURE_RISCV)
|
||||
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
|
||||
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
|
||||
impl = std::make_unique<Impl>(mcl::bit_cast<u64>(mem.ptr<u64>()), size);
|
||||
}
|
||||
#else
|
||||
# error "Invalid architecture"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
# include "dynarmic/backend/x64/exception_handler_windows.cpp"
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <mcl/mp/metavalue/lift_value.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/common/always_false.h"
|
||||
|
||||
namespace Dynarmic::Backend::RV64 {
|
||||
|
||||
|
|
@ -163,7 +164,7 @@ u32 RegAlloc::GenerateImmediate(const IR::Value& value) {
|
|||
} else if constexpr (kind == HostLoc::Kind::Fpr) {
|
||||
UNIMPLEMENTED();
|
||||
} else {
|
||||
//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<kind>>);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -226,7 +227,7 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) {
|
|||
fprs[new_location_index].realized = true;
|
||||
return new_location_index;
|
||||
} else {
|
||||
return 0; //static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<required_kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,7 +254,7 @@ u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value) {
|
|||
setup_location(fprs[new_location_index]);
|
||||
return new_location_index;
|
||||
} else {
|
||||
return 0;//static_assert(false);
|
||||
static_assert(Common::always_false_v<mcl::mp::lift_value<required_kind>>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -13,6 +10,7 @@
|
|||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/a32_emit_x64.h"
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <bit>
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
|
|
@ -48,7 +47,7 @@ static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*Lo
|
|||
static std::function<void(BlockOfCode&)> GenRCP(const A32::UserConfig& conf) {
|
||||
return [conf](BlockOfCode& code) {
|
||||
if (conf.page_table) {
|
||||
code.mov(code.r14, std::bit_cast<u64>(conf.page_table));
|
||||
code.mov(code.r14, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.mov(code.r13, *conf.fastmem_pointer);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "dynarmic/common/assert.h"
|
||||
#include <mcl/scope_exit.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include "dynarmic/backend/x64/a64_jitstate.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -13,6 +10,7 @@
|
|||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/a64_emit_x64.h"
|
||||
|
|
|
|||
|
|
@ -9,11 +9,10 @@
|
|||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <bit>
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
|
||||
#include "dynarmic/backend/x64/a64_emit_x64.h"
|
||||
|
|
@ -44,7 +43,7 @@ static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*Lo
|
|||
static std::function<void(BlockOfCode&)> GenRCP(const A64::UserConfig& conf) {
|
||||
return [conf](BlockOfCode& code) {
|
||||
if (conf.page_table) {
|
||||
code.mov(code.r14, std::bit_cast<u64>(conf.page_table));
|
||||
code.mov(code.r14, mcl::bit_cast<u64>(conf.page_table));
|
||||
}
|
||||
if (conf.fastmem_pointer) {
|
||||
code.mov(code.r13, *conf.fastmem_pointer);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "dynarmic/backend/x64/constant_pool.h"
|
||||
#include "dynarmic/backend/x64/host_feature.h"
|
||||
#include "dynarmic/backend/x64/jitstate_info.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
#include "dynarmic/ir/cond.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ ArgCallback DevirtualizeGeneric(mcl::class_type<decltype(mfp)>* this_) {
|
|||
template<auto mfp>
|
||||
ArgCallback DevirtualizeWindows(mcl::class_type<decltype(mfp)>* this_) {
|
||||
static_assert(sizeof(mfp) == 8);
|
||||
return ArgCallback{std::bit_cast<u64>(mfp), reinterpret_cast<u64>(this_)};
|
||||
return ArgCallback{mcl::bit_cast<u64>(mfp), reinterpret_cast<u64>(this_)};
|
||||
}
|
||||
|
||||
template<auto mfp>
|
||||
|
|
@ -53,7 +53,7 @@ ArgCallback DevirtualizeItanium(mcl::class_type<decltype(mfp)>* this_) {
|
|||
u64 ptr;
|
||||
/// The required adjustment to `this`, prior to the call.
|
||||
u64 adj;
|
||||
} mfp_struct = std::bit_cast<MemberFunctionPointer>(mfp);
|
||||
} mfp_struct = mcl::bit_cast<MemberFunctionPointer>(mfp);
|
||||
|
||||
static_assert(sizeof(MemberFunctionPointer) == 16);
|
||||
static_assert(sizeof(MemberFunctionPointer) == sizeof(mfp));
|
||||
|
|
@ -61,8 +61,8 @@ ArgCallback DevirtualizeItanium(mcl::class_type<decltype(mfp)>* this_) {
|
|||
u64 fn_ptr = mfp_struct.ptr;
|
||||
u64 this_ptr = reinterpret_cast<u64>(this_) + mfp_struct.adj;
|
||||
if (mfp_struct.ptr & 1) {
|
||||
u64 vtable = std::bit_cast<u64>(this_ptr);
|
||||
fn_ptr = std::bit_cast<u64>(vtable + fn_ptr - 1);
|
||||
u64 vtable = mcl::bit_cast_pointee<u64>(this_ptr);
|
||||
fn_ptr = mcl::bit_cast_pointee<u64>(vtable + fn_ptr - 1);
|
||||
}
|
||||
return ArgCallback{fn_ptr, this_ptr};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@
|
|||
#include <mcl/mp/typelist/list.hpp>
|
||||
#include <mcl/mp/typelist/lower_to_tuple.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/abi.h"
|
||||
#include "dynarmic/backend/x64/block_of_code.h"
|
||||
#include "dynarmic/backend/x64/constants.h"
|
||||
#include "dynarmic/backend/x64/emit_x64.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/cast_util.h"
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/common/fp/fpsr.h"
|
||||
#include "dynarmic/common/fp/info.h"
|
||||
|
|
@ -35,8 +36,22 @@
|
|||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
#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 {
|
||||
|
||||
|
|
@ -90,7 +105,7 @@ void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> t
|
|||
for (const Xbyak::Xmm& xmm : to_daz) {
|
||||
code.movaps(xmm0, code.Const(xword, fsize == 32 ? f32_non_sign_mask : f64_non_sign_mask));
|
||||
code.andps(xmm0, xmm);
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.pcmpgtd(xmm0, code.Const(xword, f32_smallest_normal - 1));
|
||||
} else if (code.HasHostFeature(HostFeature::SSE42)) {
|
||||
code.pcmpgtq(xmm0, code.Const(xword, f64_smallest_normal - 1));
|
||||
|
|
@ -105,11 +120,13 @@ void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list<Xbyak::Xmm> t
|
|||
|
||||
template<size_t fsize>
|
||||
void DenormalsAreZero(BlockOfCode& code, EmitContext& ctx, std::initializer_list<Xbyak::Xmm> to_daz) {
|
||||
if (ctx.FPCR().FZ())
|
||||
if (ctx.FPCR().FZ()) {
|
||||
ForceDenormalsToZero<fsize>(code, to_daz);
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch, size_t fsize) {
|
||||
template<size_t fsize>
|
||||
void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch) {
|
||||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
constexpr u32 nan_to_zero = FixupLUT(FpFixup::PosZero,
|
||||
FpFixup::PosZero);
|
||||
|
|
@ -124,7 +141,8 @@ void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch,
|
|||
}
|
||||
}
|
||||
|
||||
void ForceToDefaultNaN(BlockOfCode& code, Xbyak::Xmm result, size_t fsize) {
|
||||
template<size_t fsize>
|
||||
void ForceToDefaultNaN(BlockOfCode& code, Xbyak::Xmm result) {
|
||||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
const Xbyak::Opmask nan_mask = k1;
|
||||
FCODE(vfpclasss)(nan_mask, result, u8(FpClass::QNaN | FpClass::SNaN));
|
||||
|
|
@ -190,7 +208,7 @@ void PostProcessNaN(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm tmp) {
|
|||
// We allow for the case where op1 and result are the same register. We do not read from op1 once result is written to.
|
||||
template<size_t fsize>
|
||||
void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, Xbyak::Xmm op2, Xbyak::Reg64 tmp, Xbyak::Label end) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT exponent_mask = FP::FPInfo<FPT>::exponent_mask;
|
||||
constexpr FPT mantissa_msb = FP::FPInfo<FPT>::mantissa_msb;
|
||||
constexpr u8 mantissa_msb_bit = static_cast<u8>(FP::FPInfo<FPT>::explicit_mantissa_width - 1);
|
||||
|
|
@ -218,7 +236,7 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X
|
|||
}
|
||||
|
||||
constexpr size_t shift = fsize == 32 ? 0 : 48;
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.movd(tmp.cvt32(), xmm0);
|
||||
} else {
|
||||
// We do this to avoid requiring 64-bit immediates
|
||||
|
|
@ -234,7 +252,7 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X
|
|||
// op1 == QNaN && op2 == SNaN <<< The problematic case
|
||||
// op1 == QNaN && op2 == Inf
|
||||
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.movd(tmp.cvt32(), op2);
|
||||
code.shl(tmp.cvt32(), 32 - mantissa_msb_bit);
|
||||
} else {
|
||||
|
|
@ -273,7 +291,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
|
|||
if (ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) {
|
||||
// Do nothing
|
||||
} else if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN(code, result, fsize);
|
||||
ForceToDefaultNaN<fsize>(code, result);
|
||||
} else {
|
||||
PostProcessNaN<fsize>(code, result, xmm0);
|
||||
}
|
||||
|
|
@ -284,7 +302,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
|
|||
|
||||
template<size_t fsize, typename Function>
|
||||
void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
|
|
@ -299,7 +317,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn)
|
|||
}
|
||||
|
||||
if (!ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) {
|
||||
ForceToDefaultNaN(code, result, fsize);
|
||||
ForceToDefaultNaN<fsize>(code, result);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
|
|
@ -343,7 +361,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn)
|
|||
|
||||
template<size_t fsize>
|
||||
void FPAbs(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT non_sign_mask = FP::FPInfo<FPT>::sign_mask - FPT(1u);
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
@ -369,7 +387,7 @@ void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
void FPNeg(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT sign_mask = FP::FPInfo<FPT>::sign_mask;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
@ -424,7 +442,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
FCODE(ucomis)(result, operand);
|
||||
code.jz(*equal, code.T_NEAR);
|
||||
if (is_max) {
|
||||
if constexpr (is_max) {
|
||||
FCODE(maxs)(result, operand);
|
||||
} else {
|
||||
FCODE(mins)(result, operand);
|
||||
|
|
@ -436,7 +454,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
code.L(*equal);
|
||||
code.jp(nan);
|
||||
if (is_max) {
|
||||
if constexpr (is_max) {
|
||||
code.andps(result, operand);
|
||||
} else {
|
||||
code.orps(result, operand);
|
||||
|
|
@ -459,7 +477,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize, bool is_max>
|
||||
static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) noexcept {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
@ -484,7 +502,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::
|
|||
tmp.setBit(fsize);
|
||||
|
||||
const auto move_to_tmp = [=, &code](const Xbyak::Xmm& xmm) {
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.movd(tmp.cvt32(), xmm);
|
||||
} else {
|
||||
code.movq(tmp.cvt64(), xmm);
|
||||
|
|
@ -495,7 +513,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::
|
|||
|
||||
FCODE(ucomis)(op1, op2);
|
||||
code.jz(*z, code.T_NEAR);
|
||||
if (is_max) {
|
||||
if constexpr (is_max) {
|
||||
FCODE(maxs)(op2, op1);
|
||||
} else {
|
||||
FCODE(mins)(op2, op1);
|
||||
|
|
@ -509,7 +527,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::
|
|||
|
||||
code.L(*z);
|
||||
code.jp(nan);
|
||||
if (is_max) {
|
||||
if constexpr (is_max) {
|
||||
code.andps(op2, op1);
|
||||
} else {
|
||||
code.orps(op2, op1);
|
||||
|
|
@ -611,12 +629,12 @@ void EmitX64::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize, bool negate_product>
|
||||
static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
const auto fallback_fn = negate_product ? &FP::FPMulSub<FPT> : &FP::FPMulAdd<FPT>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
const bool needs_rounding_correction = ctx.FPCR().FZ();
|
||||
const bool needs_nan_correction = !ctx.FPCR().DN();
|
||||
|
||||
|
|
@ -625,13 +643,13 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Xmm operand2 = ctx.reg_alloc.UseXmm(args[1]);
|
||||
const Xbyak::Xmm operand3 = ctx.reg_alloc.UseXmm(args[2]);
|
||||
|
||||
if (negate_product) {
|
||||
if constexpr (negate_product) {
|
||||
FCODE(vfnmadd231s)(result, operand2, operand3);
|
||||
} else {
|
||||
FCODE(vfmadd231s)(result, operand2, operand3);
|
||||
}
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN(code, result, fsize);
|
||||
ForceToDefaultNaN<fsize>(code, result);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
|
|
@ -647,7 +665,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
code.movaps(result, operand1);
|
||||
if (negate_product) {
|
||||
if constexpr (negate_product) {
|
||||
FCODE(vfnmadd231s)(result, operand2, operand3);
|
||||
} else {
|
||||
FCODE(vfmadd231s)(result, operand2, operand3);
|
||||
|
|
@ -668,8 +686,9 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, fsize);
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<fsize>(code, result);
|
||||
}
|
||||
code.L(*end);
|
||||
|
||||
ctx.deferred_emits.emplace_back([=, &code, &ctx] {
|
||||
|
|
@ -750,7 +769,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.ptest(operand2, xmm0);
|
||||
code.jnz(op2_done);
|
||||
code.vorps(result, operand2, xmm0);
|
||||
if (negate_product) {
|
||||
if constexpr (negate_product) {
|
||||
code.xorps(result, code.Const(xword, FP::FPInfo<FPT>::sign_mask));
|
||||
}
|
||||
code.jmp(*end);
|
||||
|
|
@ -766,7 +785,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
// at this point, all SNaNs have been handled
|
||||
// if op1 was not a QNaN and op2 is, negate the result
|
||||
if (negate_product) {
|
||||
if constexpr (negate_product) {
|
||||
FCODE(ucomis)(operand1, operand1);
|
||||
code.jp(*end);
|
||||
FCODE(ucomis)(operand2, operand2);
|
||||
|
|
@ -787,7 +806,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Xmm operand2 = ctx.reg_alloc.UseScratchXmm(args[1]);
|
||||
const Xbyak::Xmm operand3 = ctx.reg_alloc.UseXmm(args[2]);
|
||||
|
||||
if (negate_product) {
|
||||
if constexpr (negate_product) {
|
||||
code.xorps(operand2, code.Const(xword, FP::FPInfo<FPT>::sign_mask));
|
||||
}
|
||||
FCODE(muls)(operand2, operand3);
|
||||
|
|
@ -838,7 +857,7 @@ void EmitX64::EmitFPMulSub64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
|
|
@ -898,9 +917,9 @@ void EmitX64::EmitFPMulX64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const Xbyak::Xmm operand = ctx.reg_alloc.UseXmm(args[0]);
|
||||
|
|
@ -909,7 +928,7 @@ static void EmitFPRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
FCODE(vrcp14s)(result, operand, operand);
|
||||
} else {
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.rcpss(result, operand);
|
||||
} else {
|
||||
code.cvtsd2ss(result, operand);
|
||||
|
|
@ -944,7 +963,7 @@ void EmitX64::EmitFPRecipEstimate64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPRecipExponent(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||
|
|
@ -967,11 +986,11 @@ void EmitX64::EmitFPRecipExponent64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
if (code.HasHostFeature(HostFeature::FMA) && ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) {
|
||||
Xbyak::Label end, fallback;
|
||||
|
||||
|
|
@ -1104,9 +1123,9 @@ void EmitX64::EmitFPRoundInt64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const Xbyak::Xmm operand = ctx.reg_alloc.UseXmm(args[0]);
|
||||
|
|
@ -1115,7 +1134,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
FCODE(vrsqrt14s)(result, operand, operand);
|
||||
} else {
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.rsqrtss(result, operand);
|
||||
} else {
|
||||
code.cvtsd2ss(result, operand);
|
||||
|
|
@ -1161,7 +1180,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
bool needs_fallback = false;
|
||||
|
||||
code.L(*bad_values);
|
||||
if (fsize == 32) {
|
||||
if constexpr (fsize == 32) {
|
||||
code.movd(tmp, operand);
|
||||
|
||||
if (!ctx.FPCR().FZ()) {
|
||||
|
|
@ -1283,11 +1302,11 @@ void EmitX64::EmitFPRSqrtEstimate64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
if (code.HasHostFeature(HostFeature::FMA | HostFeature::AVX) && ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) {
|
||||
const Xbyak::Xmm operand1 = ctx.reg_alloc.UseXmm(args[0]);
|
||||
const Xbyak::Xmm operand2 = ctx.reg_alloc.UseXmm(args[1]);
|
||||
|
|
@ -1466,8 +1485,9 @@ void EmitX64::EmitFPHalfToDouble(EmitContext& ctx, IR::Inst* inst) {
|
|||
// Double-conversion here is acceptable as this is expanding precision.
|
||||
code.vcvtph2ps(result, value);
|
||||
code.vcvtps2pd(result, result);
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, 64);
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<64>(code, result);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
return;
|
||||
|
|
@ -1489,8 +1509,9 @@ void EmitX64::EmitFPHalfToSingle(EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Xmm value = ctx.reg_alloc.UseXmm(args[0]);
|
||||
|
||||
code.vcvtph2ps(result, value);
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, 32);
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<32>(code, result);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
return;
|
||||
|
|
@ -1498,22 +1519,23 @@ void EmitX64::EmitFPHalfToSingle(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
|
||||
code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode));
|
||||
code.mov(code.ABI_PARAM3.cvt32(), static_cast<u32>(rounding_mode));
|
||||
code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||
code.CallFunction(&FP::FPConvert<u32, u16>);
|
||||
}
|
||||
|
||||
void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const auto rounding_mode = FP::RoundingMode(args[1].GetImmediateU8());
|
||||
const auto rounding_mode = static_cast<FP::RoundingMode>(args[1].GetImmediateU8());
|
||||
|
||||
// We special-case the non-IEEE-defined ToOdd rounding mode.
|
||||
if (rounding_mode == ctx.FPCR().RMode() && rounding_mode != FP::RoundingMode::ToOdd) {
|
||||
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
|
||||
code.cvtss2sd(result, result);
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, 64);
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<64>(code, result);
|
||||
}
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
} else {
|
||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||
|
|
@ -1531,9 +1553,12 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) {
|
||||
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, 32);
|
||||
code.vcvtps2ph(result, result, u8(*round_imm));
|
||||
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<32>(code, result);
|
||||
}
|
||||
code.vcvtps2ph(result, result, static_cast<u8>(*round_imm));
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1561,18 +1586,21 @@ void EmitX64::EmitFPDoubleToHalf(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const auto rounding_mode = FP::RoundingMode(args[1].GetImmediateU8());
|
||||
const auto rounding_mode = static_cast<FP::RoundingMode>(args[1].GetImmediateU8());
|
||||
|
||||
// We special-case the non-IEEE-defined ToOdd rounding mode.
|
||||
if (rounding_mode == ctx.FPCR().RMode() && rounding_mode != FP::RoundingMode::ToOdd) {
|
||||
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
|
||||
code.cvtsd2ss(result, result);
|
||||
if (ctx.FPCR().DN())
|
||||
ForceToDefaultNaN(code, result, 32);
|
||||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<32>(code, result);
|
||||
}
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
} else {
|
||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
|
||||
code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode));
|
||||
code.mov(code.ABI_PARAM3.cvt32(), static_cast<u32>(rounding_mode));
|
||||
code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||
code.CallFunction(&FP::FPConvert<u32, u64>);
|
||||
}
|
||||
|
|
@ -1587,7 +1615,7 @@ void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
|
|||
/// Better than spamming thousands of templates aye?
|
||||
template<size_t fsize>
|
||||
static u64 EmitFPToFixedThunk(u64 input, FP::FPSR& fpsr, FP::FPCR fpcr, u32 extra_args) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
auto const unsigned_ = ((extra_args >> 24) & 0xff) != 0;
|
||||
auto const isize = ((extra_args >> 16) & 0xff);
|
||||
auto const rounding = FP::RoundingMode((extra_args >> 8) & 0xff);
|
||||
|
|
@ -1602,7 +1630,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const size_t fbits = args[1].GetImmediateU8();
|
||||
const auto rounding_mode = FP::RoundingMode(args[2].GetImmediateU8());
|
||||
|
||||
if (fsize != 16) {
|
||||
if constexpr (fsize != 16) {
|
||||
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode);
|
||||
|
||||
// cvttsd2si truncates during operation so rounding (and thus SSE4.1) not required
|
||||
|
|
@ -1612,7 +1640,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr().cvt64();
|
||||
|
||||
if (fsize == 64) {
|
||||
if constexpr (fsize == 64) {
|
||||
if (fbits != 0) {
|
||||
const u64 scale_factor = static_cast<u64>((fbits + 1023) << 52);
|
||||
code.mulsd(src, code.Const(xword, scale_factor));
|
||||
|
|
@ -1634,13 +1662,13 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.cvtss2sd(src, src);
|
||||
}
|
||||
|
||||
if (isize == 64) {
|
||||
if constexpr (isize == 64) {
|
||||
const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
if (!unsigned_) {
|
||||
SharedLabel saturate_max = GenSharedLabel(), end = GenSharedLabel();
|
||||
|
||||
ZeroIfNaN(code, src, scratch, 64);
|
||||
ZeroIfNaN<64>(code, src, scratch);
|
||||
|
||||
code.movsd(scratch, code.Const(xword, f64_max_s64_lim));
|
||||
code.comisd(scratch, src);
|
||||
|
|
@ -1678,11 +1706,11 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
code.sar(result2, 63);
|
||||
code.or_(result, result2);
|
||||
}
|
||||
} else if (isize == 32) {
|
||||
} else if constexpr (isize == 32) {
|
||||
if (!unsigned_) {
|
||||
const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
ZeroIfNaN(code, src, scratch, 64);
|
||||
ZeroIfNaN<64>(code, src, scratch);
|
||||
code.minsd(src, code.Const(xword, f64_max_s32));
|
||||
// maxsd not required as cvttsd2si results in 0x8000'0000 when out of range
|
||||
code.cvttsd2si(result.cvt32(), src); // 32 bit gpr
|
||||
|
|
@ -1695,7 +1723,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
} else {
|
||||
const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm();
|
||||
|
||||
ZeroIfNaN(code, src, scratch, 64);
|
||||
ZeroIfNaN<64>(code, src, scratch);
|
||||
code.maxsd(src, code.Const(xword, unsigned_ ? f64_min_u16 : f64_min_s16));
|
||||
code.minsd(src, code.Const(xword, unsigned_ ? f64_max_u16 : f64_max_s16));
|
||||
code.cvttsd2si(result, src); // 64 bit gpr
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
#include <mcl/macro/concatenate_tokens.hpp>
|
||||
#include "dynarmic/common/type_util.h"
|
||||
|
||||
#define AxxEmitX64 CONCATENATE_TOKENS(Axx, EmitX64)
|
||||
#define AxxEmitContext CONCATENATE_TOKENS(Axx, EmitContext)
|
||||
|
|
@ -16,11 +15,14 @@ using Vector = std::array<u64, 2>;
|
|||
}
|
||||
|
||||
std::optional<AxxEmitX64::DoNotFastmemMarker> AxxEmitX64::ShouldFastmem(AxxEmitContext& ctx, IR::Inst* inst) const {
|
||||
if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem())
|
||||
if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto marker = std::make_tuple(ctx.Location(), inst->GetName());
|
||||
if (do_not_fastmem.count(marker) > 0)
|
||||
if (do_not_fastmem.count(marker) > 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return marker;
|
||||
}
|
||||
|
||||
|
|
@ -56,12 +58,16 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
// Neither fastmem nor page table: Use callbacks
|
||||
if constexpr (bitsize == 128) {
|
||||
ctx.reg_alloc.HostCall(nullptr, {}, args[1]);
|
||||
if (ordered) code.mfence();
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
}
|
||||
code.CallFunction(memory_read_128);
|
||||
ctx.reg_alloc.DefineValue(inst, xmm1);
|
||||
} else {
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[1]);
|
||||
if (ordered) code.mfence();
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
}
|
||||
Devirtualize<callback>(conf.callbacks).EmitCall(code);
|
||||
code.ZeroExtendFrom(bitsize, code.ABI_RETURN);
|
||||
}
|
||||
|
|
@ -96,10 +102,10 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
code.call(wrapped_fn);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
std::bit_cast<u64>(location),
|
||||
mcl::bit_cast<u64>(location),
|
||||
FastmemPatchInfo{
|
||||
std::bit_cast<u64>(code.getCurr()),
|
||||
std::bit_cast<u64>(wrapped_fn),
|
||||
mcl::bit_cast<u64>(code.getCurr()),
|
||||
mcl::bit_cast<u64>(wrapped_fn),
|
||||
*fastmem_marker,
|
||||
conf.recompile_on_fastmem_failure,
|
||||
});
|
||||
|
|
@ -147,7 +153,9 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
ctx.reg_alloc.HostCall(nullptr, {}, args[1], args[2]);
|
||||
Devirtualize<callback>(conf.callbacks).EmitCall(code);
|
||||
}
|
||||
if (ordered) code.mfence();
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
}
|
||||
EmitCheckMemoryAbort(ctx, inst);
|
||||
return;
|
||||
}
|
||||
|
|
@ -181,10 +189,10 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
code.call(wrapped_fn);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
std::bit_cast<u64>(location),
|
||||
mcl::bit_cast<u64>(location),
|
||||
FastmemPatchInfo{
|
||||
std::bit_cast<u64>(code.getCurr()),
|
||||
std::bit_cast<u64>(wrapped_fn),
|
||||
mcl::bit_cast<u64>(code.getCurr()),
|
||||
mcl::bit_cast<u64>(wrapped_fn),
|
||||
*fastmem_marker,
|
||||
conf.recompile_on_fastmem_failure,
|
||||
});
|
||||
|
|
@ -215,7 +223,7 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
const bool ordered = IsOrdered(args[2].GetImmediateAccType());
|
||||
|
||||
if constexpr (bitsize != 128) {
|
||||
using T = Common::UnsignedIntegerN<bitsize>;
|
||||
using T = mcl::unsigned_integer_of_size<bitsize>;
|
||||
|
||||
ctx.reg_alloc.HostCall(inst, {}, args[1]);
|
||||
|
||||
|
|
@ -282,14 +290,16 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0));
|
||||
code.mov(code.ABI_PARAM1, reinterpret_cast<u64>(&conf));
|
||||
if constexpr (bitsize != 128) {
|
||||
using T = Common::UnsignedIntegerN<bitsize>;
|
||||
using T = mcl::unsigned_integer_of_size<bitsize>;
|
||||
|
||||
code.CallLambda(
|
||||
[](AxxUserConfig& conf, Axx::VAddr vaddr, T value) -> u32 {
|
||||
return conf.global_monitor->DoExclusiveOperation<T>(conf.processor_id, vaddr,
|
||||
[&](T expected) -> bool {
|
||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||
}) ? 0 : 1;
|
||||
[&](T expected) -> bool {
|
||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||
})
|
||||
? 0
|
||||
: 1;
|
||||
});
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
|
|
@ -301,9 +311,11 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) {
|
|||
code.CallLambda(
|
||||
[](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& value) -> u32 {
|
||||
return conf.global_monitor->DoExclusiveOperation<Vector>(conf.processor_id, vaddr,
|
||||
[&](Vector expected) -> bool {
|
||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||
}) ? 0 : 1;
|
||||
[&](Vector expected) -> bool {
|
||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||
})
|
||||
? 0
|
||||
: 1;
|
||||
});
|
||||
if (ordered) {
|
||||
code.mfence();
|
||||
|
|
@ -344,7 +356,7 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in
|
|||
EmitExclusiveLock(code, conf, tmp, tmp2.cvt32());
|
||||
|
||||
code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(1));
|
||||
code.mov(tmp, std::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(tmp, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(qword[tmp], vaddr);
|
||||
|
||||
const auto fastmem_marker = ShouldFastmem(ctx, inst);
|
||||
|
|
@ -357,10 +369,10 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in
|
|||
const auto location = EmitReadMemoryMov<bitsize>(code, value_idx, src_ptr, ordered);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
std::bit_cast<u64>(location),
|
||||
mcl::bit_cast<u64>(location),
|
||||
FastmemPatchInfo{
|
||||
std::bit_cast<u64>(code.getCurr()),
|
||||
std::bit_cast<u64>(wrapped_fn),
|
||||
mcl::bit_cast<u64>(code.getCurr()),
|
||||
mcl::bit_cast<u64>(wrapped_fn),
|
||||
*fastmem_marker,
|
||||
conf.recompile_on_exclusive_fastmem_failure,
|
||||
});
|
||||
|
|
@ -378,7 +390,7 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in
|
|||
code.call(wrapped_fn);
|
||||
}
|
||||
|
||||
code.mov(tmp, std::bit_cast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(tmp, mcl::bit_cast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
EmitWriteMemoryMov<bitsize>(code, tmp, value_idx, false);
|
||||
|
||||
EmitExclusiveUnlock(code, conf, tmp, tmp2.cvt32());
|
||||
|
|
@ -425,7 +437,7 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i
|
|||
|
||||
SharedLabel end = GenSharedLabel();
|
||||
|
||||
code.mov(tmp, std::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(tmp, mcl::bit_cast<u64>(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(status, u32(1));
|
||||
code.cmp(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0));
|
||||
code.je(*end, code.T_NEAR);
|
||||
|
|
@ -435,7 +447,7 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i
|
|||
EmitExclusiveTestAndClear(code, conf, vaddr, tmp, rax);
|
||||
|
||||
code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0));
|
||||
code.mov(tmp, std::bit_cast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
code.mov(tmp, mcl::bit_cast<u64>(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id)));
|
||||
|
||||
if constexpr (bitsize == 128) {
|
||||
code.mov(rax, qword[tmp + 0]);
|
||||
|
|
@ -463,20 +475,25 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i
|
|||
const auto location = code.getCurr();
|
||||
|
||||
if constexpr (bitsize == 128) {
|
||||
code.lock(); code.cmpxchg16b(ptr[dest_ptr]);
|
||||
code.lock();
|
||||
code.cmpxchg16b(ptr[dest_ptr]);
|
||||
} else {
|
||||
switch (bitsize) {
|
||||
case 8:
|
||||
code.lock(); code.cmpxchg(code.byte[dest_ptr], value.cvt8());
|
||||
code.lock();
|
||||
code.cmpxchg(code.byte[dest_ptr], value.cvt8());
|
||||
break;
|
||||
case 16:
|
||||
code.lock(); code.cmpxchg(word[dest_ptr], value.cvt16());
|
||||
code.lock();
|
||||
code.cmpxchg(word[dest_ptr], value.cvt16());
|
||||
break;
|
||||
case 32:
|
||||
code.lock(); code.cmpxchg(dword[dest_ptr], value.cvt32());
|
||||
code.lock();
|
||||
code.cmpxchg(dword[dest_ptr], value.cvt32());
|
||||
break;
|
||||
case 64:
|
||||
code.lock(); code.cmpxchg(qword[dest_ptr], value.cvt64());
|
||||
code.lock();
|
||||
code.cmpxchg(qword[dest_ptr], value.cvt64());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
|
@ -489,10 +506,10 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i
|
|||
code.call(wrapped_fn);
|
||||
|
||||
fastmem_patch_info.emplace(
|
||||
std::bit_cast<u64>(location),
|
||||
mcl::bit_cast<u64>(location),
|
||||
FastmemPatchInfo{
|
||||
std::bit_cast<u64>(code.getCurr()),
|
||||
std::bit_cast<u64>(wrapped_fn),
|
||||
mcl::bit_cast<u64>(code.getCurr()),
|
||||
mcl::bit_cast<u64>(wrapped_fn),
|
||||
*fastmem_marker,
|
||||
conf.recompile_on_exclusive_fastmem_failure,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <numeric>
|
||||
#include <bit>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/a32_emit_x64.h"
|
||||
|
|
@ -346,7 +342,7 @@ void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 p
|
|||
return;
|
||||
}
|
||||
|
||||
code.mov(pointer, std::bit_cast<u64>(GetExclusiveMonitorLockPointer(conf.global_monitor)));
|
||||
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorLockPointer(conf.global_monitor)));
|
||||
EmitSpinLockLock(code, pointer, tmp);
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +352,7 @@ void EmitExclusiveUnlock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64
|
|||
return;
|
||||
}
|
||||
|
||||
code.mov(pointer, std::bit_cast<u64>(GetExclusiveMonitorLockPointer(conf.global_monitor)));
|
||||
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorLockPointer(conf.global_monitor)));
|
||||
EmitSpinLockUnlock(code, pointer, tmp);
|
||||
}
|
||||
|
||||
|
|
@ -373,7 +369,7 @@ void EmitExclusiveTestAndClear(BlockOfCode& code, const UserConfig& conf, Xbyak:
|
|||
continue;
|
||||
}
|
||||
Xbyak::Label ok;
|
||||
code.mov(pointer, std::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.jne(ok, code.T_NEAR);
|
||||
code.mov(qword[pointer], tmp);
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@
|
|||
#include "dynarmic/common/assert.h"
|
||||
#include <mcl/bit/bit_field.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
|
||||
#include "dynarmic/backend/x64/block_of_code.h"
|
||||
#include "dynarmic/backend/x64/emit_x64.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
#include "dynarmic/common/fp/util.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
|
@ -39,7 +38,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
|
|||
Xbyak::Reg addend = ctx.reg_alloc.UseGpr(args[1]).changeBit(size);
|
||||
Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr().changeBit(size);
|
||||
|
||||
constexpr u64 int_max = static_cast<u64>((std::numeric_limits<Common::SignedIntegerN<size>>::max)());
|
||||
constexpr u64 int_max = static_cast<u64>((std::numeric_limits<mcl::signed_integer_of_size<size>>::max)());
|
||||
if constexpr (size < 64) {
|
||||
code.xor_(overflow.cvt32(), overflow.cvt32());
|
||||
code.bt(result.cvt32(), size - 1);
|
||||
|
|
@ -83,7 +82,7 @@ void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst
|
|||
Xbyak::Reg op_result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(size);
|
||||
Xbyak::Reg addend = ctx.reg_alloc.UseScratchGpr(args[1]).changeBit(size);
|
||||
|
||||
constexpr u64 boundary = op == Op::Add ? (std::numeric_limits<Common::UnsignedIntegerN<size>>::max)() : 0;
|
||||
constexpr u64 boundary = op == Op::Add ? (std::numeric_limits<mcl::unsigned_integer_of_size<size>>::max)() : 0;
|
||||
|
||||
if constexpr (op == Op::Add) {
|
||||
code.add(op_result, addend);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <mcl/mp/typelist/list.hpp>
|
||||
#include <mcl/mp/typelist/lower_to_tuple.hpp>
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
#include <mcl/type_traits/integer_of_size.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/abi.h"
|
||||
|
|
@ -30,14 +31,27 @@
|
|||
#include "dynarmic/common/fp/info.h"
|
||||
#include "dynarmic/common/fp/op.h"
|
||||
#include "dynarmic/common/fp/util.h"
|
||||
#include "dynarmic/common/type_util.h"
|
||||
#include "dynarmic/common/lut_from_list.h"
|
||||
#include "dynarmic/interface/optimization_flags.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
|
||||
#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
#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 {
|
||||
|
||||
|
|
@ -62,7 +76,7 @@ void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_cont
|
|||
template<size_t fsize, template<typename> class Indexer, size_t narg>
|
||||
struct NaNHandler {
|
||||
public:
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
using function_type = void (*)(std::array<VectorArray<FPT>, narg>&, FP::FPCR);
|
||||
|
||||
|
|
@ -144,33 +158,33 @@ Xbyak::Address GetVectorOf(BlockOfCode& code) {
|
|||
|
||||
template<size_t fsize>
|
||||
Xbyak::Address GetNaNVector(BlockOfCode& code) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
return GetVectorOf<fsize, FP::FPInfo<FPT>::DefaultNaN()>(code);
|
||||
}
|
||||
|
||||
template<size_t fsize>
|
||||
Xbyak::Address GetNegativeZeroVector(BlockOfCode& code) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
return GetVectorOf<fsize, FP::FPInfo<FPT>::Zero(true)>(code);
|
||||
}
|
||||
|
||||
template<size_t fsize>
|
||||
Xbyak::Address GetNonSignMaskVector(BlockOfCode& code) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT non_sign_mask = FP::FPInfo<FPT>::exponent_mask | FP::FPInfo<FPT>::mantissa_mask;
|
||||
return GetVectorOf<fsize, non_sign_mask>(code);
|
||||
}
|
||||
|
||||
template<size_t fsize>
|
||||
Xbyak::Address GetSmallestNormalVector(BlockOfCode& code) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT smallest_normal_number = FP::FPValue<FPT, false, FP::FPInfo<FPT>::exponent_min, 1>();
|
||||
return GetVectorOf<fsize, smallest_normal_number>(code);
|
||||
}
|
||||
|
||||
template<size_t fsize, bool sign, int exponent, Common::UnsignedIntegerN<fsize> value>
|
||||
template<size_t fsize, bool sign, int exponent, mcl::unsigned_integer_of_size<fsize> value>
|
||||
Xbyak::Address GetVectorOf(BlockOfCode& code) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
return GetVectorOf<fsize, FP::FPValue<FPT, sign, exponent, value>()>(code);
|
||||
}
|
||||
|
||||
|
|
@ -1071,7 +1085,7 @@ static void EmitFPVectorMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::I
|
|||
|
||||
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
// result = xmm_a == SNaN || xmm_b == QNaN
|
||||
{
|
||||
|
|
@ -1144,7 +1158,7 @@ static void EmitFPVectorMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::I
|
|||
}
|
||||
|
||||
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
// result = xmm_a == SNaN || xmm_b == QNaN
|
||||
{
|
||||
|
|
@ -1300,7 +1314,7 @@ static void EmitFPVectorMulAddFallback(VectorArray<FPT>& result, const VectorArr
|
|||
|
||||
template<size_t fsize>
|
||||
void EmitFPVectorMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
const auto fallback_fn = [](VectorArray<FPT>& result, const VectorArray<FPT>& addend, const VectorArray<FPT>& op1, const VectorArray<FPT>& op2, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
|
|
@ -1411,7 +1425,7 @@ void EmitX64::EmitFPVectorMulAdd64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitFPVectorMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const bool fpcr_controlled = args[2].GetImmediateU1();
|
||||
|
|
@ -1477,7 +1491,7 @@ void EmitX64::EmitFPVectorMulX64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
void FPVectorNeg(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
constexpr FPT sign_mask = FP::FPInfo<FPT>::sign_mask;
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
@ -1530,7 +1544,7 @@ void EmitX64::EmitFPVectorPairedAddLower64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
if constexpr (fsize != 16) {
|
||||
if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) {
|
||||
|
|
@ -1576,7 +1590,7 @@ void EmitX64::EmitFPVectorRecipEstimate64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
const auto fallback_fn = [](VectorArray<FPT>& result, const VectorArray<FPT>& op1, const VectorArray<FPT>& op2, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
|
|
@ -1700,7 +1714,7 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
}
|
||||
|
||||
// Do not make a LUT out of this, let the compiler do it's thing
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
switch (rounding) {
|
||||
case FP::RoundingMode::ToNearest_TieEven:
|
||||
exact
|
||||
|
|
@ -1746,7 +1760,7 @@ void EmitX64::EmitFPVectorRoundInt64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
const auto fallback_fn = [](VectorArray<FPT>& result, const VectorArray<FPT>& operand, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
|
|
@ -1838,7 +1852,7 @@ void EmitX64::EmitFPVectorRSqrtEstimate64(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
template<size_t fsize>
|
||||
static void EmitRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>;
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||
|
||||
const auto fallback_fn = [](VectorArray<FPT>& result, const VectorArray<FPT>& op1, const VectorArray<FPT>& op2, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||
for (size_t i = 0; i < result.size(); i++) {
|
||||
|
|
@ -2112,7 +2126,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
FCODE(orp)(src, exceed_unsigned);
|
||||
}
|
||||
} else {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>; // WORKAROUND: For issue 678 on MSVC
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
|
||||
constexpr u64 integer_max = FPT((std::numeric_limits<std::conditional_t<unsigned_, FPT, std::make_signed_t<FPT>>>::max)());
|
||||
|
||||
code.movaps(xmm0, GetVectorOf<fsize, float_upper_limit_signed>(code));
|
||||
|
|
@ -2136,7 +2150,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
||||
|
||||
static const auto lut = Common::GenerateLookupTableFromList([]<typename I>(I) {
|
||||
using FPT = Common::UnsignedIntegerN<fsize>; // WORKAROUND: For issue 678 on MSVC
|
||||
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
|
||||
return std::pair{
|
||||
mp::lower_to_tuple_v<I>,
|
||||
Common::FptrCast([](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,23 @@
|
|||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
||||
#define FCODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##s(args...); else code.NAME##d(args...); }
|
||||
#define ICODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##d(args...); else code.NAME##q(args...); }
|
||||
#define FCODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (esize == 32) { \
|
||||
code.NAME##s(args...); \
|
||||
} else { \
|
||||
code.NAME##d(args...); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ICODE(NAME) \
|
||||
[&code](auto... args) { \
|
||||
if constexpr (esize == 32) { \
|
||||
code.NAME##d(args...); \
|
||||
} else { \
|
||||
code.NAME##q(args...); \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/backend/exception_handler.h"
|
||||
|
|
@ -184,20 +184,20 @@ struct ExceptionHandler::Impl final {
|
|||
// Our 3rd argument is a PCONTEXT.
|
||||
|
||||
// If not within our codeblock, ignore this exception.
|
||||
code.mov(code.rax, Safe::Negate(std::bit_cast<u64>(code.getCode())));
|
||||
code.mov(code.rax, Safe::Negate(mcl::bit_cast<u64>(code.getCode())));
|
||||
code.add(code.rax, code.qword[code.ABI_PARAM3 + Xbyak::RegExp(offsetof(CONTEXT, Rip))]);
|
||||
code.cmp(code.rax, static_cast<u32>(code.GetTotalCodeSize()));
|
||||
code.ja(exception_handler_without_cb);
|
||||
|
||||
code.lea(code.rsp, code.ptr[code.rsp - 8]);
|
||||
code.mov(code.ABI_PARAM1, std::bit_cast<u64>(&cb));
|
||||
code.mov(code.ABI_PARAM1, mcl::bit_cast<u64>(&cb));
|
||||
code.mov(code.ABI_PARAM2, code.ABI_PARAM3);
|
||||
code.CallLambda(
|
||||
[](const std::function<FakeCall(u64)>& cb_, PCONTEXT ctx) {
|
||||
FakeCall fc = cb_(ctx->Rip);
|
||||
|
||||
ctx->Rsp -= sizeof(u64);
|
||||
*std::bit_cast<u64*>(ctx->Rsp) = fc.ret_rip;
|
||||
*mcl::bit_cast<u64*>(ctx->Rsp) = fc.ret_rip;
|
||||
ctx->Rip = fc.call_rip;
|
||||
});
|
||||
code.add(code.rsp, 8);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -9,8 +6,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <bit>
|
||||
#include <numeric>
|
||||
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
|
|
@ -20,7 +17,7 @@ void PerfMapRegister(const void* start, const void* end, std::string_view friend
|
|||
|
||||
template<typename T>
|
||||
void PerfMapRegister(T start, const void* end, std::string_view friendly_name) {
|
||||
detail::PerfMapRegister(std::bit_cast<const void*>(start), end, friendly_name);
|
||||
detail::PerfMapRegister(mcl::bit_cast<const void*>(start), end, friendly_name);
|
||||
}
|
||||
|
||||
void PerfMapClear();
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <bit>
|
||||
|
||||
#include <fmt/ostream.h>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/abi.h"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2023 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Dynarmic::Common {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool always_false_v = false;
|
||||
|
||||
} // namespace Dynarmic::Common
|
||||
|
|
@ -16,33 +16,38 @@ template<typename... Ts>
|
|||
|
||||
// Temporary until MCL is fully removed
|
||||
#ifndef ASSERT_MSG
|
||||
# define ASSERT_MSG(_a_, ...) do if (!(_a_)) [[unlikely]] assert_terminate(#_a_, __VA_ARGS__); while(0)
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
([&]() { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
assert_terminate(#_a_, __VA_ARGS__); \
|
||||
} \
|
||||
}())
|
||||
#endif
|
||||
#ifndef ASSERT_FALSE
|
||||
# define ASSERT_FALSE(...) assert_terminate("false", __VA_ARGS__)
|
||||
#define ASSERT_FALSE(...) \
|
||||
([&]() { \
|
||||
assert_terminate("false", __VA_ARGS__); \
|
||||
}())
|
||||
#endif
|
||||
|
||||
#ifndef ASSERT
|
||||
# define ASSERT(_a_) ASSERT_MSG(_a_, "")
|
||||
#define ASSERT(_a_) ASSERT_MSG(_a_, "")
|
||||
#endif
|
||||
#ifndef UNREACHABLE
|
||||
# ifdef _MSC_VER
|
||||
# define UNREACHABLE() ASSERT_FALSE("unreachable")
|
||||
# else
|
||||
# define UNREACHABLE() __builtin_unreachable();
|
||||
# endif
|
||||
#define UNREACHABLE() ASSERT_MSG(false, "unreachable")
|
||||
#endif
|
||||
#ifdef _DEBUG
|
||||
# ifndef DEBUG_ASSERT
|
||||
# define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
# endif
|
||||
# ifndef DEBUG_ASSERT_MSG
|
||||
# define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__)
|
||||
# endif
|
||||
#else // not debug
|
||||
# ifndef DEBUG_ASSERT
|
||||
# define DEBUG_ASSERT(_a_)
|
||||
# endif
|
||||
# ifndef DEBUG_ASSERT_MSG
|
||||
# define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
|
||||
# endif
|
||||
#ifndef DEBUG_ASSERT
|
||||
#define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
#endif
|
||||
#ifndef DEBUG_ASSERT_MSG
|
||||
#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__)
|
||||
#endif
|
||||
#else // not debug
|
||||
#ifndef DEBUG_ASSERT
|
||||
#define DEBUG_ASSERT(_a_)
|
||||
#endif
|
||||
#ifndef DEBUG_ASSERT_MSG
|
||||
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
namespace Dynarmic::Common {
|
||||
|
||||
/// Cast a lambda into an equivalent function pointer.
|
||||
template<class Function>
|
||||
inline auto FptrCast(Function f) noexcept {
|
||||
return static_cast<mcl::equivalent_function_type<Function>*>(f);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Common
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
|
|
@ -9,7 +6,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <cstdint>
|
||||
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/common/fp/info.h"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <string>
|
||||
#include <bit>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#ifdef DYNARMIC_USE_LLVM
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#endif
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/common/llvm_disassemble.h"
|
||||
|
|
@ -52,7 +53,7 @@ std::string DisassembleX64(const void* begin, const void* end) {
|
|||
LLVMDisasmDispose(llvm_ctx);
|
||||
#else
|
||||
result += fmt::format("(recompile with DYNARMIC_USE_LLVM=ON to disassemble the generated x86_64 code)\n");
|
||||
result += fmt::format("start: {:016x}, end: {:016x}\n", std::bit_cast<u64>(begin), std::bit_cast<u64>(end));
|
||||
result += fmt::format("start: {:016x}, end: {:016x}\n", mcl::bit_cast<u64>(begin), mcl::bit_cast<u64>(end));
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
namespace Dynarmic::Common {
|
||||
|
||||
/// Cast a lambda into an equivalent function pointer.
|
||||
template<class Function>
|
||||
inline auto FptrCast(Function f) noexcept {
|
||||
return static_cast<mcl::equivalent_function_type<Function>*>(f);
|
||||
}
|
||||
|
||||
namespace Detail {
|
||||
template<std::size_t size> struct IntegerOfSize {};
|
||||
template<> struct IntegerOfSize<8> { using U = std::uint8_t; using S = std::int8_t; };
|
||||
template<> struct IntegerOfSize<16> { using U = std::uint16_t; using S = std::int16_t; };
|
||||
template<> struct IntegerOfSize<32> { using U = std::uint32_t; using S = std::int32_t; };
|
||||
template<> struct IntegerOfSize<64> { using U = std::uint64_t; using S = std::int64_t; };
|
||||
}
|
||||
template<size_t N> using UnsignedIntegerN = typename Detail::IntegerOfSize<N>::U;
|
||||
template<size_t N> using SignedIntegerN = typename Detail::IntegerOfSize<N>::S;
|
||||
|
||||
} // namespace Dynarmic::Common
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "dynarmic/common/common_types.h"
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include <numeric>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
#include "dynarmic/ir/acc_type.h"
|
||||
|
|
@ -2931,19 +2931,19 @@ public:
|
|||
}
|
||||
|
||||
void CallHostFunction(void (*fn)(void)) {
|
||||
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), Value{}, Value{}, Value{});
|
||||
Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), Value{}, Value{}, Value{});
|
||||
}
|
||||
|
||||
void CallHostFunction(void (*fn)(u64), const U64& arg1) {
|
||||
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), arg1, Value{}, Value{});
|
||||
Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, Value{}, Value{});
|
||||
}
|
||||
|
||||
void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) {
|
||||
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), arg1, arg2, Value{});
|
||||
Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, Value{});
|
||||
}
|
||||
|
||||
void CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3) {
|
||||
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), arg1, arg2, arg3);
|
||||
Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast<u64>(fn)), arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
void SetTerm(const Terminal& terminal) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <mcl/bit/swap.hpp>
|
||||
#include <mcl/macro/architecture.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "./A32/testenv.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue