xbyak_util.h 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. // SPDX-FileCopyrightText: 2016 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <type_traits>
  5. #include <xbyak/xbyak.h>
  6. #include "common/x64/xbyak_abi.h"
  7. namespace Common::X64 {
  8. // Constants for use with cmpps/cmpss
  9. enum {
  10. CMP_EQ = 0,
  11. CMP_LT = 1,
  12. CMP_LE = 2,
  13. CMP_UNORD = 3,
  14. CMP_NEQ = 4,
  15. CMP_NLT = 5,
  16. CMP_NLE = 6,
  17. CMP_ORD = 7,
  18. };
  19. constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) {
  20. const u64 distance = target - (ref + 5);
  21. return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
  22. }
  23. inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
  24. return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
  25. }
  26. template <typename T>
  27. inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
  28. static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
  29. size_t addr = reinterpret_cast<size_t>(f);
  30. if (IsWithin2G(code, addr)) {
  31. code.call(f);
  32. } else {
  33. // ABI_RETURN is a safe temp register to use before a call
  34. code.mov(ABI_RETURN, addr);
  35. code.call(ABI_RETURN);
  36. }
  37. }
  38. } // namespace Common::X64