xbyak_util.h 1.2 KB

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