backend/arm64: Implement Devirtualize
This commit is contained in:
parent
6239eb5eb6
commit
f3bf27c816
2 changed files with 41 additions and 0 deletions
|
@ -373,6 +373,7 @@ elseif(ARCHITECTURE STREQUAL "arm64")
|
|||
backend/arm64/a32_jitstate.h
|
||||
backend/arm64/abi.cpp
|
||||
backend/arm64/abi.h
|
||||
backend/arm64/devirtualize.h
|
||||
backend/arm64/emit_arm64.cpp
|
||||
backend/arm64/emit_arm64.h
|
||||
backend/arm64/emit_arm64_a32.cpp
|
||||
|
|
40
src/dynarmic/backend/arm64/devirtualize.h
Normal file
40
src/dynarmic/backend/arm64/devirtualize.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
namespace Dynarmic::Backend::Arm64 {
|
||||
|
||||
struct DevirtualizedCall {
|
||||
u64 fn_ptr;
|
||||
u64 this_ptr;
|
||||
};
|
||||
|
||||
template<auto mfp>
|
||||
DevirtualizedCall Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
|
||||
struct MemberFunctionPointer {
|
||||
// Address of non-virtual function or index into vtable.
|
||||
u64 ptr;
|
||||
// LSB is discriminator for if function is virtual. Other bits are this adjustment.
|
||||
u64 adj;
|
||||
} 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 = mcl::bit_cast<u64>(this_) + (mfp_struct.adj >> 1);
|
||||
if (mfp_struct.adj & 1) {
|
||||
u64 vtable = mcl::bit_cast_pointee<u64>(this_ptr);
|
||||
fn_ptr = mcl::bit_cast_pointee<u64>(vtable + fn_ptr);
|
||||
}
|
||||
return {fn_ptr, this_ptr};
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::Arm64
|
Loading…
Reference in a new issue