mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-02 00:06:32 -05:00
48 lines
1.2 KiB
C++
48 lines
1.2 KiB
C++
|
// Copyright 2016 Citra Emulator Project
|
||
|
// Licensed under GPLv2 or any later version
|
||
|
// Refer to the license.txt file included.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <type_traits>
|
||
|
#include <xbyak.h>
|
||
|
#include "common/x64/xbyak_abi.h"
|
||
|
|
||
|
namespace Common::X64 {
|
||
|
|
||
|
// Constants for use with cmpps/cmpss
|
||
|
enum {
|
||
|
CMP_EQ = 0,
|
||
|
CMP_LT = 1,
|
||
|
CMP_LE = 2,
|
||
|
CMP_UNORD = 3,
|
||
|
CMP_NEQ = 4,
|
||
|
CMP_NLT = 5,
|
||
|
CMP_NLE = 6,
|
||
|
CMP_ORD = 7,
|
||
|
};
|
||
|
|
||
|
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) {
|
||
|
const u64 distance = target - (ref + 5);
|
||
|
return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
|
||
|
}
|
||
|
|
||
|
inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
|
||
|
return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
|
||
|
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
|
||
|
size_t addr = reinterpret_cast<size_t>(f);
|
||
|
if (IsWithin2G(code, addr)) {
|
||
|
code.call(f);
|
||
|
} else {
|
||
|
// ABI_RETURN is a safe temp register to use before a call
|
||
|
code.mov(ABI_RETURN, addr);
|
||
|
code.call(ABI_RETURN);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace Common::X64
|