backend/arm64: Implement Devirtualize

This commit is contained in:
Merry 2022-07-24 11:50:04 +01:00 committed by merry
parent 6239eb5eb6
commit f3bf27c816
2 changed files with 41 additions and 0 deletions

View file

@ -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

View 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